-
+
+
{currentDatasourceCate && currentDatasource ? (
@@ -106,8 +110,8 @@ export default function AlertTable(props: IProps) {
-
- {_.map(record.tags, (item) => {
+
+ {_.map(visibleTags, (item) => {
return (
);
})}
+ {hiddenTagsCount > 0 && +{hiddenTagsCount}}
);
@@ -186,14 +191,14 @@ export default function AlertTable(props: IProps) {
{
title: t('common:table.operations'),
fixed: 'right' as const,
+ width: 64,
render(record) {
return (
-
+
{IS_PLUS && (
@@ -208,10 +213,8 @@ export default function AlertTable(props: IProps) {
)}
{!_.includes(['firemap', 'northstar'], record?.rule_prod) && (
-
+
)}
+ {(IS_PLUS || !_.includes(['firemap', 'northstar'], record?.rule_prod)) && }
-
+
}
>
- } />
+
);
diff --git a/src/pages/alertCurEvent/pages/List/index.tsx b/src/pages/alertCurEvent/pages/List/index.tsx
index 3cc49d98c..f273c5626 100644
--- a/src/pages/alertCurEvent/pages/List/index.tsx
+++ b/src/pages/alertCurEvent/pages/List/index.tsx
@@ -1,6 +1,7 @@
import React, { useContext, useState, useMemo, useEffect, useRef, useCallback } from 'react';
-import { Input, Checkbox, Collapse, Segmented, Button, Space, Row, Col } from 'antd';
+import { Input, Checkbox, Collapse, Segmented, Button, Space, Tooltip } from 'antd';
import { AlertOutlined, SearchOutlined } from '@ant-design/icons';
+import { ListChevronsDownUp, ListChevronsUpDown } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import _ from 'lodash';
import queryString from 'query-string';
@@ -109,6 +110,7 @@ const AlertCurEvent: React.FC = () => {
);
const [refreshFlag, setRefreshFlag] = useState
(_.uniqueId('refresh_'));
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
+ const [eventColumnExpanded, setEventColumnExpanded] = useState(false);
const params = getRequestParamsByFilter(filter);
type RuleCardsRequestParams = {
@@ -323,7 +325,20 @@ const AlertCurEvent: React.FC = () => {
}}
>
-
+
+
+
+ : }
+ onClick={() => {
+ setEventColumnExpanded(!eventColumnExpanded);
+ }}
+ />
+
+
@@ -381,6 +396,7 @@ const AlertCurEvent: React.FC = () => {
setSelectedRowKeys={setSelectedRowKeys}
params={params}
setRefreshFlag={setRefreshFlag}
+ eventColumnExpanded={eventColumnExpanded}
/>
diff --git a/src/pages/alertCurEvent/style.less b/src/pages/alertCurEvent/style.less
index c8bfcfaa4..c059a69cd 100644
--- a/src/pages/alertCurEvent/style.less
+++ b/src/pages/alertCurEvent/style.less
@@ -108,6 +108,75 @@
text-overflow: unset !important;
}
+ .alert-event-summary-toolbar {
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 8px;
+
+ > :first-child {
+ flex: 1;
+ min-width: 0;
+ }
+ }
+
+ .alert-event-expand-btn {
+ flex: none;
+ width: 28px;
+ height: 28px;
+ padding: 0;
+
+ .ant-btn-icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ }
+ }
+
+ .alert-event-content {
+ min-width: 0;
+ }
+
+ .alert-event-title {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+
+ .alert-event-tags {
+ display: flex;
+ gap: 4px;
+
+ &.is-expanded {
+ flex-wrap: wrap;
+ }
+
+ &.is-collapsed {
+ flex-wrap: nowrap;
+ overflow: hidden;
+ }
+
+ .ant-tag {
+ display: inline-flex;
+ align-items: center;
+ max-width: 240px;
+ margin-right: 0;
+ margin-bottom: 0;
+
+ > div {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+ }
+
+ .alert-event-more-tag {
+ flex: none;
+ color: var(--fc-text-3);
+ background: var(--fc-fill-2-5);
+ }
+ }
+
.ant-table table {
border-collapse: collapse !important;
@@ -123,4 +192,4 @@
border-left: 10px solid #23252b !important;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/pages/alertRules/List/ListNG.tsx b/src/pages/alertRules/List/ListNG.tsx
index 974e3da0e..dbd7c876a 100644
--- a/src/pages/alertRules/List/ListNG.tsx
+++ b/src/pages/alertRules/List/ListNG.tsx
@@ -1,25 +1,25 @@
import React, { useContext, useState, useEffect } from 'react';
-import { Space, Select, Input, Button, Table, Tooltip, Tag, Modal, Switch, message } from 'antd';
+import { Space, Select, Input, Button, Table, Tooltip, Tag, Modal, Switch, message, Dropdown, Menu } from 'antd';
import { ColumnType } from 'antd/lib/table';
-import { EyeOutlined, SearchOutlined, InfoCircleOutlined, WarningFilled, CheckCircleFilled } from '@ant-design/icons';
+import { EyeOutlined, SearchOutlined, InfoCircleOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import { useDebounceFn } from 'ahooks';
import _ from 'lodash';
import { Link } from 'react-router-dom';
import moment from 'moment';
+import { TriangleAlert, CircleCheckBig } from 'lucide-react';
import { CommonStateContext } from '@/App';
-import { priorityColor } from '@/utils/constant';
import { updateAlertRules, deleteStrategy } from '@/services/warning';
-import { allCates } from '@/components/AdvancedWrap/utils';
+import { allCates, getCateDisplayLabel } from '@/components/AdvancedWrap/utils';
import RefreshIcon from '@/components/RefreshIcon';
+import { TableActionButton, TableActionLink, TableActionTrigger } from '@/components/TableActionDropdown';
import DatasourceSelect from '@/components/DatasourceSelect/DatasourceSelect';
import OrganizeColumns, { getDefaultColumnsConfigs, setDefaultColumnsConfigs, ajustColumns } from '@/components/OrganizeColumns';
import usePagination from '@/components/usePagination';
-import Tags from '@/components/Tags';
+import Tags from '@/components/TableTags/Tags';
import localeCompare from '@/pages/dashboard/Renderer/utils/localeCompare';
import { getItems as getNotificationRules, RuleItem as NotificationRuleItem } from '@/pages/notificationRules/services';
-import { NS as notificationRulesNS } from '@/pages/notificationRules/constants';
import { AlertRuleType, AlertRuleStatus } from '@/pages/alertRules/types';
import { defaultColumnsConfigs, LOCAL_STORAGE_KEY } from '@/pages/alertRules/List/constants';
import EventsDrawer, { Props as EventsDrawerProps } from '@/pages/alertRules/List/EventsDrawer';
@@ -54,7 +54,7 @@ interface Props {
}
export default function AlertRules(props: Props) {
- const { t } = useTranslation('alertRules');
+ const { t, i18n } = useTranslation('alertRules');
const { busiGroups, datasourceList } = useContext(CommonStateContext);
const { hideBusinessGroupColumn, showRowSelection, readonly, headerExtra, data, loading, setRefreshFlag, linkTarget } = props;
let defaultFilter = {} as Filter;
@@ -92,13 +92,24 @@ export default function AlertRules(props: Props) {
),
dataIndex: 'cur_event_count',
+ width: 100,
sorter: (a, b) => {
return localeCompare(a.cur_event_count, b.cur_event_count);
},
render: (val, record) => {
return (
-
{
+ 0 ? 'var(--fc-red-3)' : 'var(--fc-green-3)'}
+ fontColor={val > 0 ? 'var(--fc-red-11)' : 'var(--fc-green-11)'}
+ borderRadius={6}
+ icon={() => {
+ if (val > 0) {
+ return ;
+ }
+ return ;
+ }}
+ onTagClick={() => {
setEventsDrawerProps({
...eventsDrawerProps,
visible: true,
@@ -106,60 +117,13 @@ export default function AlertRules(props: Props) {
rid: record.id,
});
}}
- style={{
- fontSize: 20,
- color: val > 0 ? '#e6522c' : '#00a700',
- }}
- >
- {val > 0 ? : }
-
+ data={[val > 0 ? t('status_triggered') : t('status_normal')]}
+ />
);
},
},
],
- hideBusinessGroupColumn
- ? []
- : ([
- {
- title: t('common:business_group'),
- dataIndex: 'group_id',
- render: (id) => {
- return _.find(busiGroups, { id })?.name;
- },
- },
- ] as any),
[
- {
- title: t('table.cate'),
- dataIndex: 'cate',
- render: (val) => {
- let logoSrc = _.find(allCates, { value: val })?.logo;
- if (val === 'host') {
- logoSrc = '/image/logos/host.png';
- }
- return

;
- },
- },
- {
- title: t('table.datasource_ids'),
- dataIndex: 'datasource_ids',
- render(value) {
- if (!value) return '';
- return (
-
{
- if (item === 0) return '$all';
- const name = _.find(datasourceList, { id: item })?.name;
- if (!name) return '';
- return name;
- }),
- )}
- />
- );
- },
- },
{
title: t('table.name'),
dataIndex: 'name',
@@ -167,16 +131,20 @@ export default function AlertRules(props: Props) {
return localeCompare(a.name, b.name);
},
render: (data, record) => {
+ const groupName = !hideBusinessGroupColumn ? _.find(busiGroups, { id: record.group_id })?.name : undefined;
return (
-
- {data}
-
+
+
+ {data}
+
+ {groupName && {groupName}}
+
);
},
},
@@ -185,27 +153,61 @@ export default function AlertRules(props: Props) {
dataIndex: 'severities',
render: (data) => {
return (
- `S${severity}`)}
+ bgColor={(tagname: string) => {
+ const bgColorMap: Record = {
+ S1: 'var(--fc-red-3)',
+ S2: 'var(--fc-orange-3)',
+ S3: 'var(--fc-yellow-3)',
+ };
+ return bgColorMap[tagname] || 'var(--fc-gray-3)';
}}
- >
- {_.map(data, (severity) => {
- return (
-
- S{severity}
-
- );
- })}
-
+ fontColor={(tagname: string) => {
+ const fontColorMap: Record = {
+ S1: 'var(--fc-red-11)',
+ S2: 'var(--fc-orange-11)',
+ S3: 'var(--fc-yellow-11)',
+ };
+ return fontColorMap[tagname] || 'var(--fc-gray-11)';
+ }}
+ />
+ );
+ },
+ },
+ {
+ title: t('table.datasource_ids'),
+ dataIndex: 'datasource_ids',
+ render(value, record) {
+ if (!value) return null;
+ const cate = _.find(allCates, { value: record.cate });
+ const cateLabel = record.cate === 'host' ? 'Host' : getCateDisplayLabel(cate, i18n.language);
+ let logoSrc = cate?.logo;
+ if (record.cate === 'host') {
+ logoSrc = '/image/logos/host.png';
+ }
+ return (
+
+ {logoSrc && (
+
+
+
+ )}
+ {
+ if (item === 0) return '$all';
+ const name = _.find(datasourceList, { id: item })?.name;
+ if (!name) return '';
+ return name;
+ }),
+ )}
+ />
+
);
},
},
@@ -213,55 +215,14 @@ export default function AlertRules(props: Props) {
title: t('table.append_tags'),
dataIndex: 'append_tags',
render(value) {
- return (
-
- {_.map(value, (item) => {
- return (
-
-
-
- {item}
-
-
-
- );
- })}
-
- );
+ return ;
},
},
{
title: t('table.notify_groups_obj'),
dataIndex: 'notify_groups_obj',
render: (data) => {
- return (
-
- {_.map(data, (user) => {
- const val = user.nickname || user.username || user.name;
- return (
-
-
-
- {val}
-
-
-
- );
- })}
-
- );
+ return user.nickname || user.username || user.name)} />;
},
},
{
@@ -269,48 +230,52 @@ export default function AlertRules(props: Props) {
dataIndex: 'notify_rule_ids',
render: (data) => {
return (
-
- {_.map(data, (id) => {
- const val = _.find(notificationRules, { id })?.name || id;
- return (
-
-
-
-
- {val}
-
-
-
-
- );
- })}
-
+
+ type='outline'
+ maxWidth={180}
+ data={data}
+ getKey={(id) => id}
+ getLabel={(id) => _.find(notificationRules, { id })?.name || _.toString(id)}
+ onTagClick={(id) => {
+ const finded = _.find(notificationRules, { id });
+ if (finded) {
+ window.open(`/notification-rules/edit/${id}`, '_blank');
+ } else {
+ message.warning(t('notify_rule_not_found'));
+ }
+ }}
+ />
);
},
},
{
title: t('table.update_at'),
dataIndex: 'update_at',
+ width: 100,
sorter: (a, b) => {
return a.update_at - b.update_at;
},
render: (text: string) => {
- return {moment.unix(Number(text)).format('YYYY-MM-DD HH:mm:ss')}
;
+ const m = moment.unix(Number(text));
+ return (
+
+
{m.format('YYYY-MM-DD')}
+
{m.format('HH:mm:ss')}
+
+ );
},
},
{
title: t('common:table.username'),
dataIndex: 'update_by',
- },
- {
- title: t('common:table.nickname'),
- dataIndex: 'update_by_nickname',
+ render: (val, record) => {
+ return (
+
+
{val}
+
{record.update_by_nickname}
+
+ );
+ },
},
],
readonly
@@ -355,48 +320,61 @@ export default function AlertRules(props: Props) {
{
title: t('common:table.operations'),
fixed: 'right',
+ width: 64,
render: (record: any) => {
const anomalyEnabled = _.get(record, ['rule_config', 'anomaly_trigger', 'enable']);
return (
-
-
- {t('common:btn.clone')}
-
-
- {record.cate === 'prometheus' && anomalyEnabled === true && (
-
- {t('brain_result_btn')}
-
- )}
-
+ onCancel() {},
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+
+ }
+ >
+
+
);
},
},
diff --git a/src/pages/alertRules/List/constants.ts b/src/pages/alertRules/List/constants.ts
index dac1b27d8..24196474d 100644
--- a/src/pages/alertRules/List/constants.ts
+++ b/src/pages/alertRules/List/constants.ts
@@ -24,16 +24,6 @@ export const defaultColumnsConfigs = [
i18nKey: 'table.status',
visible: true,
},
- {
- name: 'cate',
- i18nKey: 'table.cate',
- visible: true,
- },
- {
- name: 'datasource_ids',
- i18nKey: 'table.datasource_ids',
- visible: false,
- },
{
name: 'name',
i18nKey: 'table.name',
@@ -44,6 +34,11 @@ export const defaultColumnsConfigs = [
i18nKey: 'table.severity',
visible: false,
},
+ {
+ name: 'datasource_ids',
+ i18nKey: 'table.datasource_ids',
+ visible: false,
+ },
{
name: 'append_tags',
i18nKey: 'table.append_tags',
@@ -69,11 +64,6 @@ export const defaultColumnsConfigs = [
i18nKey: 'common:table.username',
visible: true,
},
- {
- name: 'update_by_nickname',
- i18nKey: 'common:table.nickname',
- visible: true,
- },
{
name: 'disabled',
i18nKey: 'table.disabled',
diff --git a/src/pages/alertRules/List/index.tsx b/src/pages/alertRules/List/index.tsx
index 245500e5f..45a7c4ef9 100644
--- a/src/pages/alertRules/List/index.tsx
+++ b/src/pages/alertRules/List/index.tsx
@@ -95,7 +95,7 @@ export default function List(props: ListProps) {
}, [gids, refreshFlag]);
return (
-
+
{
prod: string;
severities: number[];
update_at: number;
- update_by: number;
+ update_by: string;
+ update_by_nickname?: string;
cur_event_count: number;
}
diff --git a/src/pages/builtInComponents/AlertRules/index.tsx b/src/pages/builtInComponents/AlertRules/index.tsx
index c2fb266a1..c67cce56f 100644
--- a/src/pages/builtInComponents/AlertRules/index.tsx
+++ b/src/pages/builtInComponents/AlertRules/index.tsx
@@ -1,7 +1,7 @@
import React, { useState, useRef, useContext, useEffect } from 'react';
import _ from 'lodash';
import { Table, Space, Button, Input, Select, Dropdown, Menu, Modal, Tag, message } from 'antd';
-import { SearchOutlined, MoreOutlined } from '@ant-design/icons';
+import { SearchOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import { useDebounceEffect } from 'ahooks';
@@ -10,6 +10,8 @@ import Export from '@/pages/dashboard/List/Export';
import AuthorizationWrapper from '@/components/AuthorizationWrapper';
import { CommonStateContext } from '@/App';
import { HelpLink } from '@/components/pageLayout';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
+import Tags from '@/components/TableTags/Tags';
import { RuleType } from './types';
import Import from './Import';
import { getPayloads, deletePayloads, getCates } from '../services';
@@ -205,29 +207,17 @@ export default function index(props: Props) {
render: (val) => {
const tags = _.compact(_.split(val, ' '));
return (
-
- {_.map(tags, (tag, idx) => {
- return (
- {
- const queryItem = _.compact(_.split(filter.query, ' '));
- if (_.includes(queryItem, tag)) return;
- setFilter((filter) => {
- return {
- ...filter,
- query: filter.query ? filter.query + ' ' + tag : tag,
- };
- });
- }}
- >
- {tag}
-
- );
- })}
-
+ {
+ const queryItem = _.compact(_.split(filter.query, ' '));
+ if (_.includes(queryItem, tag)) return;
+ setFilter((filter) => ({
+ ...filter,
+ query: filter.query ? filter.query + ' ' + tag : tag,
+ }));
+ }}
+ />
);
},
},
@@ -245,14 +235,19 @@ export default function index(props: Props) {
},
{
title: t('common:table.operations'),
- width: 100,
+ width: 64,
+ fixed: 'right' as const,
render: (record) => {
return (
- {
Import({
data: formatBeautifyJson(record.content),
@@ -264,10 +259,11 @@ export default function index(props: Props) {
}}
>
{t('import_to_buisGroup')}
-
+
- {
Export({
data: formatBeautifyJson(record.content, 'array'),
@@ -275,12 +271,13 @@ export default function index(props: Props) {
}}
>
{t('common:btn.export')}
-
+
{record.updated_by !== 'system' && (
- {
PayloadFormModal({
darkMode,
@@ -297,38 +294,40 @@ export default function index(props: Props) {
}}
>
{t('common:btn.edit')}
-
+
)}
{record.updated_by !== 'system' && (
-
-
-
+ <>
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk() {
+ deletePayloads([record.id]).then(() => {
+ fetchData();
+ fetchCates();
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+ >
)}
}
>
- } />
+
);
},
diff --git a/src/pages/builtInComponents/CollectTpls/index.tsx b/src/pages/builtInComponents/CollectTpls/index.tsx
index 39f3d8792..c9044dd2a 100644
--- a/src/pages/builtInComponents/CollectTpls/index.tsx
+++ b/src/pages/builtInComponents/CollectTpls/index.tsx
@@ -1,13 +1,14 @@
import React, { useState, useRef, useContext, useEffect } from 'react';
import _ from 'lodash';
import { Table, Space, Button, Input, Dropdown, Menu, Modal, Tag } from 'antd';
-import { SearchOutlined, MoreOutlined } from '@ant-design/icons';
+import { SearchOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import { useDebounceEffect } from 'ahooks';
import { CommonStateContext } from '@/App';
import usePagination from '@/components/usePagination';
import AuthorizationWrapper from '@/components/AuthorizationWrapper';
import { HelpLink } from '@/components/pageLayout';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
import { getPayloads, deletePayloads, getCates } from '../services';
import { TypeEnum, Payload } from '../types';
import PayloadFormModal from '../components/PayloadFormModal';
@@ -153,14 +154,19 @@ export default function index(props: Props) {
},
{
title: t('common:table.operations'),
- width: 100,
+ width: 64,
+ fixed: 'right' as const,
render: (record) => {
return (
- {
GroupSelectModal({
busiGroups,
@@ -171,11 +177,12 @@ export default function index(props: Props) {
}}
>
{t('collect_create')}
-
+
- {
PayloadFormModal({
darkMode,
@@ -194,37 +201,39 @@ export default function index(props: Props) {
}}
>
{t('common:btn.edit')}
-
+
{record.updated_by !== 'system' && (
-
-
-
+ <>
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk() {
+ deletePayloads([record.id]).then(() => {
+ fetchData();
+ fetchCates();
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+ >
)}
}
>
- } />
+
);
},
diff --git a/src/pages/builtInComponents/Dashboards/index.tsx b/src/pages/builtInComponents/Dashboards/index.tsx
index d618a90e7..72e457180 100644
--- a/src/pages/builtInComponents/Dashboards/index.tsx
+++ b/src/pages/builtInComponents/Dashboards/index.tsx
@@ -2,7 +2,7 @@ import React, { useState, useRef, useContext } from 'react';
import _ from 'lodash';
import { Link } from 'react-router-dom';
import { Table, Space, Button, Input, Dropdown, Menu, Modal, Tag, message } from 'antd';
-import { SearchOutlined, MoreOutlined } from '@ant-design/icons';
+import { SearchOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import { useDebounceEffect } from 'ahooks';
import { CommonStateContext } from '@/App';
@@ -10,6 +10,8 @@ import usePagination from '@/components/usePagination';
import Export from '@/pages/dashboard/List/Export';
import AuthorizationWrapper from '@/components/AuthorizationWrapper';
import { HelpLink } from '@/components/pageLayout';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
+import Tags from '@/components/TableTags/Tags';
import { getPayloads, deletePayloads } from '../services';
import { TypeEnum, Payload } from '../types';
import PayloadFormModal from '../components/PayloadFormModal';
@@ -160,29 +162,17 @@ export default function index(props: Props) {
render: (val) => {
const tags = _.compact(_.split(val, ' '));
return (
-
- {_.map(tags, (tag, idx) => {
- return (
- {
- const queryItem = _.compact(_.split(filter.query, ' '));
- if (_.includes(queryItem, tag)) return;
- setFilter((filter) => {
- return {
- ...filter,
- query: filter.query ? filter.query + ' ' + tag : tag,
- };
- });
- }}
- >
- {tag}
-
- );
- })}
-
+ {
+ const queryItem = _.compact(_.split(filter.query, ' '));
+ if (_.includes(queryItem, tag)) return;
+ setFilter((filter) => ({
+ ...filter,
+ query: filter.query ? filter.query + ' ' + tag : tag,
+ }));
+ }}
+ />
);
},
},
@@ -205,14 +195,19 @@ export default function index(props: Props) {
},
{
title: t('common:table.operations'),
- width: 100,
+ width: 64,
+ fixed: 'right' as const,
render: (record) => {
return (
- {
Import({
data: formatBeautifyJson(record.content),
@@ -221,10 +216,11 @@ export default function index(props: Props) {
}}
>
{t('import_to_buisGroup')}
-
+
- {
Export({
data: formatBeautifyJson(record.content, 'array'),
@@ -232,12 +228,13 @@ export default function index(props: Props) {
}}
>
{t('common:btn.export')}
-
+
{record.updated_by !== 'system' && (
- {
PayloadFormModal({
darkMode,
@@ -252,37 +249,39 @@ export default function index(props: Props) {
}}
>
{t('common:btn.edit')}
-
+
)}
{record.updated_by !== 'system' && (
-
-
-
+ <>
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk() {
+ deletePayloads([record.id]).then(() => {
+ fetchData();
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+ >
)}
}
>
- } />
+
);
},
diff --git a/src/pages/builtInComponents/Metrics/index.tsx b/src/pages/builtInComponents/Metrics/index.tsx
index ce9098c21..0a25c65d1 100644
--- a/src/pages/builtInComponents/Metrics/index.tsx
+++ b/src/pages/builtInComponents/Metrics/index.tsx
@@ -19,7 +19,7 @@ import _ from 'lodash';
import { useAntdTable, useDebounceFn } from 'ahooks';
import { useTranslation } from 'react-i18next';
import { Space, Table, Button, Input, Dropdown, Select, message, Modal, Tooltip, Menu, Tag } from 'antd';
-import { DownOutlined, SearchOutlined, EyeOutlined, MoreOutlined } from '@ant-design/icons';
+import { DownOutlined, SearchOutlined, EyeOutlined } from '@ant-design/icons';
import { ColumnType } from 'antd/lib/table';
import usePagination from '@/components/usePagination';
import RefreshIcon from '@/components/RefreshIcon';
@@ -33,6 +33,7 @@ import FormModal from './components/FormModal';
import Export from '@/pages/metricsBuiltin/components/Export';
import Import from '@/pages/metricsBuiltin/components/Import';
import { HelpLink } from '@/components/pageLayout';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
interface Props {
component: string;
@@ -142,9 +143,14 @@ export default function index(props: Props) {
{
title: t('common:table.operations'),
dataIndex: 'operator',
+ width: 64,
+ fixed: 'right' as const,
render: (data, record: any) => {
return (
{actionAuth.add && (
@@ -159,7 +165,7 @@ export default function index(props: Props) {
setRefreshFlag(_.uniqueId('refreshFlag_'));
}}
>
- {t('common:btn.clone')}
+ {t('common:btn.clone')}
)}
@@ -175,36 +181,38 @@ export default function index(props: Props) {
setRefreshFlag(_.uniqueId('refreshFlag_'));
}}
>
- {t('common:btn.edit')}
+ {t('common:btn.edit')}
)}
{actionAuth.delete && record.updated_by !== 'system' && (
-
-
-
+ <>
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk() {
+ deleteMetrics([record.id]).then(() => {
+ message.success(t('common:success.delete'));
+ setRefreshFlag(_.uniqueId('refreshFlag_'));
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+ >
)}
}
>
- } />
+
);
},
diff --git a/src/pages/dashboard/List/constants.ts b/src/pages/dashboard/List/constants.ts
index d4d88ba61..00b7a4e01 100644
--- a/src/pages/dashboard/List/constants.ts
+++ b/src/pages/dashboard/List/constants.ts
@@ -41,11 +41,6 @@ export const defaultColumnsConfigs = [
i18nKey: 'common:table.username',
visible: false,
},
- {
- name: 'update_by_nickname',
- i18nKey: 'common:table.nickname',
- visible: false,
- },
{
name: 'public',
i18nKey: 'public.name',
diff --git a/src/pages/dashboard/List/index.tsx b/src/pages/dashboard/List/index.tsx
index 0918dbabd..3abf69ea9 100644
--- a/src/pages/dashboard/List/index.tsx
+++ b/src/pages/dashboard/List/index.tsx
@@ -19,8 +19,8 @@
*/
import React, { useState, useEffect, useContext } from 'react';
import { Link } from 'react-router-dom';
-import { Table, Tag, Modal, Space, Button, Dropdown, Menu, message, Tooltip } from 'antd';
-import { FundViewOutlined, EditOutlined, ShareAltOutlined, MoreOutlined } from '@ant-design/icons';
+import { Table, Modal, Space, Dropdown, Menu, message, Tooltip } from 'antd';
+import { FundViewOutlined, EditOutlined, ShareAltOutlined } from '@ant-design/icons';
import moment from 'moment';
import _ from 'lodash';
import { useTranslation } from 'react-i18next';
@@ -33,6 +33,8 @@ import { getBusiGroupsDashboards, getBusiGroupsPublicDashboards, cloneDashboard,
import PageLayout from '@/components/pageLayout';
import { CommonStateContext } from '@/App';
import BusinessGroupSideBarWithAll, { getDefaultGidsInDashboard } from '@/components/BusinessGroup/BusinessGroupSideBarWithAll';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
+import Tags from '@/components/TableTags/Tags';
import usePagination from '@/components/usePagination';
import { getDefaultColumnsConfigs, ajustColumns } from '@/components/OrganizeColumns';
import { getBusiGroups } from '@/components/BusinessGroup';
@@ -143,26 +145,15 @@ export default function index() {
className='mt-2'
dataSource={data}
columns={ajustColumns(
- _.concat(
- businessGroup.isLeaf && gids !== '-1' && gids !== '-2'
- ? []
- : ([
- {
- title: t('common:business_group'),
- dataIndex: 'group_id',
- width: 100,
- render: (id) => {
- return _.find(busiGroups, { id })?.name;
- },
- },
- ] as any),
- [
- {
- title: t('name'),
- dataIndex: 'name',
- className: 'name-column',
- render: (text: string, record: DashboardType) => {
- return (
+ _.concat([
+ {
+ title: t('name'),
+ dataIndex: 'name',
+ className: 'name-column',
+ render: (text: string, record: DashboardType) => {
+ const groupName = _.find(busiGroups, { id: record.group_id })?.name;
+ return (
+
{text}
- );
- },
+ {groupName && {groupName}}
+
+ );
},
- {
- title: t('tags'),
- dataIndex: 'tags',
- className: 'tags-column',
- render: (text: string) => (
- <>
- {_.map(_.split(text, ' '), (tag, index) => {
- return tag ? (
- {
- const queryItem = searchVal.length > 0 ? searchVal.split(' ') : [];
- if (queryItem.includes(tag)) return;
- setsearchVal((searchVal) => {
- if (searchVal) {
- sessionStorage.setItem(SEARCH_SESSION_STORAGE_KEY, searchVal + ' ' + tag);
- return searchVal + ' ' + tag;
- }
- sessionStorage.setItem(SEARCH_SESSION_STORAGE_KEY, tag);
- return tag;
- });
- }}
- >
- {tag}
-
- ) : null;
- })}
- >
- ),
- },
- {
- title: t('common:table.note'),
- dataIndex: 'note',
- className: 'note-column',
- },
- {
- title: t('common:table.update_at'),
- width: 150,
- dataIndex: 'update_at',
- render: (text: number) => moment.unix(text).format('YYYY-MM-DD HH:mm:ss'),
- },
- {
- title: t('common:table.username'),
- dataIndex: 'update_by',
- width: 100,
- },
- {
- title: t('common:table.nickname'),
- dataIndex: 'update_by_nickname',
- width: 100,
+ },
+ {
+ title: t('tags'),
+ dataIndex: 'tags',
+ className: 'tags-column',
+ render: (text: string) => (
+ {
+ const queryItem = searchVal.length > 0 ? searchVal.split(' ') : [];
+ if (queryItem.includes(tag)) return;
+ setsearchVal((searchVal) => {
+ if (searchVal) {
+ sessionStorage.setItem(SEARCH_SESSION_STORAGE_KEY, searchVal + ' ' + tag);
+ return searchVal + ' ' + tag;
+ }
+ sessionStorage.setItem(SEARCH_SESSION_STORAGE_KEY, tag);
+ return tag;
+ });
+ }}
+ />
+ ),
+ },
+ {
+ title: t('common:table.note'),
+ dataIndex: 'note',
+ className: 'note-column',
+ },
+ {
+ title: t('common:table.update_at'),
+ width: 100,
+ dataIndex: 'update_at',
+ render: (text: number) => {
+ return (
+
+
{moment.unix(text).format('YYYY-MM-DD')}
+
{moment.unix(text).format('HH:mm:ss')}
+
+ );
},
- {
- title: t('public.name'),
- width: 150,
- dataIndex: 'public',
- className: 'published-cell',
- render: (val: number, record: DashboardType) => {
- let content: React.ReactNode = null;
- if (val === 1 && record.public_cate !== undefined) {
- if (record.public_cate === 0) {
- content = (
-
-
-
- {t('public.theme_link.dark')}
-
-
-
-
- {t('public.theme_link.light')}
-
-
- >
- }
+ },
+ {
+ title: t('common:table.username'),
+ dataIndex: 'update_by',
+ render: (val: string, record: any) => (
+
+
{val}
+ {record.update_by_nickname &&
{record.update_by_nickname}
}
+
+ ),
+ },
+ {
+ title: t('public.name'),
+ width: 150,
+ dataIndex: 'public',
+ className: 'published-cell',
+ render: (val: number, record: DashboardType) => {
+ let content: React.ReactNode = null;
+ if (val === 1 && record.public_cate !== undefined) {
+ if (record.public_cate === 0) {
+ content = (
+
+
+
+ {t('public.theme_link.dark')}
+
+
+
+
+ {t('public.theme_link.light')}
+
+
+ >
+ }
+ >
+
-
- {t(`public.cate.${record.public_cate}`)}
-
-
- );
- } else {
- content = t(`public.cate.${record.public_cate}`);
- }
+ {t(`public.cate.${record.public_cate}`)}
+
+
+ );
} else {
- content = t('public.unpublic');
+ content = t(`public.cate.${record.public_cate}`);
}
+ } else {
+ content = t('public.unpublic');
+ }
- return (
-
- {content}
- {gids !== '-1' && (
- {
- PublicForm({
- busiGroups,
- boardId: record.id,
- initialValues: {
- public: val,
- public_cate: record.public_cate,
- bgids: record.bgids,
- },
- onOk: () => {
- setRefreshKey(_.uniqueId('refreshKey_'));
- },
- });
- }}
- />
- )}
-
- );
- },
+ return (
+
+ {content}
+ {gids !== '-1' && (
+ {
+ PublicForm({
+ busiGroups,
+ boardId: record.id,
+ initialValues: {
+ public: val,
+ public_cate: record.public_cate,
+ bgids: record.bgids,
+ },
+ onOk: () => {
+ setRefreshKey(_.uniqueId('refreshKey_'));
+ },
+ });
+ }}
+ />
+ )}
+
+ );
},
- {
- title: t('common:table.operations'),
- render: (text: string, record: DashboardType) => {
- return (
-
- {gids !== '-1' && (
-
-
-
- )}
- {gids && gids !== '-1' && (
-
-
-
- )}
+ },
+ {
+ title: t('common:table.operations'),
+ width: 64,
+ fixed: 'right' as const,
+ render: (text: string, record: DashboardType) => {
+ return (
+
+ {gids !== '-1' && (
-
+ )}
+ {gids && gids !== '-1' && (
+
+ {
- const exportData = await getDashboard(record.id);
- Export({
- data: exportDataStringify(exportData),
+ Modal.confirm({
+ title: t('common:confirm.clone'),
+ onOk: async () => {
+ await cloneDashboard(record.group_id, record.id);
+ message.success(t('common:success.clone'));
+ setRefreshKey(_.uniqueId('refreshKey_'));
+ },
+
+ onCancel() {},
});
}}
>
- {t('common:btn.export')}
-
+ {t('common:btn.clone')}
+
- {gids !== '-1' && (
+ )}
+
+ {
+ const exportData = await getDashboard(record.id);
+ Export({
+ data: exportDataStringify(exportData),
+ });
+ }}
+ >
+ {t('common:btn.export')}
+
+
+ {gids !== '-1' && (
+ <>
+
-
+
- )}
-
- }
- >
- } />
-
- );
- },
+ >
+ )}
+
+ }
+ >
+
+
+ );
},
- ],
- ),
+ },
+ ]),
columnsConfigs,
)}
rowKey='id'
diff --git a/src/pages/datasource/components/TableSource/index.tsx b/src/pages/datasource/components/TableSource/index.tsx
index 67920d589..dbf9451aa 100644
--- a/src/pages/datasource/components/TableSource/index.tsx
+++ b/src/pages/datasource/components/TableSource/index.tsx
@@ -3,7 +3,7 @@ import _ from 'lodash';
import { useTranslation } from 'react-i18next';
import { message, Table, Modal, Button, Space, Popconfirm, Tooltip, Dropdown, Menu } from 'antd';
import { ColumnProps } from 'antd/es/table';
-import { CheckCircleFilled, MinusCircleFilled, WarningOutlined, MoreOutlined } from '@ant-design/icons';
+import { CheckCircleFilled, MinusCircleFilled, WarningOutlined } from '@ant-design/icons';
import { CommonStateContext } from '@/App';
import usePagination from '@/components/usePagination';
import { allCates } from '@/components/AdvancedWrap/utils';
@@ -11,6 +11,7 @@ import localeCompare from '@/pages/dashboard/Renderer/utils/localeCompare';
import Rename from '../Rename';
import { deleteDataSourceById, getDataSourceList, updateDataSourceStatus, getServerClusters } from '../../services';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
// @ts-ignore
import { autoDatasourcetype, AuthList, AutoDatasourcetypeValue } from 'plus:/components/DataSourceAuth/auth';
// @ts-ignore
@@ -191,61 +192,67 @@ const TableSource = (props: IPropsType) => {
{
title: t('common:table.operations'),
- width: 100,
+ width: 64,
+ fixed: 'right' as const,
render: (record) => {
return (
-
- {
- updateDataSourceStatus({
- id: record.id,
- status: record.status === 'enabled' ? 'disabled' : 'enabled',
- }).then(() => {
- message.success(record.status === 'enabled' ? t('success.disable') : t('success.enable'));
- setRefresh((oldVal) => !oldVal);
- });
- }}
- >
- {record.status === 'enabled' ? t('disable') : t('enable')}
-
-
- {record.status === 'disabled' && (
-
- )}
-
- {record.plugin_type === 'cloudwatch' && (
-
+ }}
+ >
+ {record.status === 'enabled' ? t('disable') : t('enable')}
+
+
+ {record.plugin_type === 'cloudwatch' && (
+
+
+
+ )}
+ {record.status === 'disabled' && (
+ <>
+
-
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk() {
+ deleteDataSourceById(record.id).then(() => {
+ message.success(t('common:success.delete'));
+ setRefresh((oldVal) => !oldVal);
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
-
- }
- >
- } />
-
- )}
-
+ >
+ )}
+
+ }
+ >
+
+
);
},
},
diff --git a/src/pages/embeddedProduct/pages/List/index.tsx b/src/pages/embeddedProduct/pages/List/index.tsx
index 3209308b5..08b634167 100644
--- a/src/pages/embeddedProduct/pages/List/index.tsx
+++ b/src/pages/embeddedProduct/pages/List/index.tsx
@@ -1,7 +1,7 @@
import React, { useEffect, useMemo, useState } from 'react';
import _ from 'lodash';
import moment from 'moment';
-import { Space, Table, Button, Modal, Tag, message, Switch } from 'antd';
+import { Space, Table, Button, Modal, Tag, message, Switch, Dropdown, Menu } from 'antd';
import { ColumnType } from 'antd/lib/table';
import { MenuOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
@@ -12,17 +12,12 @@ import { arrayMoveImmutable } from 'array-move';
import { getTeamInfoList } from '@/services/manage';
import PageLayout from '@/components/pageLayout';
import { eventBus, EVENT_KEYS } from '@/pages/embeddedProduct/eventBus';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
+import Tags from '@/components/TableTags/Tags';
import { NS, DETAIL_PATH } from '../../constants';
import { EmbeddedProductParams, EmbeddedProductResponse } from '../../types';
-import {
- getEmbeddedProducts,
- addEmbeddedProducts,
- updateEmbeddedProducts,
- putEmbeddedProductsWeights,
- deleteEmbeddedProducts,
- putEmbeddedProductHide,
-} from '../../services';
+import { getEmbeddedProducts, addEmbeddedProducts, updateEmbeddedProducts, putEmbeddedProductsWeights, deleteEmbeddedProducts, putEmbeddedProductHide } from '../../services';
import EmbeddedProductModal from '../../components/EmbeddedProductModal';
import './style.less';
@@ -70,10 +65,7 @@ export default function Index() {
title: t('team_ids'),
dataIndex: 'team_ids',
render: (val) => {
- return _.map(val, (item) => {
- const name = _.find(userGroups, { id: item })?.name;
- return {name || item};
- });
+ return data={val} maxWidth={320} getKey={(item) => item} getLabel={(item) => _.find(userGroups, { id: item })?.name || String(item)} />;
},
},
{
@@ -132,38 +124,53 @@ export default function Index() {
{
title: t('common:table.operations'),
dataIndex: 'operator',
- width: 120,
+ width: 64,
+ fixed: 'right' as const,
render: (_val, record: EmbeddedProductResponse) => {
return (
-
- {
- e.preventDefault();
- setCurrentRecord(record);
- setModalVisible(true);
- }}
- >
- {t('common:btn.edit')}
-
- {
- e.preventDefault();
- Modal.confirm({
- title: t('common:confirm.delete'),
- onOk: () => {
- return deleteEmbeddedProducts(String(record.id)).then(() => {
- message.success(t('common:success.delete'));
- fetchData();
- eventBus.emit(EVENT_KEYS.EMBEDDED_PRODUCT_UPDATED);
- });
- },
- });
- }}
- >
- {t('common:btn.delete')}
-
-
+
+
+ {
+ setCurrentRecord(record);
+ setModalVisible(true);
+ }}
+ >
+ {t('common:btn.edit')}
+
+
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk: () => {
+ return deleteEmbeddedProducts(String(record.id)).then(() => {
+ message.success(t('common:success.delete'));
+ fetchData();
+ eventBus.emit(EVENT_KEYS.EMBEDDED_PRODUCT_UPDATED);
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+
+ }
+ >
+
+
);
},
},
diff --git a/src/pages/event/Table.tsx b/src/pages/event/Table.tsx
index 79771335e..2ce8bfa8d 100644
--- a/src/pages/event/Table.tsx
+++ b/src/pages/event/Table.tsx
@@ -17,7 +17,6 @@
import React, { useState, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { Tag, Button, Table, Tooltip, Dropdown, Menu } from 'antd';
-import { MoreOutlined } from '@ant-design/icons';
import { useHistory, Link } from 'react-router-dom';
import moment from 'moment';
import _ from 'lodash';
@@ -28,6 +27,7 @@ import { parseRange } from '@/components/TimeRangePicker';
import { getEvents } from './services';
import { deleteAlertEventsModal } from './index';
import { SeverityColor } from './index';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
// @ts-ignore
import AckBtn from 'plus:/parcels/Event/Acknowledge/AckBtn';
@@ -130,10 +130,14 @@ export default function TableCpt(props: IProps) {
{
title: t('common:table.operations'),
dataIndex: 'operate',
- width: 80,
+ width: 64,
+ fixed: 'right' as const,
render(value, record) {
return (
@@ -146,10 +150,8 @@ export default function TableCpt(props: IProps) {
{!_.includes(['firemap', 'northstar'], record?.rule_prod) && (
-
+
)}
+
-
+
}
>
- } />
+
);
},
diff --git a/src/pages/event/card.tsx b/src/pages/event/card.tsx
index 057d426fe..078a3a065 100644
--- a/src/pages/event/card.tsx
+++ b/src/pages/event/card.tsx
@@ -1,6 +1,5 @@
import React, { useEffect, useState, useLayoutEffect, useRef, useImperativeHandle, useContext } from 'react';
import { Button, Row, Col, Drawer, Tag, Table, Dropdown, Menu, Tooltip } from 'antd';
-import { MoreOutlined } from '@ant-design/icons';
import { useHistory, Link } from 'react-router-dom';
import { ReactNode } from 'react-markdown/lib/react-markdown';
import _, { throttle } from 'lodash';
@@ -14,6 +13,7 @@ import { parseRange } from '@/components/TimeRangePicker';
import { SeverityColor, deleteAlertEventsModal } from './index';
import CardLeft from './cardLeft';
import './index.less';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
// @ts-ignore
import BatchAckBtn from 'plus:/parcels/Event/Acknowledge/BatchAckBtn';
@@ -171,10 +171,14 @@ function Card(props: Props, ref) {
{
title: t('common:table.operations'),
dataIndex: 'operate',
- width: 80,
+ width: 64,
+ fixed: 'right' as const,
render(value, record) {
return (
@@ -187,10 +191,8 @@ function Card(props: Props, ref) {
{!_.includes(['firemap', 'northstar'], record?.rule_prod) && (
-
+
)}
+
-
+
}
>
- } />
+
);
},
diff --git a/src/pages/eventPipeline/pages/Executions/index.tsx b/src/pages/eventPipeline/pages/Executions/index.tsx
index 1f85eea76..7f8bdeab2 100644
--- a/src/pages/eventPipeline/pages/Executions/index.tsx
+++ b/src/pages/eventPipeline/pages/Executions/index.tsx
@@ -1,12 +1,13 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { Input, Space, Select, Table, Tag } from 'antd';
+import { Input, Space, Select, Table } from 'antd';
import { useAntdTable } from 'ahooks';
import _ from 'lodash';
import moment from 'moment';
import { useLocation } from 'react-router-dom';
import queryString from 'query-string';
+import Tags from '@/components/TableTags/Tags';
import PageLayout from '@/components/pageLayout';
import AutoRefresh from '@/components/TimeRangePicker/AutoRefresh';
@@ -47,12 +48,6 @@ export default function index() {
defaultPageSize,
});
- const statusMap = {
- running: {t('executions.status.running')},
- success: {t('executions.status.success')},
- failed: {t('executions.status.failed')},
- };
-
const [itemDetailDrawerState, setItemDetailDrawerState] = useState<{
id: string | null;
visible: boolean;
@@ -152,7 +147,7 @@ export default function index() {
key: 'mode',
width: 100,
render: (value) => {
- return {t(`trigger_mode.${value}`)};
+ return 'var(--fc-green-3)'} fontColor={() => 'var(--fc-green-11)'} />;
},
},
{
@@ -161,7 +156,24 @@ export default function index() {
key: 'status',
width: 100,
render: (value) => {
- return statusMap[value] || value;
+ const bgColorMap = {
+ running: 'var(--fc-purple-3)',
+ success: 'var(--fc-green-3)',
+ failed: 'var(--fc-red-3)',
+ };
+ const fontColorMap = {
+ running: 'var(--fc-purple-11)',
+ success: 'var(--fc-green-11)',
+ failed: 'var(--fc-red-11)',
+ };
+ return (
+ bgColorMap[value as string] || 'var(--fc-gray-3)'}
+ fontColor={() => fontColorMap[value as string] || 'var(--fc-gray-11)'}
+ />
+ );
},
},
{
diff --git a/src/pages/eventPipeline/pages/List/index.tsx b/src/pages/eventPipeline/pages/List/index.tsx
index 9b8bfad13..a12d74e32 100644
--- a/src/pages/eventPipeline/pages/List/index.tsx
+++ b/src/pages/eventPipeline/pages/List/index.tsx
@@ -1,10 +1,9 @@
import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
-import { Space, Table, Button, Tag, Input, Modal, Drawer, Select } from 'antd';
+import { Space, Table, Button, Input, Modal, Drawer, Select, Dropdown, Menu } from 'antd';
import { SearchOutlined } from '@ant-design/icons';
import moment from 'moment';
import _ from 'lodash';
-import { Link } from 'react-router-dom';
import usePagination from '@/components/usePagination';
@@ -13,6 +12,8 @@ import { Item, getList, deleteItems } from '../../services';
import Add from '../Add';
import Edit from '../Edit';
import MoreOperations from './MoreOperations';
+import { TableActionButton, TableActionLink, TableActionTrigger } from '@/components/TableActionDropdown';
+import Tags from '@/components/TableTags/Tags';
export default function List() {
const { t } = useTranslation(NS);
@@ -66,11 +67,6 @@ export default function List() {
featchData();
}, []);
- const disabledMap = {
- false: {t('disabled.false')},
- true: {t('disabled.true')},
- };
-
return (
<>
@@ -185,7 +181,7 @@ export default function List() {
dataIndex: 'use_case',
width: 100,
render: (value) => {
- return
{t(`use_case.${value}`)};
+ return
;
},
},
{
@@ -193,7 +189,7 @@ export default function List() {
dataIndex: 'trigger_mode',
width: 100,
render: (value) => {
- return
{t(`trigger_mode.${value}`)};
+ return
;
},
},
{
@@ -202,79 +198,115 @@ export default function List() {
key: 'disabled',
width: 100,
render: (value) => {
- return disabledMap[value] || value;
+ return (
+
(value === false ? 'var(--fc-green-3)' : 'var(--fc-red-3)')}
+ fontColor={() => (value === false ? 'var(--fc-green-11)' : 'var(--fc-red-11)')}
+ />
+ );
},
},
{
title: t('teams'),
dataIndex: 'team_names',
render: (val) => {
- return _.map(val, (item) => {
- return {item};
- });
+ return ;
},
},
{
title: t('common:table.update_by'),
dataIndex: 'update_by',
+ render: (val, record: any) => (
+
+
{val}
+ {record.update_by_nickname &&
{record.update_by_nickname}
}
+
+ ),
},
{
title: t('common:table.update_at'),
dataIndex: 'update_at',
render: (val) => {
- return moment.unix(val).format('YYYY-MM-DD HH:mm:ss');
+ const m = moment.unix(val);
+ return (
+
+
{m.format('YYYY-MM-DD')}
+
{m.format('HH:mm:ss')}
+
+ );
},
},
{
title: t('common:table.operations'),
- width: 200,
+ width: 64,
+ fixed: 'right' as const,
render: (item: Item) => {
return (
-
- {
- setEventPipelineDrawerState({
- visible: true,
- action: 'clone',
- data: _.omit(item, 'id'),
- });
- }}
- >
- {t('common:btn.clone')}
-
- {
- setEventPipelineDrawerState({
- visible: true,
- action: 'edit',
- id: item.id,
- });
- }}
- >
- {t('common:btn.edit')}
-
-
- {t('executions.title')}
-
+
+
+ {
+ setEventPipelineDrawerState({
+ visible: true,
+ action: 'clone',
+ data: _.omit(item, 'id'),
+ });
+ }}
+ >
+ {t('common:btn.clone')}
+
+
+
+ {
+ setEventPipelineDrawerState({
+ visible: true,
+ action: 'edit',
+ id: item.id,
+ });
+ }}
+ >
+ {t('common:btn.edit')}
+
+
+
+
+ {t('executions.title')}
+
+
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk: () => {
+ deleteItems([item.id]).then(() => {
+ featchData();
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+
+ }
+ >
+
+
);
},
},
diff --git a/src/pages/historyEvents/ListNG/index.tsx b/src/pages/historyEvents/ListNG/index.tsx
index fba35297d..ca0c396f5 100644
--- a/src/pages/historyEvents/ListNG/index.tsx
+++ b/src/pages/historyEvents/ListNG/index.tsx
@@ -1,5 +1,5 @@
import React, { useContext, useState } from 'react';
-import { SearchOutlined, MoreOutlined } from '@ant-design/icons';
+import { SearchOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import moment from 'moment';
import _ from 'lodash';
@@ -21,6 +21,7 @@ import EventDetailDrawer from '@/pages/alertCurEvent/pages/List/EventDetailDrawe
import usePagination from '@/components/usePagination';
import { getEventById } from '@/pages/alertCurEvent/services';
import deleteAlertEventsModal from '@/pages/alertCurEvent/utils/deleteAlertEventsModal';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
import exportEvents, { downloadFile } from '../exportEvents';
import { SeverityColor } from '../../event';
@@ -184,14 +185,14 @@ const Event = (props: Props) => {
{
title: t('common:table.operations'),
fixed: 'right' as const,
+ width: 64,
render(record) {
return (
-
+
{IS_PLUS && (
@@ -206,10 +207,8 @@ const Event = (props: Props) => {
)}
{!_.includes(['firemap', 'northstar'], record?.rule_prod) && (
-
+
)}
{!hideDeleteEventButton && (
-
-
-
+ <>
+
+
+
+ deleteAlertEventsModal(
+ [record.id],
+ () => {
+ setRefreshFlag(_.uniqueId('refresh_'));
+ },
+ t,
+ )
+ }
+ >
+ {t('common:btn.delete')}
+
+
+ >
)}
}
>
- } />
+
);
diff --git a/src/pages/hosts/pages/List/List.tsx b/src/pages/hosts/pages/List/List.tsx
index 56bb3683a..62959c9a5 100644
--- a/src/pages/hosts/pages/List/List.tsx
+++ b/src/pages/hosts/pages/List/List.tsx
@@ -14,6 +14,7 @@ import { copy2ClipBoard } from '@/utils';
import getTextWidth from '@/utils/getTextWidth';
import usePagination from '@/components/usePagination';
import DocumentDrawer from '@/components/DocumentDrawer';
+import Tags from '@/components/TableTags/Tags';
import HostsSelect from '@/pages/targets/components/HostsSelect';
import Explorer from '@/pages/targets/components/Explorer';
import EditBusinessGroups from '@/pages/targets/components/EditBusinessGroups';
@@ -31,7 +32,6 @@ import { NS } from '../../constants';
import { Item, OperateType } from '../../types';
import { getList } from '../../services';
import VersionIcon from './VersionIcon';
-import Tags from './Tags';
import { formatBeatTimeDisplay } from './formatBeatTimeDisplay';
const downtimeOptions = [1, 2, 3, 5, 10, 30];
@@ -527,7 +527,7 @@ export default function List(props: Props) {
{
if (!_.includes(params.query, tag)) {
const val = params.query ? `${params.query.trim()} ${tag}` : tag;
@@ -560,7 +560,7 @@ export default function List(props: Props) {
{
if (!_.includes(params.query, tag)) {
const val = params.query ? `${params.query.trim()} ${tag}` : tag;
@@ -584,7 +584,7 @@ export default function List(props: Props) {
}
return (
-
+
);
},
diff --git a/src/pages/hosts/pages/List/Tags.tsx b/src/pages/hosts/pages/List/Tags.tsx
deleted file mode 100644
index 6a6f11ea0..000000000
--- a/src/pages/hosts/pages/List/Tags.tsx
+++ /dev/null
@@ -1,211 +0,0 @@
-import React, { useRef, useState, useLayoutEffect } from 'react';
-import { Button, Popover } from 'antd';
-import { CopyOutlined } from '@ant-design/icons';
-import { Trans } from 'react-i18next';
-
-import { copy2ClipBoard } from '@/utils';
-
-import { NS } from '../../constants';
-
-interface Props {
- type: 'outline' | 'fill';
- bgColor?: string; // 背景颜色,仅在 type 为 'fill' 时生效
- fontColor?: string; // 字体颜色,仅在 type 为 'fill' 时生效
- data: string[];
- onTagClick?: (tag: string) => void;
-}
-
-const GAP = 2;
-
-/**
- * 核心布局算法:根据实际测量的 tag 宽度计算可见数量
- */
-function calcLayout(tagWidths: number[], overflowTagWidth: number, containerWidth: number): { visibleCount: number; overflowCount: number } {
- if (!tagWidths.length || containerWidth <= 0) {
- return { visibleCount: tagWidths.length, overflowCount: 0 };
- }
-
- const widths = tagWidths.map((w) => Math.min(w, containerWidth));
-
- // ── 第一行 ──
- let row1End = -1;
- let rem = containerWidth;
- for (let i = 0; i < widths.length; i++) {
- const needed = i === 0 ? widths[i] : GAP + widths[i];
- if (rem >= needed) {
- rem -= needed;
- row1End = i;
- } else {
- break;
- }
- }
-
- if (row1End === widths.length - 1) {
- return { visibleCount: widths.length, overflowCount: 0 };
- }
-
- // ── 第二行 ──
- const r2start = row1End + 1;
- rem = containerWidth;
- let r2count = 0;
-
- for (let i = r2start; i < widths.length; i++) {
- const isFirst = i === r2start;
- const needed = isFirst ? widths[i] : GAP + widths[i];
- const isLast = i === widths.length - 1;
-
- if (isLast) {
- if (rem >= needed) r2count++;
- break;
- }
-
- // 非最后一个:放置当前 tag 后,还需在第二行留出 overflow tag 的空间
- if (rem >= needed + GAP + overflowTagWidth) {
- rem -= needed;
- r2count++;
- } else {
- break;
- }
- }
-
- const visibleCount = r2start + r2count;
- return { visibleCount, overflowCount: widths.length - visibleCount };
-}
-
-export default function Tags(props: Props) {
- const { type = 'outline', data, onTagClick } = props;
- const bgColor = props.bgColor || 'var(--fc-violet-3)';
- const fontColor = props.fontColor || 'var(--fc-violet-11)';
- const containerRef = useRef(null);
- const tagMeasureRefs = useRef<(HTMLSpanElement | null)[]>([]);
- const overflowMeasureRef = useRef(null);
- const [layout, setLayout] = useState({ visibleCount: data.length, overflowCount: 0 });
-
- // fill 模式下通过 inline style 设置动态颜色(Tailwind 不支持动态值)
- const fillStyle: React.CSSProperties | undefined =
- type === 'fill'
- ? {
- backgroundColor: bgColor,
- backgroundClip: 'padding-box',
- borderColor: bgColor,
- color: fontColor,
- }
- : undefined;
-
- // tag 的 Tailwind 基础类(测量层和渲染层共用)
- // p-[6px] border border-[var(--fc-border-color)] rounded-2xl leading-none whitespace-nowrap box-border
- const tagBaseClass = `inline-block px-[6px] py-[4px] border ${type === 'fill' ? '' : 'border-[var(--fc-border-color)]'} rounded-2xl leading-none whitespace-nowrap box-border ${
- onTagClick ? 'cursor-pointer' : ''
- }`;
-
- // 可见层额外加溢出省略
- const visibleTagClass = `${tagBaseClass} overflow-hidden text-ellipsis max-w-full shrink-0`;
-
- useLayoutEffect(() => {
- const el = containerRef.current;
- if (!el) return;
-
- const compute = () => {
- const containerWidth = el.getBoundingClientRect().width;
- if (containerWidth <= 0) return;
-
- const tagWidths = tagMeasureRefs.current.slice(0, data.length).map((span) => (span ? Math.ceil(span.getBoundingClientRect().width) : containerWidth));
- const overflowTagWidth = overflowMeasureRef.current ? Math.ceil(overflowMeasureRef.current.getBoundingClientRect().width) : 40;
-
- setLayout(calcLayout(tagWidths, overflowTagWidth, containerWidth));
- };
-
- const ro = new ResizeObserver(compute);
- ro.observe(el);
- compute();
-
- return () => ro.disconnect();
- }, [data]);
-
- const { visibleCount, overflowCount } = layout;
-
- return (
-
- {/* 隐藏测量层:绝对定位不占空间,用于获取各 tag 的真实渲染宽度 */}
-
- {data.map((tag, i) => (
- {
- tagMeasureRefs.current[i] = el;
- }}
- className={tagBaseClass}
- >
- {tag}
-
- ))}
- {/* 用最大计数值预估 overflow tag 宽度上限 */}
-
- +{data.length}
-
-
-
- {/* 可见布局层 */}
-
- {data.slice(0, visibleCount).map((tag, i) => (
-
{
- e.stopPropagation();
- onTagClick?.(tag);
- }}
- >
- {tag}
-
- ))}
- {overflowCount > 0 && (
-
-
- }
- onClick={() => {
- copy2ClipBoard(data.join('\n'));
- }}
- />
-
- }
- content={
-
- {data.map((tag, i) => (
-
-
{
- e.stopPropagation();
- onTagClick?.(tag);
- }}
- >
- {tag}
-
-
- ))}
-
- }
- >
-
{
- e.stopPropagation();
- }}
- >
- +{overflowCount}
-
-
- )}
-
-
- );
-}
diff --git a/src/pages/log/IndexPatterns/index.tsx b/src/pages/log/IndexPatterns/index.tsx
index 4b4491e06..17fee7815 100644
--- a/src/pages/log/IndexPatterns/index.tsx
+++ b/src/pages/log/IndexPatterns/index.tsx
@@ -15,7 +15,7 @@
*
*/
import React, { useState, useEffect, useContext } from 'react';
-import { Button, Input, Popconfirm, Space, Table, Tag, message } from 'antd';
+import { Button, Input, Modal, Dropdown, Menu, Table, Tag, message } from 'antd';
import _ from 'lodash';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
@@ -30,6 +30,7 @@ import './locale';
import { SearchOutlined } from '@ant-design/icons';
import EditField from './EditField';
import { useQuery } from '@/utils';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
export default function Servers() {
const { t } = useTranslation('es-index-patterns');
@@ -142,66 +143,89 @@ export default function Servers() {
},
{
title: t('common:table.operations'),
- width: 160,
+ width: 64,
+ fixed: 'right' as const,
render: (record) => {
return (
-
- {
- if (record) {
- EditField({
- id: record.id,
- datasourceList,
- onOk(values, name) {
- console.log('values', values);
- const newFieldConfig = {
- ...values,
- version: 2,
- };
- putESIndexPattern(record.id, {
- ..._.omit(record, ['fieldConfig', 'id']),
- fields_format: JSON.stringify(newFieldConfig),
- name,
- }).then(() => {
- fetchData();
- message.success(t('common:success.save'));
+
+
+ {
+ if (record) {
+ EditField({
+ id: record.id,
+ datasourceList,
+ onOk(values, name) {
+ console.log('values', values);
+ const newFieldConfig = {
+ ...values,
+ version: 2,
+ };
+ putESIndexPattern(record.id, {
+ ..._.omit(record, ['fieldConfig', 'id']),
+ fields_format: JSON.stringify(newFieldConfig),
+ name,
+ }).then(() => {
+ fetchData();
+ message.success(t('common:success.save'));
+ });
+ },
+ });
+ }
+ }}
+ >
+ {t('common:btn.config')}
+
+
+
+ {
+ FormModal({
+ mode: 'edit',
+ initialValues: record,
+ indexPatterns: data,
+ datasourceList: groupedDatasourceList.elasticsearch,
+ onOk: () => {
+ fetchData();
+ },
});
- },
- });
- }
- }}
- >
- {t('common:btn.config')}
-
- {
- FormModal({
- mode: 'edit',
- initialValues: record,
- indexPatterns: data,
- datasourceList: groupedDatasourceList.elasticsearch,
- onOk: () => {
- fetchData();
- },
- });
- }}
- >
- {t('common:btn.edit')}
-
- {
- deleteESIndexPattern(record.id).then(() => {
- message.success(t('common:success.delete'));
- fetchData();
- });
- }}
- >
-
-
-
+ }}
+ >
+ {t('common:btn.edit')}
+
+
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk: () => {
+ deleteESIndexPattern(record.id).then(() => {
+ message.success(t('common:success.delete'));
+ fetchData();
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+
+ }
+ >
+
+
);
},
},
diff --git a/src/pages/metricsBuiltin/List.tsx b/src/pages/metricsBuiltin/List.tsx
index c33ecfa87..d44154aed 100644
--- a/src/pages/metricsBuiltin/List.tsx
+++ b/src/pages/metricsBuiltin/List.tsx
@@ -19,13 +19,14 @@ import _ from 'lodash';
import { useAntdTable, useDebounceFn } from 'ahooks';
import { useTranslation } from 'react-i18next';
import { Space, Table, Button, Input, Dropdown, Select, message, Modal, Tooltip, Menu, Tag } from 'antd';
-import { SettingOutlined, DownOutlined, SearchOutlined, EyeOutlined, MoreOutlined } from '@ant-design/icons';
+import { SettingOutlined, DownOutlined, SearchOutlined, EyeOutlined } from '@ant-design/icons';
import { ColumnType } from 'antd/lib/table';
import { CommonStateContext } from '@/App';
import Markdown from '@/components/Markdown';
import PageLayout from '@/components/pageLayout';
import usePagination from '@/components/usePagination';
+import Tags from '@/components/TableTags/Tags';
import RefreshIcon from '@/components/RefreshIcon';
import OrganizeColumns, { getDefaultColumnsConfigs, setDefaultColumnsConfigs, ajustColumns } from '@/components/OrganizeColumns';
import { getUnitLabel, buildUnitOptions } from '@/pages/dashboard/Components/UnitPicker/utils';
@@ -33,6 +34,7 @@ import { getMenuPerm } from '@/services/common';
import Collapse from '@/pages/monitor/object/metricViews/components/Collapse';
import { getComponents, Component } from '@/pages/builtInComponents/services';
import { getDefaultDatasourceValue } from '@/utils';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
import { getMetrics, Record, Filter, getTypes, getCollectors, deleteMetrics, buildLabelFilterAndExpression } from './services';
import { defaultColumnsConfigs, LOCAL_STORAGE_KEY } from './constants';
@@ -230,13 +232,7 @@ export default function index() {
title: t('extra_fields'),
dataIndex: 'extra_fields',
render: (val) => {
- return (
-
- {_.map(val, (item) => {
- return {`${item.name}: ${item.value}`};
- })}
-
- );
+ return `${item.name}: ${item.value}`)} maxWidth={180} />;
},
},
{
@@ -269,14 +265,20 @@ export default function index() {
{
title: t('common:table.operations'),
dataIndex: 'operator',
+ width: 64,
+ fixed: 'right' as const,
render: (data, record: any) => {
return (
{actionAuth.add && (
- {
setFormDrawerData({
open: true,
@@ -287,12 +289,13 @@ export default function index() {
}}
>
{t('common:btn.clone')}
-
+
)}
{actionAuth.edit && record.updated_by !== 'system' && (
- {
setFormDrawerData({
open: true,
@@ -303,34 +306,37 @@ export default function index() {
}}
>
{t('common:btn.edit')}
-
+
)}
{actionAuth.delete && record.updated_by !== 'system' && (
-
-
-
+ <>
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk() {
+ deleteMetrics([record.id]).then(() => {
+ message.success(t('common:success.delete'));
+ setRefreshFlag(_.uniqueId('refreshFlag_'));
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+ >
)}
{record.expression_type === 'metric_name' && (
- {
setNewMetricExplorerDrawerState((prev) => {
return {
@@ -342,13 +348,13 @@ export default function index() {
}}
>
{t('laset_over_time')}
-
+
)}
}
>
- } />
+
);
},
diff --git a/src/pages/notificationChannels/pages/List/index.tsx b/src/pages/notificationChannels/pages/List/index.tsx
index a3bfb3041..a8138c2ae 100644
--- a/src/pages/notificationChannels/pages/List/index.tsx
+++ b/src/pages/notificationChannels/pages/List/index.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect, useMemo } from 'react';
-import { Table, Space, Button, Switch, Modal, Input, message } from 'antd';
+import { Table, Space, Button, Switch, Modal, Input, message, Dropdown, Menu } from 'antd';
import { NotificationOutlined, SearchOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import _ from 'lodash';
@@ -13,6 +13,7 @@ import { Import, Export } from '@/components/ExportImport';
import { getItems, putItem, deleteItems, postItems } from '../../services';
import { NS } from '../../constants';
import { ChannelItem } from '../../types';
+import { TableActionButton, TableActionLink, TableActionTrigger } from '@/components/TableActionDropdown';
export default function List() {
const { t } = useTranslation(NS);
@@ -181,41 +182,46 @@ export default function List() {
},
{
title: t('common:table.operations'),
- width: 100,
+ width: 64,
+ fixed: 'right' as const,
render: (record) => {
return (
-
-
- {t('common:btn.clone')}
-
-
-
+
+
+
+ {t('common:btn.clone')}
+
+
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk: () => {
+ deleteItems([record.id]).then(() => {
+ message.success(t('common:success.delete'));
+ fetchData();
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+
+ }
+ >
+
+
);
},
},
diff --git a/src/pages/notificationChannels/pages/ListNG/index.tsx b/src/pages/notificationChannels/pages/ListNG/index.tsx
index fafd5aedd..221689732 100644
--- a/src/pages/notificationChannels/pages/ListNG/index.tsx
+++ b/src/pages/notificationChannels/pages/ListNG/index.tsx
@@ -1,6 +1,6 @@
import React, { useMemo, useState } from 'react';
-import { Input, Select, Space, Table, Button, Modal, Switch, message, Tooltip } from 'antd';
-import { NotificationOutlined, PlusOutlined, CopyOutlined, DeleteOutlined } from '@ant-design/icons';
+import { Input, Select, Space, Table, Button, Modal, Switch, message, Tooltip, Dropdown, Menu } from 'antd';
+import { NotificationOutlined, PlusOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import { map, upperCase, includes, filter } from 'lodash';
import { Link } from 'react-router-dom';
@@ -14,6 +14,7 @@ import { Import, Export } from '@/components/ExportImport';
import { NS, NOTIFICATION_CHANNEL_TYPES } from '../../constants';
import { getItems, putItem, deleteItems, postItems } from '../../services';
import { ChannelItem } from '../../types';
+import { TableActionButton, TableActionLink, TableActionTrigger } from '@/components/TableActionDropdown';
interface Filter {
search?: string;
@@ -294,40 +295,49 @@ export default function index() {
},
{
title: t('common:table.operations'),
- width: 100,
+ width: 64,
+ fixed: 'right' as const,
render: (record) => {
return (
-
-
- } />
-
-
- }
- disabled={record.enable === true}
- onClick={() => {
- Modal.confirm({
- title: t('common:confirm.delete'),
- onOk: () => {
- deleteItems([record.id]).then(() => {
- message.success(t('common:success.delete'));
- run();
- });
- },
- });
- }}
- />
-
-
+
+
+
+ {t('common:btn.clone')}
+
+
+
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk: () => {
+ deleteItems([record.id]).then(() => {
+ message.success(t('common:success.delete'));
+ run();
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+
+
+ }
+ >
+
+
);
},
},
@@ -339,7 +349,7 @@ export default function index() {
},
}}
pagination={pagination}
- scroll={{ y: 'calc(100% - 42px)' }}
+ scroll={{ x: 'max-content', y: 'calc(100% - 42px)' }}
/>
diff --git a/src/pages/notificationRules/pages/List.tsx b/src/pages/notificationRules/pages/List.tsx
index 07abc8526..8c866fdc1 100644
--- a/src/pages/notificationRules/pages/List.tsx
+++ b/src/pages/notificationRules/pages/List.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect, useMemo } from 'react';
-import { Table, Space, Button, Switch, Modal, Input, Tag, Tooltip } from 'antd';
+import { Table, Space, Button, Switch, Modal, Input, Dropdown, Menu } from 'antd';
import { NotificationOutlined, SearchOutlined } from '@ant-design/icons';
import { useTranslation } from 'react-i18next';
import _ from 'lodash';
@@ -8,6 +8,7 @@ import { Link } from 'react-router-dom';
import { IS_PLUS } from '@/utils/constant';
import PageLayout from '@/components/pageLayout';
+import Tags from '@/components/TableTags/Tags';
import { getSimplifiedItems as getNotificationChannels } from '@/pages/notificationChannels/services';
import { getTeamInfoList } from '@/services/manage';
import usePagination from '@/components/usePagination';
@@ -15,6 +16,7 @@ import usePagination from '@/components/usePagination';
import { getItems, putItem, deleteItems } from '../services';
import { NS, CN, TABLE_PAGINATION_CACHE_KEY } from '../constants';
import { RuleItem } from '../types';
+import { TableActionButton, TableActionLink, TableActionTrigger } from '@/components/TableActionDropdown';
interface Filter {
search?: string;
@@ -138,39 +140,62 @@ export default function List() {
{
title: t('notification_configuration.channel'),
dataIndex: 'notify_configs',
- render: (val) => {
- return _.map(val, (item) => {
- return (
-
- {item.channel ?? item.channel_id}
-
- );
- });
+ render: (val: { channel_id: number; channel?: string }[]) => {
+ return (
+
item.channel_id}
+ getLabel={(item) => item.channel ?? String(item.channel_id)}
+ getTooltipTitle={(item) => (typeof item === 'string' ? undefined : item.channel ? undefined : t('channel_invalid_tip'))}
+ />
+ );
},
},
{
title: t('user_group_ids'),
dataIndex: 'user_group_ids',
- render: (val) => {
- return _.map(val, (item) => {
- const name = _.find(userGroups, { id: item })?.name;
- return (
-
- {name ?? item}
-
- );
- });
+ render: (val: number[]) => {
+ return (
+ item}
+ getLabel={(item) => {
+ const id = typeof item === 'number' ? item : Number(item);
+ return _.find(userGroups, { id })?.name ?? String(item);
+ }}
+ getTooltipTitle={(item) => {
+ const id = typeof item === 'number' ? item : Number(item);
+ return _.find(userGroups, { id })?.name ? undefined : t('user_group_id_invalid_tip');
+ }}
+ />
+ );
},
},
{
title: t('common:table.update_by'),
dataIndex: 'update_by',
+ render: (val, record: any) => (
+
+
{val}
+ {record.update_by_nickname &&
{record.update_by_nickname}
}
+
+ ),
},
{
title: t('common:table.update_at'),
dataIndex: 'update_at',
render: (val) => {
- return moment.unix(val).format('YYYY-MM-DD HH:mm:ss');
+ const m = moment.unix(val);
+ return (
+
+
{m.format('YYYY-MM-DD')}
+
{m.format('HH:mm:ss')}
+
+ );
},
},
{
@@ -203,48 +228,50 @@ export default function List() {
},
{
title: t('common:table.operations'),
- width: 160,
+ width: 64,
+ fixed: 'right' as const,
render: (record) => {
return (
-
-
- {t('common:btn.edit')}
-
-
- {t('common:btn.clone')}
-
-
-
+
+
+
+ {t('common:btn.edit')}
+
+
+
+
+ {t('common:btn.clone')}
+
+
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk: () => {
+ deleteItems([record.id]).then(() => {
+ fetchData();
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+
+ }
+ >
+
+
);
},
},
diff --git a/src/pages/recordingRules/PageTable.tsx b/src/pages/recordingRules/PageTable.tsx
index 7da7fa058..89271993e 100644
--- a/src/pages/recordingRules/PageTable.tsx
+++ b/src/pages/recordingRules/PageTable.tsx
@@ -1,5 +1,5 @@
import React, { useEffect, useState, useMemo, useContext } from 'react';
-import { Button, Modal, message, Dropdown, Table, Switch, Select, Space, Tag } from 'antd';
+import { Button, Modal, message, Dropdown, Table, Switch, Select, Space, Tag, Menu } from 'antd';
import { useHistory } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { ColumnType } from 'antd/lib/table';
@@ -13,6 +13,8 @@ import { strategyItem, strategyStatus } from '@/store/warningInterface';
import { deleteRecordingRule } from '@/services/recording';
import { CommonStateContext } from '@/App';
import localeCompare from '@/pages/dashboard/Renderer/utils/localeCompare';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
+import Tags from '@/components/TableTags/Tags';
import EditModal from './components/editModal';
import Import from './components/Import';
import Export from './components/Export';
@@ -113,49 +115,36 @@ const PageTable: React.FC = ({ gids }) => {
getRecordingRules();
};
- const columns: ColumnType[] = _.concat(
- businessGroup.isLeaf && gids !== '-2'
- ? []
- : ([
- {
- title: t('common:business_group'),
- dataIndex: 'group_id',
- width: 100,
- render: (id) => {
- return _.find(busiGroups, { id })?.name;
- },
- },
- ] as any),
- [
- {
- title: t('common:datasource.name'),
- dataIndex: 'datasource_ids',
- render: (data) => {
- return _.map(
- _.filter(data, (item) => {
- return _.find(groupedDatasourceList.prometheus, { id: item });
- }),
- (item) => {
- if (item === 0) {
- return (
-
- $all
-
- );
- }
- return {_.find(groupedDatasourceList.prometheus, { id: item })?.name!};
- },
- );
- },
+ const columns: ColumnType[] = _.concat([
+ {
+ title: t('common:datasource.name'),
+ dataIndex: 'datasource_ids',
+ render: (data) => {
+ return (
+ item === 0 || _.find(groupedDatasourceList.prometheus, { id: item })),
+ (item) => {
+ if (item === 0) return '$all';
+ return _.find(groupedDatasourceList.prometheus, { id: item })?.name!;
+ },
+ )}
+ />
+ );
},
- {
- title: t('name'),
- dataIndex: 'name',
- sorter: (a, b) => {
- return localeCompare(a.name, b.name);
- },
- render: (data, record) => {
- return (
+ },
+ {
+ title: t('name'),
+ dataIndex: 'name',
+ sorter: (a, b) => {
+ return localeCompare(a.name, b.name);
+ },
+ render: (data, record) => {
+ const groupName = !(businessGroup.isLeaf && gids !== '-2') ? _.find(busiGroups, { id: record.group_id })?.name : undefined;
+ return (
+
{
@@ -164,100 +153,117 @@ const PageTable: React.FC
= ({ gids }) => {
>
{data}
- );
- },
+ {groupName &&
{groupName}}
+
+ );
},
- {
- title: t('cron_pattern'),
- dataIndex: 'cron_pattern',
+ },
+ {
+ title: t('cron_pattern'),
+ dataIndex: 'cron_pattern',
+ },
+ {
+ title: t('append_tags'),
+ dataIndex: 'append_tags',
+ render: (data) => {
+ const array = data || [];
+ return ;
},
- {
- title: t('append_tags'),
- dataIndex: 'append_tags',
- render: (data) => {
- const array = data || [];
- return (
- (array.length &&
- array.map((tag: string, index: number) => {
- return (
-
- {tag}
-
- );
- })) ||
- );
- },
+ },
+ {
+ title: t('common:table.update_at'),
+ dataIndex: 'update_at',
+ sorter: (a, b) => {
+ return a.update_at - b.update_at;
},
- {
- title: t('common:table.update_at'),
- dataIndex: 'update_at',
- sorter: (a, b) => {
- return a.update_at - b.update_at;
- },
- render: (text: number) => moment.unix(text).format('YYYY-MM-DD HH:mm:ss'),
+ render: (text: number) => {
+ const m = moment.unix(text);
+ return (
+
+
{m.format('YYYY-MM-DD')}
+
{m.format('HH:mm:ss')}
+
+ );
},
- {
- title: t('disabled'),
- dataIndex: 'disabled',
- render: (disabled, record) => (
- {
- const { id, disabled } = record;
- updateRecordingRules(
- {
- ids: [id],
- fields: {
- disabled: !disabled ? 1 : 0,
- },
+ },
+ {
+ title: t('disabled'),
+ dataIndex: 'disabled',
+ render: (disabled, record) => (
+ {
+ const { id, disabled } = record;
+ updateRecordingRules(
+ {
+ ids: [id],
+ fields: {
+ disabled: !disabled ? 1 : 0,
},
- record.group_id,
- ).then(() => {
- refreshList();
- });
- }}
- />
- ),
- },
- {
- title: t('common:table.operations'),
- dataIndex: 'operator',
- render: (data, record) => {
- return (
-
-
{
- handleClickEdit(record.id, true);
- }}
- >
- {t('common:btn.clone')}
-
-
{
- confirm({
- title: t('common:confirm.delete'),
- onOk: () => {
- deleteRecordingRule([record.id], record.group_id).then(() => {
- message.success(t('common:success.delete'));
- refreshList();
- });
- },
+ },
+ record.group_id,
+ ).then(() => {
+ refreshList();
+ });
+ }}
+ />
+ ),
+ },
+ {
+ title: t('common:table.operations'),
+ dataIndex: 'operator',
+ width: 64,
+ fixed: 'right' as const,
+ render: (data, record) => {
+ return (
+
+
+ {
+ handleClickEdit(record.id, true);
+ }}
+ >
+ {t('common:btn.clone')}
+
+
+
+
+ {
+ confirm({
+ title: t('common:confirm.delete'),
+ onOk: () => {
+ deleteRecordingRule([record.id], record.group_id).then(() => {
+ message.success(t('common:success.delete'));
+ refreshList();
+ });
+ },
- onCancel() {},
- });
- }}
- >
- {t('common:btn.delete')}
-
-
- );
- },
+ onCancel() {},
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+
+ }
+ >
+
+
+ );
},
- ],
- );
+ },
+ ]);
const toOneArr = (arr, res, name) => {
arr.forEach((ele) => {
diff --git a/src/pages/targets/List.tsx b/src/pages/targets/List.tsx
index 19c6745ed..c8eba3df1 100644
--- a/src/pages/targets/List.tsx
+++ b/src/pages/targets/List.tsx
@@ -20,6 +20,7 @@ import TargetMetaDrawer from './TargetMetaDrawer';
import Explorer from './components/Explorer';
import EditBusinessGroups from './components/EditBusinessGroups';
import HostsSelect from './components/HostsSelect';
+import Tags from '@/components/TableTags/Tags';
// @ts-ignore
import CollectsDrawer from 'plus:/pages/collects/CollectsDrawer';
@@ -46,8 +47,9 @@ export interface ITargetProps {
id: number;
cluster: string;
group_id: number;
- group_objs: object[] | null;
+ group_objs: { name: string }[] | null;
ident: string;
+ host_ip?: string;
note: string;
tags: string[];
beat_time: number;
@@ -96,7 +98,7 @@ export default function List(props: IProps) {
{
title: (
- {t('common:table.ident')}
+ {t('host_ip')}
{
+ render: (text, record: ITargetProps) => {
+ const groupNames = _.map(record.group_objs, 'name');
return (
-
-
- {import.meta.env['VITE_IS_PRO'] && (
-
- {
- setCollectsDrawerVisible(true);
- setCollectsDrawerIdent(text);
- }}
- />
-
- )}
+
+
+
+ {import.meta.env['VITE_IS_PRO'] && (
+
+ {
+ setCollectsDrawerVisible(true);
+ setCollectsDrawerIdent(text);
+ }}
+ />
+
+ )}
+
+
+ {record.host_ip && record.host_ip !== text && {text}}
+ {!_.isEmpty(groupNames) ? {groupNames.join(' / ')} : {t('common:not_grouped')}}
+ {record.note && {record.note}}
+
);
},
@@ -178,13 +188,7 @@ export default function List(props: IProps) {
_.forEach(columnsConfigs, (item) => {
if (!item.visible) return;
- if (item.name === 'host_ip') {
- columns.push({
- title: t('host_ip'),
- dataIndex: 'host_ip',
- className: 'n9e-hosts-table-column-ip',
- });
- }
+ if (item.name === 'host_ip' || item.name === 'group_obj') return;
if (item.name === 'host_tags') {
columns.push({
title: (
@@ -201,30 +205,19 @@ export default function List(props: IProps) {
showTitle: false,
},
render(tagArr) {
- const content =
- tagArr &&
- tagArr.map((item) => (
-
{
- if (!tableQueryContent.includes(item)) {
- isAddTagToQueryInput.current = true;
- const val = tableQueryContent ? `${tableQueryContent.trim()} ${item}` : item;
- setTableQueryContent(val);
- setSearchVal(val);
- }
- }}
- >
- {item}
-
- ));
return (
- tagArr && (
-
document.body} overlayClassName='mon-manage-table-tooltip'>
- {content}
-
- )
+
+ data={tagArr}
+ maxWidth={180}
+ onTagClick={(item) => {
+ if (!tableQueryContent.includes(item)) {
+ isAddTagToQueryInput.current = true;
+ const val = tableQueryContent ? `${tableQueryContent.trim()} ${item}` : item;
+ setTableQueryContent(val);
+ setSearchVal(val);
+ }
+ }}
+ />
);
},
});
@@ -273,33 +266,6 @@ export default function List(props: IProps) {
},
});
}
- if (item.name === 'group_obj') {
- columns.push({
- title: t('group_obj'),
- dataIndex: 'group_objs',
- className: 'n9e-hosts-table-column-tags',
- ellipsis: {
- showTitle: false,
- },
- render(tagArr) {
- if (_.isEmpty(tagArr)) return t('common:not_grouped');
- const content =
- tagArr &&
- tagArr.map((item) => (
-
- {item.name}
-
- ));
- return (
- tagArr && (
- document.body}>
- {content}
-
- )
- );
- },
- });
- }
if (item.name === 'mem_util') {
columns.push({
title: t('mem_util'),
diff --git a/src/pages/task/index.tsx b/src/pages/task/index.tsx
index 0f7f7a26c..35a141b19 100644
--- a/src/pages/task/index.tsx
+++ b/src/pages/task/index.tsx
@@ -16,13 +16,14 @@
*/
import React, { useContext, useState, useEffect } from 'react';
import { Link, useHistory } from 'react-router-dom';
-import { Table, Divider, Checkbox, Row, Col, Select, Button, Space } from 'antd';
+import { Table, Checkbox, Row, Col, Select, Button, Space, Dropdown, Menu } from 'antd';
import { CodeOutlined } from '@ant-design/icons';
import { ColumnProps } from 'antd/lib/table';
import _ from 'lodash';
import moment from 'moment';
import { useTranslation } from 'react-i18next';
import { useAntdTable } from 'ahooks';
+import { TableActionButton, TableActionLink, TableActionTrigger } from '@/components/TableActionDropdown';
import request from '@/utils/request';
import api from '@/utils/api';
@@ -118,57 +119,81 @@ const index = (_props: any) => {
});
};
+ const showBusinessGroup = !(businessGroup.isLeaf && gids !== '-2');
const columns: ColumnProps[] = _.concat(
- businessGroup.isLeaf && gids !== '-2'
- ? []
- : ([
- {
- title: t('common:business_group'),
- dataIndex: 'group_id',
- width: 100,
- render: (id) => {
- return _.find(busiGroups, { id })?.name;
- },
- },
- ] as any),
[
- {
- title: 'ID',
- dataIndex: 'id',
- width: 100,
- },
{
title: t('task.title'),
dataIndex: 'title',
- width: 200,
+ width: 240,
render: (text, record) => {
- return {text};
- },
- },
- {
- title: t('table.operations'),
- width: 150,
- render: (_text, record) => {
+ const groupName = _.find(busiGroups, { id: record.group_id })?.name;
return (
-
- {t('task.clone')}
-
- handleOpenMetaDrawer(record)}>{t('task.meta')}
-
+
+ {text}
+
+ ID: {record.id}
+ {showBusinessGroup && groupName && {groupName}}
+
+
);
},
},
+ ] as any,
+ [
{
title: t('task.creator'),
dataIndex: 'create_by',
width: 100,
+ render: (val, record: any) => (
+
+
{val}
+ {record.create_by_nickname &&
{record.create_by_nickname}
}
+
+ ),
},
{
title: t('task.created'),
dataIndex: 'create_at',
width: 160,
render: (text) => {
- return moment.unix(text).format('YYYY-MM-DD HH:mm:ss');
+ const m = moment.unix(text);
+ return (
+
+
{m.format('YYYY-MM-DD')}
+
{m.format('HH:mm:ss')}
+
+ );
+ },
+ },
+ {
+ title: t('table.operations'),
+ width: 64,
+ fixed: 'right' as const,
+ render: (_text, record) => {
+ return (
+
+
+
+ {t('task.clone')}
+
+
+
+ handleOpenMetaDrawer(record)}>
+ {t('task.meta')}
+
+
+
+ }
+ >
+
+
+ );
},
},
],
diff --git a/src/pages/taskTpl/index.tsx b/src/pages/taskTpl/index.tsx
index 6cc933572..4cdce2691 100644
--- a/src/pages/taskTpl/index.tsx
+++ b/src/pages/taskTpl/index.tsx
@@ -16,13 +16,15 @@
*/
import React, { useState, useContext, useEffect } from 'react';
import { Link } from 'react-router-dom';
-import { Table, Divider, Popconfirm, Tag, Row, Col, Button, Dropdown, Menu, message, Space } from 'antd';
+import { Table, Modal, Tag, Row, Col, Button, Dropdown, Menu, message, Space } from 'antd';
import { DownOutlined, CodeOutlined } from '@ant-design/icons';
import { ColumnProps } from 'antd/lib/table';
import _ from 'lodash';
import moment from 'moment';
import { useAntdTable } from 'ahooks';
import { useTranslation } from 'react-i18next';
+import { TableActionButton, TableActionLink, TableActionTrigger } from '@/components/TableActionDropdown';
+import Tags from '@/components/TableTags/Tags';
import request from '@/utils/request';
import { RequestMethod } from '@/store/common';
@@ -112,81 +114,115 @@ const index = (_props: any) => {
}
}
+ const showBusinessGroup = !(businessGroup.isLeaf && gids !== '-2');
const columns: ColumnProps[] = _.concat(
- businessGroup.isLeaf && gids !== '-2'
- ? []
- : ([
- {
- title: t('common:business_group'),
- dataIndex: 'group_id',
- width: 100,
- render: (id) => {
- return _.find(busiGroups, { id })?.name;
- },
- },
- ] as any),
[
- {
- title: 'ID',
- dataIndex: 'id',
- },
{
title: t('tpl.title'),
dataIndex: 'title',
+ width: 360,
render: (text, record) => {
- return {text};
+ const groupName = _.find(busiGroups, { id: record.group_id })?.name;
+ return (
+
+ {text}
+
+ ID: {record.id}
+ {showBusinessGroup && groupName && {groupName}}
+
+
+ );
},
},
+ ] as any,
+ [
{
title: t('tpl.tags'),
dataIndex: 'tags',
+ width: 280,
render: (text) => {
- return _.map(text, (item) => (
- handleTagClick(item)}>
- {item}
-
- ));
+ return ;
},
},
{
title: t('tpl.creator'),
dataIndex: 'create_by',
- width: 100,
+ width: 120,
+ render: (val, record: any) => (
+
+
{val}
+ {record.create_by_nickname &&
{record.create_by_nickname}
}
+
+ ),
},
{
title: t('tpl.last_updated'),
dataIndex: 'update_at',
- width: 160,
+ width: 180,
render: (text) => {
- return moment.unix(text).format('YYYY-MM-DD HH:mm:ss');
+ const m = moment.unix(text);
+ return (
+
+
{m.format('YYYY-MM-DD')}
+
{m.format('HH:mm:ss')}
+
+ );
},
},
{
title: t('table.operations'),
- width: 220,
+ width: 64,
+ fixed: 'right' as const,
render: (_text, record) => {
return (
-
- {t('task.create')}
-
- {t('common:btn.edit')}
-
- {t('common:btn.clone')}
-
- {t('common:confirm.delete')} }
- onConfirm={() => {
- request(`${api.tasktpl(record.group_id)}/${record.id}`, {
- method: 'DELETE',
- }).then(() => {
- message.success(t('msg.delete.success'));
- refresh();
- });
- }}
- >
- {t('common:btn.delete')}
-
-
+
+
+
+ {t('task.create')}
+
+
+
+
+ {t('common:btn.edit')}
+
+
+
+
+ {t('common:btn.clone')}
+
+
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk: () => {
+ return request(`${api.tasktpl(record.group_id)}/${record.id}`, {
+ method: 'DELETE',
+ }).then(() => {
+ message.success(t('msg.delete.success'));
+ refresh();
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+
+ }
+ >
+
+
);
},
},
@@ -202,7 +238,7 @@ const index = (_props: any) => {
{gids ? (
-
+
{
{
...tableProps.pagination,
showSizeChanger: true,
- pageSizeOptions: ['10', '50', '100', '500', '1000'],
+ pageSizeOptions: ['10', '15', '50', '100', '500', '1000'],
showTotal: (total) => {
return i18n.language == 'en' ? `Total ${total} items` : `共 ${total} 条`;
},
diff --git a/src/pages/user/business.tsx b/src/pages/user/business.tsx
index c41161a62..e7c63ca79 100644
--- a/src/pages/user/business.tsx
+++ b/src/pages/user/business.tsx
@@ -19,13 +19,14 @@ import moment from 'moment';
import _ from 'lodash';
import classNames from 'classnames';
import PageLayout, { HelpLink } from '@/components/pageLayout';
-import { Button, Table, Input, message, Row, Col, Modal, Space } from 'antd';
+import { Button, Table, Input, message, Row, Col, Modal, Space, Dropdown, Menu } from 'antd';
import { EditOutlined, DeleteOutlined, SearchOutlined, UserOutlined, InfoCircleOutlined } from '@ant-design/icons';
import UserInfoModal from './component/createModal';
import { deleteBusinessTeamMember, getBusinessTeamList, getBusinessTeamInfo, deleteBusinessTeam } from '@/services/manage';
import { Team, ActionType } from '@/store/manageInterface';
import { CommonStateContext } from '@/App';
import { ColumnsType } from 'antd/lib/table';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
import { useTranslation } from 'react-i18next';
import { useQuery } from '@/utils';
import { listToTree, getCollapsedKeys, getLocaleExpandedKeys, setLocaleExpandedKeys, getDefaultBusiness } from '@/components/BusinessGroup';
@@ -69,35 +70,49 @@ const Resource: React.FC = () => {
},
{
title: t('common:table.operations'),
- width: '100px',
+ width: 64,
+ fixed: 'right' as const,
render: (text: string, record) => (
-
+
+
),
},
];
diff --git a/src/pages/user/component/Tags/index.tsx b/src/pages/user/component/Tags/index.tsx
deleted file mode 100644
index f916d686c..000000000
--- a/src/pages/user/component/Tags/index.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import React from 'react';
-import _ from 'lodash';
-import { Tag, Tooltip } from 'antd';
-import { Link } from 'react-router-dom';
-
-interface Props {
- data: { id: number; name: string }[];
- tagLinkTo: (item) => {
- pathname: string;
- search: string;
- };
-}
-
-export default function index(props: Props) {
- const { data, tagLinkTo } = props;
- const displayData = _.slice(data, 0, 3);
- return (
-
-
- {_.map(displayData, (item) => {
- return (
-
-
-
- {item.name}
-
-
-
- );
- })}
- {data.length > 2 && (
-
- ...
-
- )}
-
-
- );
-}
diff --git a/src/pages/user/constants.ts b/src/pages/user/constants.ts
index a5ecc63a7..1426f0667 100644
--- a/src/pages/user/constants.ts
+++ b/src/pages/user/constants.ts
@@ -24,21 +24,6 @@ export const defaultColumnsConfigs = [
i18nKey: 'account:profile.username',
visible: true,
},
- {
- name: 'nickname',
- i18nKey: 'account:profile.nickname',
- visible: true,
- },
- {
- name: 'email',
- i18nKey: 'account:profile.email',
- visible: false,
- },
- {
- name: 'phone',
- i18nKey: 'account:profile.phone',
- visible: false,
- },
{
name: 'roles',
i18nKey: 'account:profile.role',
diff --git a/src/pages/user/groups.tsx b/src/pages/user/groups.tsx
index 86ee61915..36bb210c7 100644
--- a/src/pages/user/groups.tsx
+++ b/src/pages/user/groups.tsx
@@ -20,16 +20,18 @@ import _ from 'lodash';
import { useLocation } from 'react-router-dom';
import queryString from 'query-string';
import PageLayout, { HelpLink } from '@/components/pageLayout';
-import { Button, Table, Input, message, List, Row, Col, Modal, Space, Tag } from 'antd';
+import { Button, Table, Input, message, List, Row, Col, Modal, Space, Tag, Dropdown, Menu } from 'antd';
import { EditOutlined, DeleteOutlined, SearchOutlined, UserOutlined, InfoCircleOutlined, PlusSquareOutlined } from '@ant-design/icons';
import UserInfoModal from './component/createModal';
import { getTeamInfoList, getTeamInfo, deleteTeam, deleteMember } from '@/services/manage';
import { User, Team, UserType, ActionType, TeamInfo } from '@/store/manageInterface';
import { ColumnsType } from 'antd/lib/table';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
import { useTranslation } from 'react-i18next';
import { listToTree } from '@/components/BusinessGroup';
import { CommonStateContext } from '@/App';
import Tree from '@/components/BusinessGroup/components/Tree';
+import Tags from '@/components/TableTags/Tags';
import './index.less';
import './locale';
import usePagination from '@/components/usePagination';
@@ -102,9 +104,7 @@ const Resource: React.FC = () => {
dataIndex: 'busi_groups',
render: (text: string, record) => {
if (_.isEmpty(record.busi_groups)) return '-';
- return _.map(record.busi_groups, (item) => {
- return {item.name};
- });
+ return item.id} getLabel={(item) => item.name} />;
},
},
];
@@ -113,30 +113,43 @@ const Resource: React.FC = () => {
...userColumn,
{
title: t('common:table.operations'),
- width: '100px',
+ width: 64,
+ fixed: 'right' as const,
render: (text: string, record) => (
-
+
+
),
},
];
diff --git a/src/pages/user/users.tsx b/src/pages/user/users.tsx
index 47b1815e1..2475ec94b 100644
--- a/src/pages/user/users.tsx
+++ b/src/pages/user/users.tsx
@@ -18,11 +18,12 @@ import React, { useState, useContext } from 'react';
import moment from 'moment';
import _ from 'lodash';
import { Button, Input, message, Row, Modal, Table, Space, Dropdown, Menu } from 'antd';
-import { SearchOutlined, UserOutlined, EyeOutlined, MoreOutlined } from '@ant-design/icons';
+import { SearchOutlined, UserOutlined, EyeOutlined } from '@ant-design/icons';
import { ColumnsType } from 'antd/lib/table';
import { useTranslation } from 'react-i18next';
import { useAntdTable } from 'ahooks';
-import PageLayout, { HelpLink } from '@/components/pageLayout';
+import PageLayout from '@/components/pageLayout';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
import UserInfoModal from './component/createModal';
import { getUserInfoList, deleteUser } from '@/services/manage';
import { User, UserType, ActionType } from '@/store/manageInterface';
@@ -31,7 +32,7 @@ import usePagination from '@/components/usePagination';
import TimeRangePicker, { IRawTimeRange, parseRange } from '@/components/TimeRangePicker';
import OrganizeColumns, { getDefaultColumnsConfigs, setDefaultColumnsConfigs, ajustColumns } from '@/components/OrganizeColumns';
import { defaultColumnsConfigs, LOCAL_STORAGE_KEY } from './constants';
-import Tags from './component/Tags';
+import Tags from '@/components/TableTags/Tags';
import './index.less';
import './locale';
@@ -45,30 +46,24 @@ const Resource: React.FC = () => {
const [memberId, setMemberId] = useState('');
const [query, setQuery] = useState('');
const [range, setRange] = useState();
- const { profile, perms } = useContext(CommonStateContext);
+ const { perms } = useContext(CommonStateContext);
const pagination = usePagination({ PAGESIZE_KEY: 'users' });
const [columnsConfigs, setColumnsConfigs] = useState<{ name: string; visible: boolean }[]>(getDefaultColumnsConfigs(defaultColumnsConfigs, LOCAL_STORAGE_KEY));
const userColumn: ColumnsType = [
{
title: t('account:profile.username'),
dataIndex: 'username',
+ width: 260,
ellipsis: true,
- },
- {
- title: t('account:profile.nickname'),
- dataIndex: 'nickname',
- ellipsis: true,
- render: (text: string, record) => record.nickname || '-',
- },
- {
- title: t('account:profile.email'),
- dataIndex: 'email',
- render: (text: string, record) => record.email || '-',
- },
- {
- title: t('account:profile.phone'),
- dataIndex: 'phone',
- render: (text: string, record) => record.phone || '-',
+ sorter: true,
+ render: (text: string, record) => {
+ return (
+
+ {record.nickname || text}
+ {text}
+
+ );
+ },
},
];
const userColumns: ColumnsType = [
@@ -76,20 +71,22 @@ const Resource: React.FC = () => {
{
title: t('account:profile.role'),
dataIndex: 'roles',
+ width: 120,
render: (text: []) => text.join(', '),
},
{
title: t('user.busi_groups'),
dataIndex: 'busi_groups',
- render: (value) => {
+ width: 160,
+ render: (value: { id: number; name: string }[]) => {
return (
{
- return {
- pathname: '/busi-groups',
- search: `?id=${item.id}`,
- };
+ maxWidth={220}
+ getKey={(item) => item.id}
+ getLabel={(item) => item.name}
+ onTagClick={(item) => {
+ if (typeof item !== 'string') window.open(`/busi-groups?id=${item.id}`, '_blank');
}}
/>
);
@@ -98,15 +95,16 @@ const Resource: React.FC = () => {
{
title: t('user.user_groups'),
dataIndex: 'user_groups',
- render: (value) => {
+ width: 160,
+ render: (value: { id: number; name: string }[]) => {
return (
{
- return {
- pathname: '/user-groups',
- search: `?id=${item.id}`,
- };
+ maxWidth={220}
+ getKey={(item) => item.id}
+ getLabel={(item) => item.name}
+ onTagClick={(item) => {
+ if (typeof item !== 'string') window.open(`/user-groups?id=${item.id}`, '_blank');
}}
/>
);
@@ -115,6 +113,7 @@ const Resource: React.FC = () => {
{
title: t('common:table.create_at'),
dataIndex: 'create_at',
+ width: 170,
render: (text) => {
return moment.unix(text).format('YYYY-MM-DD HH:mm:ss');
},
@@ -123,6 +122,7 @@ const Resource: React.FC = () => {
{
title: t('user.last_active_time'),
dataIndex: 'last_active_time',
+ width: 170,
render: (text) => {
if (!text) {
return '-';
@@ -133,26 +133,27 @@ const Resource: React.FC = () => {
},
{
title: t('common:table.operations'),
- width: i18n.language === 'en_US' || i18n.language === 'ru_RU' ? 80 : 40,
+ width: 64,
+ fixed: 'right' as const,
render: (text: string, record) => {
return (
{_.includes(perms, '/users/put') && (
handleClick(ActionType.EditUser, record.id)}>
-
+ {t('common:btn.edit')}
)}
{_.includes(perms, '/users/put') && (
handleClick(ActionType.Reset, record.id)}>
-
+ {t('account:password.reset')}
)}
+ {_.includes(perms, '/users/del') && }
{_.includes(perms, '/users/del') && (
{
@@ -168,15 +169,15 @@ const Resource: React.FC = () => {
});
}}
>
-
+
)}
}
>
- } />
+
);
},
diff --git a/src/pages/variableConfigs/index.tsx b/src/pages/variableConfigs/index.tsx
index 1c98fe853..ba226da20 100644
--- a/src/pages/variableConfigs/index.tsx
+++ b/src/pages/variableConfigs/index.tsx
@@ -17,12 +17,13 @@
import React, { useState, useEffect } from 'react';
import _ from 'lodash';
import { useTranslation } from 'react-i18next';
-import { Button, Input, Table, Space, message, Popconfirm } from 'antd';
+import { Button, Input, Table, Space, message, Modal, Dropdown, Menu } from 'antd';
import { SettingOutlined } from '@ant-design/icons';
import PageLayout from '@/components/pageLayout';
import DocumentDrawer from '@/components/DocumentDrawer';
import { getVariableConfigs, VariableConfig, postVariableConfigs, deleteVariableConfigs, putVariableConfigs, getRSAConfig, RASConfig } from './services';
import FormModal from './FormModal';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
import './locale';
export default function index() {
@@ -110,64 +111,81 @@ export default function index() {
},
{
title: t('common:table.operations'),
- width: 140,
+ width: 64,
+ fixed: 'right' as const,
render: (record) => {
return (
-
-
-
- {
- deleteVariableConfigs(record.id).then(() => {
- message.success(t('common:success.delete'));
- fetchData();
- });
- }}
- >
-
-
-
+
+
+ {
+ FormModal({
+ title: t('common:btn.clone'),
+ rsaConfig,
+ data: record,
+ onOk: (values) => {
+ return postVariableConfigs(values).then(() => {
+ fetchData();
+ message.success(t('common:success.clone'));
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.clone')}
+
+
+
+ {
+ FormModal({
+ title: t('common:btn.edit'),
+ rsaConfig,
+ data: record,
+ onOk: (values) => {
+ return putVariableConfigs(record.id, values).then(() => {
+ fetchData();
+ message.success(t('common:success.edit'));
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.edit')}
+
+
+
+
+ {
+ Modal.confirm({
+ title: t('common:confirm.delete'),
+ onOk: () => {
+ deleteVariableConfigs(record.id).then(() => {
+ message.success(t('common:success.delete'));
+ fetchData();
+ });
+ },
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+
+ }
+ >
+
+
);
},
},
diff --git a/src/pages/warning/shield/index.tsx b/src/pages/warning/shield/index.tsx
index 6b36d1f56..cb363b598 100644
--- a/src/pages/warning/shield/index.tsx
+++ b/src/pages/warning/shield/index.tsx
@@ -15,15 +15,16 @@
*
*/
import React, { useState, useEffect, useContext } from 'react';
-import { Button, Input, Table, Tooltip, message, Modal, Switch, Space, Tag } from 'antd';
+import { Button, Input, Table, Tooltip, message, Modal, Switch, Space, Tag, Dropdown, Menu } from 'antd';
import { ColumnsType } from 'antd/lib/table';
import { CloseCircleOutlined, ExclamationCircleOutlined, SearchOutlined } from '@ant-design/icons';
import moment from 'moment';
import _ from 'lodash';
import { useTranslation } from 'react-i18next';
import { useHistory, Link } from 'react-router-dom';
+import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
-import Tags from '@/components/Tags';
+import Tags from '@/components/TableTags/Tags';
import PageLayout from '@/components/pageLayout';
import { getBusiGroupsAlertMutes, deleteShields, updateShields } from '@/services/shield';
import { shieldItem, strategyStatus } from '@/store/warningInterface';
@@ -32,7 +33,7 @@ import RefreshIcon from '@/components/RefreshIcon';
import { DatasourceSelect } from '@/components/DatasourceSelect';
import { CommonStateContext } from '@/App';
import usePagination from '@/components/usePagination';
-import { allCates } from '@/components/AdvancedWrap/utils';
+import { allCates, getCateDisplayLabel } from '@/components/AdvancedWrap/utils';
import DeleteMutesModal from './components/DeleteMutesModal';
import './locale';
@@ -52,7 +53,7 @@ interface Filter {
const FILTER_SESSION_STORAGE_KEY = 'alert-mutes-filter';
const Shield: React.FC = () => {
- const { t } = useTranslation('alertMutes');
+ const { t, i18n } = useTranslation('alertMutes');
const history = useHistory();
const { datasourceList, groupedDatasourceList, businessGroup, busiGroups } = useContext(CommonStateContext);
const [gids, setGids] = useState(getDefaultGids(N9E_GIDS_LOCALKEY, businessGroup));
@@ -72,63 +73,62 @@ const Shield: React.FC = () => {
const prev = JSON.parse(window.sessionStorage.getItem(FILTER_SESSION_STORAGE_KEY) || '{}');
window.sessionStorage.setItem(FILTER_SESSION_STORAGE_KEY, JSON.stringify({ ...prev, ...patch }));
};
+ const showBusinessGroup = !(businessGroup.isLeaf && gids !== '-2');
const columns: ColumnsType = _.concat(
- businessGroup.isLeaf && gids !== '-2'
- ? []
- : ([
- {
- title: t('common:business_group'),
- dataIndex: 'group_id',
- render: (id) => {
- return _.find(busiGroups, { id })?.name;
- },
- },
- ] as any),
[
{
title: t('note'),
dataIndex: 'note',
render: (data, record: any) => {
+ const groupName = _.find(busiGroups, { id: record.group_id })?.name;
return (
-
- {data}
-
+
+
+ {data}
+
+ {showBusinessGroup && groupName && {groupName}}
+
);
},
},
- {
- title: t('common:datasource.type'),
- dataIndex: 'cate',
- render: (val) => {
- let logoSrc = _.find(allCates, { value: val })?.logo;
- if (val === 'host') {
- logoSrc = '/image/logos/host.png';
- }
- return
;
- },
- },
+ ] as any,
+ [
{
title: t('common:datasource.id'),
dataIndex: 'datasource_ids',
render(value, record: any) {
if (!value) return '-';
+ const cate = _.find(allCates, { value: record.cate });
+ const cateLabel = record.cate === 'host' ? 'Host' : getCateDisplayLabel(cate, i18n.language);
+ let logoSrc = cate?.logo;
+ if (record.cate === 'host') {
+ logoSrc = '/image/logos/host.png';
+ }
return (
- {
- if (item === 0) return '$all';
- const name = _.find(groupedDatasourceList[record.cate], { id: item })?.name;
- if (!name) return '';
- return name;
- }),
+
+ {logoSrc && (
+
+
+
)}
- />
+ {
+ if (item === 0) return '$all';
+ const name = _.find(groupedDatasourceList[record.cate], { id: item })?.name;
+ if (!name) return '';
+ return name;
+ }),
+ )}
+ />
+
);
},
},
@@ -137,17 +137,11 @@ const Shield: React.FC = () => {
dataIndex: 'tags',
render: (text: any) => {
return (
-
- {text
- ? text.map((tag, index) => {
- return tag ? (
-
{`${tag.key} ${tag.func} ${
- tag.func === 'in' ? tag.value.split(' ').join(', ') : tag.value
- }`}
- ) : null;
- })
- : ''}
-
+ (tag ? `${tag.key} ${tag.func} ${tag.func === 'in' ? tag.value.split(' ').join(', ') : tag.value}` : '')))}
+ />
);
},
},
@@ -237,12 +231,24 @@ const Shield: React.FC = () => {
title: t('common:table.update_at'),
dataIndex: 'update_at',
render: (value) => {
- return moment.unix(value).format('YYYY-MM-DD HH:mm:ss');
+ const m = moment.unix(value);
+ return (
+
+
{m.format('YYYY-MM-DD')}
+
{m.format('HH:mm:ss')}
+
+ );
},
},
{
title: t('common:table.update_by'),
dataIndex: 'update_by',
+ render: (val, record: any) => (
+
+
{val}
+ {record.update_by_nickname &&
{record.update_by_nickname}
}
+
+ ),
},
{
title: t('common:table.enabled'),
@@ -273,60 +279,66 @@ const Shield: React.FC = () => {
title: t('common:table.operations'),
dataIndex: 'operation',
fixed: 'right',
+ width: 64,
render: (text: undefined, record: shieldItem) => {
return (
- <>
-
-
{
- history.push({
- pathname: `/alert-mutes/edit/${record.id}`,
- search: `?mode=clone&bgid=${record.group_id}`,
- });
- }}
- >
- {t('common:btn.clone')}
-
-
{
- confirm({
- title: t('common:confirm.delete'),
- icon:
,
- onOk: () => {
- deleteShields({ ids: [record.id] }, record.group_id).then((res) => {
- refreshList();
- if (res.err) {
- message.success(res.err);
- } else {
- message.success(t('common:success.delete'));
- }
+
+
+ {
+ history.push({
+ pathname: `/alert-mutes/edit/${record.id}`,
+ search: `?mode=clone&bgid=${record.group_id}`,
});
- },
+ }}
+ >
+ {t('common:btn.clone')}
+
+
+
+
+ {
+ confirm({
+ title: t('common:confirm.delete'),
+ icon: ,
+ onOk: () => {
+ deleteShields({ ids: [record.id] }, record.group_id).then((res) => {
+ refreshList();
+ if (res.err) {
+ message.success(res.err);
+ } else {
+ message.success(t('common:success.delete'));
+ }
+ });
+ },
- onCancel() {},
- });
- }}
- >
- {t('common:btn.delete')}
-
-
- >
+ onCancel() {},
+ });
+ }}
+ >
+ {t('common:btn.delete')}
+
+
+
+ }
+ >
+
+
);
},
},
],
);
- const pagination = usePagination({ pageSizeLocalstorageKey: 'alert-mutes-table-pagesize', defaultPageSize: 30, pageSizeOptions: ['30', '50', '100', '300'] });
+ const pagination = usePagination({ pageSizeLocalstorageKey: 'alert-mutes-table-pagesize' });
useEffect(() => {
getList();
diff --git a/src/pages/warning/subscribe/ListNG.tsx b/src/pages/warning/subscribe/ListNG.tsx
index 2f2996436..26edbe931 100644
--- a/src/pages/warning/subscribe/ListNG.tsx
+++ b/src/pages/warning/subscribe/ListNG.tsx
@@ -1,6 +1,6 @@
import React, { useState, useContext, useEffect } from 'react';
import { Button, Input, Table, message, Modal, Space, Switch, Tag, Dropdown, Menu, Tooltip } from 'antd';
-import { ExclamationCircleOutlined, SearchOutlined, EyeOutlined, MoreOutlined } from '@ant-design/icons';
+import { ExclamationCircleOutlined, SearchOutlined, EyeOutlined } from '@ant-design/icons';
import { ColumnsType } from 'antd/lib/table';
import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
@@ -13,7 +13,8 @@ import { CommonStateContext } from '@/App';
import { priorityColor } from '@/utils/constant';
import { DatasourceSelect } from '@/components/DatasourceSelect';
import { strategyStatus } from '@/store/warningInterface';
-import Tags from '@/components/Tags';
+import Tags from '@/components/TableTags/Tags';
+import { allCates, getCateDisplayLabel } from '@/components/AdvancedWrap/utils';
import OrganizeColumns, { getDefaultColumnsConfigs, setDefaultColumnsConfigs, ajustColumns } from '@/components/OrganizeColumns';
import usePagination from '@/components/usePagination';
import { NS as notificationRulesNS } from '@/pages/notificationRules/constants';
@@ -22,6 +23,7 @@ import { getItems as getNotificationRules, RuleItem as NotificationRuleItem } fr
import { defaultColumnsConfigs, LOCAL_STORAGE_KEY } from './constants';
import './locale';
import './index.less';
+import { TableActionButton, TableActionLink, TableActionTrigger } from '@/components/TableActionDropdown';
export { default as Add } from './add';
export { default as Edit } from './edit';
@@ -46,7 +48,7 @@ interface Props {
}
const Subscribe = (props: Props) => {
- const { t } = useTranslation('alertSubscribes');
+ const { t, i18n } = useTranslation('alertSubscribes');
const { datasourceList, busiGroups } = useContext(CommonStateContext);
const { hideBusinessGroupColumn, readonly, headerExtra, data, loading, setRefreshFlag, linkTarget } = props;
const [columnsConfigs, setColumnsConfigs] = useState<{ name: string; visible: boolean }[]>(getDefaultColumnsConfigs(defaultColumnsConfigs, LOCAL_STORAGE_KEY));
@@ -65,52 +67,61 @@ const Subscribe = (props: Props) => {
const [notificationRules, setNotificationRules] = useState();
const columns: ColumnsType = _.concat(
- hideBusinessGroupColumn
- ? []
- : ([
- {
- title: t('common:business_group'),
- dataIndex: 'group_id',
- render: (id) => {
- return _.find(busiGroups, { id })?.name;
- },
- },
- ] as any),
[
{
title: t('note'),
dataIndex: 'note',
render: (data, record: any) => {
+ const groupName = _.find(busiGroups, { id: record.group_id })?.name;
return (
-
- {data}
-
+
+
+ {data}
+
+ {!hideBusinessGroupColumn && groupName && {groupName}}
+
);
},
},
+ ] as any,
+ [
{
title: t('common:datasource.id'),
dataIndex: 'datasource_ids',
- render(value) {
+ render(value, record: any) {
if (!value) return '-';
+ const cate = _.find(allCates, { value: record.cate });
+ const cateLabel = record.cate === 'host' ? 'Host' : getCateDisplayLabel(cate, i18n.language);
+ let logoSrc = cate?.logo;
+ if (record.cate === 'host') {
+ logoSrc = '/image/logos/host.png';
+ }
return (
- {
- if (item === 0) return '$all';
- const name = _.find(datasourceList, { id: item })?.name;
- if (!name) return '';
- return name;
- }),
+
+ {logoSrc && (
+
+
+
)}
- />
+ {
+ if (item === 0) return '$all';
+ const name = _.find(datasourceList, { id: item })?.name;
+ if (!name) return '';
+ return name;
+ }),
+ )}
+ />
+
);
},
},
@@ -119,27 +130,19 @@ const Subscribe = (props: Props) => {
dataIndex: 'severities',
render: (data) => {
return (
- `S${severity}`)}
+ bgColor={(tagname) => {
+ const bgColorMap = { S1: 'var(--fc-red-3)', S2: 'var(--fc-orange-3)', S3: 'var(--fc-yellow-3)' };
+ return bgColorMap[tagname as string] || 'var(--fc-gray-3)';
}}
- >
- {_.map(data, (severity) => {
- return (
-
- S{severity}
-
- );
- })}
-
+ fontColor={(tagname) => {
+ const fontColorMap = { S1: 'var(--fc-red-11)', S2: 'var(--fc-orange-11)', S3: 'var(--fc-yellow-11)' };
+ return fontColorMap[tagname as string] || 'var(--fc-gray-11)';
+ }}
+ />
);
},
},
@@ -157,13 +160,11 @@ const Subscribe = (props: Props) => {
render: (text: any) => {
if (!text) return '-';
return (
- <>
- {text
- ? text.map((tag, index) => {
- return tag ? {`${tag.func} ${_.includes(['in', 'not in'], tag.func) ? tag.value.split(' ').join(', ') : tag.value}`}
: null;
- })
- : ''}
- >
+ (tag ? `${tag.func} ${_.includes(['in', 'not in'], tag.func) ? tag.value.split(' ').join(', ') : tag.value}` : '')))}
+ />
);
},
},
@@ -172,13 +173,11 @@ const Subscribe = (props: Props) => {
dataIndex: 'tags',
render: (text: any) => {
return (
- <>
- {text
- ? text.map((tag, index) => {
- return tag ? {`${tag.key} ${tag.func} ${_.includes(['in', 'not in'], tag.func) ? tag.value.split(' ').join(', ') : tag.value}`}
: null;
- })
- : ''}
- >
+ (tag ? `${tag.key} ${tag.func} ${_.includes(['in', 'not in'], tag.func) ? tag.value.split(' ').join(', ') : tag.value}` : '')))}
+ />
);
},
},
@@ -186,7 +185,7 @@ const Subscribe = (props: Props) => {
title: t('user_groups'),
dataIndex: 'user_groups',
render: (data) => {
- return ;
+ return ;
},
},
{
@@ -194,28 +193,14 @@ const Subscribe = (props: Props) => {
dataIndex: 'notify_rule_ids',
render: (data) => {
return (
-
- {_.map(data, (id) => {
- const val = _.find(notificationRules, { id })?.name || id;
- return (
-
-
-
-
- {val}
-
-
-
-
- );
- })}
-
+
+ type='outline'
+ maxWidth={180}
+ data={data}
+ getKey={(id) => id}
+ getLabel={(id) => _.find(notificationRules, { id })?.name || _.toString(id)}
+ onTagClick={(id) => window.open(`/${notificationRulesNS}/edit/${id}`, '_blank')}
+ />
);
},
},
@@ -237,11 +222,12 @@ const Subscribe = (props: Props) => {
title: t('common:table.username'),
ellipsis: true,
dataIndex: 'update_by',
- },
- {
- title: t('common:table.nickname'),
- ellipsis: true,
- dataIndex: 'update_by_nickname',
+ render: (val, record: any) => (
+
+
{val}
+ {record.update_by_nickname &&
{record.update_by_nickname}
}
+
+ ),
},
],
readonly
@@ -286,35 +272,41 @@ const Subscribe = (props: Props) => {
title: t('common:table.operations'),
dataIndex: 'operation',
fixed: 'right',
+ width: 64,
render: (text: string, record: subscribeItem) => {
return (
-
{t('common:btn.edit')}
-
+
-
{t('common:btn.clone')}
-
+
+
-
+
}
>
- } />
+
);
},
},
],
);
- const pagination = usePagination({ pageSizeLocalstorageKey: 'alert-subscribes-table-pagesize', defaultPageSize: 30, pageSizeOptions: ['30', '50', '100', '300'] });
+ const pagination = usePagination({ pageSizeLocalstorageKey: 'alert-subscribes-table-pagesize' });
const filterData = () => {
const res = _.filter(data, (item: subscribeItem) => {
diff --git a/src/theme/antd.dark.less b/src/theme/antd.dark.less
index bf02e5fa2..aa5222d5c 100644
--- a/src/theme/antd.dark.less
+++ b/src/theme/antd.dark.less
@@ -22002,7 +22002,7 @@ div.ant-table-summary {
transition: all 0.3s;
}
.ant-table-thead th.ant-table-column-has-sorters:hover {
- background: rgb(var(--fc-fill-5-rgb) / 0.4);
+ background: var(--fc-fill-2-5);
}
.ant-table-thead th.ant-table-column-has-sorters:hover::before {
background-color: transparent !important;
@@ -22012,7 +22012,7 @@ div.ant-table-summary {
}
.ant-table-thead th.ant-table-column-has-sorters.ant-table-cell-fix-left:hover,
.ant-table-thead th.ant-table-column-has-sorters.ant-table-cell-fix-right:hover {
- background: var(--fc-fill-3);
+ background: var(--fc-fill-2-5);
}
.ant-table-thead th.ant-table-column-sort {
background: var(--fc-fill-2-5);
@@ -22021,7 +22021,7 @@ div.ant-table-summary {
background-color: transparent !important;
}
td.ant-table-column-sort {
- background: var(--fc-fill-2-5);
+ background: var(--fc-fill-2);
}
.ant-table-column-title {
position: relative;
diff --git a/src/theme/antd.light-blue.less b/src/theme/antd.light-blue.less
index 7de19d88a..75d088f67 100644
--- a/src/theme/antd.light-blue.less
+++ b/src/theme/antd.light-blue.less
@@ -22010,13 +22010,13 @@ div.ant-table-summary {
background: #f5f5f5;
}
.ant-table-thead th.ant-table-column-sort {
- background: #EEF6FE;
+ background: var(--fc-fill-2-5);
}
.ant-table-thead th.ant-table-column-sort::before {
background-color: transparent !important;
}
td.ant-table-column-sort {
- background: #fafafa;
+ background: var(--fc-fill-2);
}
.ant-table-column-title {
position: relative;
diff --git a/src/theme/antd.light-gold.less b/src/theme/antd.light-gold.less
index d8ca8b7f5..980eb6073 100644
--- a/src/theme/antd.light-gold.less
+++ b/src/theme/antd.light-gold.less
@@ -21997,7 +21997,7 @@ div.ant-table-summary {
transition: all 0.3s;
}
.ant-table-thead th.ant-table-column-has-sorters:hover {
- background: rgb(var(--fc-fill-5-rgb) / 0.4);
+ background: var(--fc-fill-2-5);
}
.ant-table-thead th.ant-table-column-has-sorters:hover::before {
background-color: transparent !important;
@@ -22007,7 +22007,7 @@ div.ant-table-summary {
}
.ant-table-thead th.ant-table-column-has-sorters.ant-table-cell-fix-left:hover,
.ant-table-thead th.ant-table-column-has-sorters.ant-table-cell-fix-right:hover {
- background: var(--fc-fill-3);
+ background: var(--fc-fill-2-5);
}
.ant-table-thead th.ant-table-column-sort {
background: var(--fc-fill-2-5);
@@ -22016,7 +22016,7 @@ div.ant-table-summary {
background-color: transparent !important;
}
td.ant-table-column-sort {
- background: var(--fc-fill-2-5);
+ background: var(--fc-fill-2);
}
.ant-table-column-title {
position: relative;
diff --git a/src/theme/default.less b/src/theme/default.less
index 58997d58a..57bf0bef0 100644
--- a/src/theme/default.less
+++ b/src/theme/default.less
@@ -10,7 +10,6 @@ mark {
// 当 table 作为 flex item 时,设置高度为 100%,以便在父容器中填满空间
.n9e-antd-table-height-full {
-
height: 100%;
min-height: 0;
@@ -56,81 +55,131 @@ mark {
}
}
-// 2026-05 table design
-.ant-table-wrapper {
- .ant-table-container {
- border: 1px solid var(--fc-border-color) !important;
- border-radius: 8px !important;
- overflow: hidden;
+// 2026-03 release-23 版本 强制给表格添加边框和圆角
+.ant-table-container {
+ border: 1px solid var(--fc-border-color) !important;
+ border-radius: 8px !important;
+}
+
+.fc-table-action-dropdown {
+ .ant-dropdown-menu {
+ min-width: 112px;
+ padding: 8px 0;
+ border-radius: 8px;
}
- tr.ant-table-measure-row {
- visibility: collapse;
+ .ant-dropdown-menu-item {
+ padding: 0;
+ line-height: normal;
}
- .ant-table-tbody .ant-table-cell-fix-left,
- .ant-table-tbody .ant-table-cell-fix-right {
- background: inherit;
+ .ant-dropdown-menu-item-divider {
+ margin: 4px 0;
+ background-color: var(--fc-border-color);
}
- .ant-table-thead > tr > th.ant-table-cell-fix-left,
- .ant-table-thead > tr > th.ant-table-cell-fix-right {
- background: var(--fc-fill-2-5);
+ .fc-table-action-menu-button {
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ width: 100%;
+ height: 32px;
+ padding: 0 16px;
+ color: var(--fc-text-3);
+ font-size: 12px;
+ font-weight: 500;
+ text-align: left;
}
- .ant-table-thead > tr > th,
- .ant-table-tbody > tr > td,
- .ant-table tfoot > tr > th,
- .ant-table tfoot > tr > td {
- border-bottom-color: var(--fc-border-color);
+ .fc-table-action-menu-link {
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ width: 100%;
+ height: 32px;
+ padding: 0 16px;
+ color: var(--fc-text-3);
+ font-size: 12px;
+ font-weight: 500;
+ line-height: 32px;
}
- .ant-table.ant-table-bordered {
- > .ant-table-title,
- > .ant-table-footer,
- > .ant-table-container {
- border-color: var(--fc-border-color);
- }
+ .fc-table-action-menu-icon {
+ display: inline-flex;
+ flex: none;
+ width: 16px;
+ height: 16px;
+ margin-right: 12px;
+ font-size: 16px;
+ line-height: 1;
+ stroke-width: 2;
+ }
- > .ant-table-container {
- > .ant-table-content,
- > .ant-table-header,
- > .ant-table-body,
- > .ant-table-summary {
- > table {
- > thead > tr > th,
- > tbody > tr > td,
- > tfoot > tr > th,
- > tfoot > tr > td {
- border-right-color: var(--fc-border-color);
- }
- }
- }
-
- > .ant-table-content,
- > .ant-table-header {
- > table {
- border-top-color: var(--fc-border-color);
- }
- }
- }
+ .fc-table-action-menu-button:hover,
+ .fc-table-action-menu-button:focus,
+ .fc-table-action-menu-link:hover,
+ .fc-table-action-menu-link:focus {
+ color: var(--fc-text-2);
}
- .ant-table-tbody > tr.ant-table-row-selected > td {
- color: inherit;
- background: rgb(var(--fc-fill-5-rgb) / 0.15);
+ .fc-table-action-menu-button.ant-btn-dangerous {
+ color: var(--fc-fill-error);
}
- .ant-table-tbody > tr.ant-table-row-selected:hover > td {
- background: rgb(var(--fc-fill-5-rgb) / 0.25);
+ .fc-table-action-menu-button.ant-btn-dangerous:hover,
+ .fc-table-action-menu-button.ant-btn-dangerous:focus {
+ color: color-mix(in srgb, var(--fc-fill-error) 82%, #000);
}
- .ant-table-tbody > tr.ant-table-row-selected > td.ant-table-column-sort {
- background: rgb(var(--fc-fill-5-rgb) / 0.15);
+ .fc-table-action-menu-button[disabled],
+ .fc-table-action-menu-button[disabled]:hover,
+ .fc-table-action-menu-button.ant-btn-dangerous[disabled],
+ .fc-table-action-menu-button.ant-btn-dangerous[disabled]:hover {
+ color: var(--fc-text-4);
}
+}
- .ant-table-tbody > tr.ant-table-row-selected:hover > td.ant-table-column-sort {
- background: rgb(var(--fc-fill-5-rgb) / 0.25);
+// 2026-05 table 设计规范:排序 icon 替换为线性箭头,hover 横向并排 ↑↓,已排序只显示当前方向
+.ant-table-column-sorter {
+ .ant-table-column-sorter-inner {
+ flex-direction: row;
+ align-items: center;
+ gap: 2px;
+ }
+
+ .ant-table-column-sorter-up,
+ .ant-table-column-sorter-down {
+ width: 12px;
+ height: 12px;
+ background-color: currentColor;
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-position: center;
+ -webkit-mask-size: contain;
+ mask-repeat: no-repeat;
+ mask-position: center;
+ mask-size: contain;
+
+ svg {
+ display: none;
+ }
+ }
+
+ .ant-table-column-sorter-up {
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='64 64 896 896'%3E%3Cpath d='M868 545.5L536.1 163a31.96 31.96 0 00-48.3 0L156 545.5a7.97 7.97 0 006 13.2h81c4.6 0 9-2 12.1-5.5L474 300.9V864c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V300.9l218.9 252.3c3 3.5 7.4 5.5 12.1 5.5h81c6.8 0 10.5-8 6-13.2z'/%3E%3C/svg%3E");
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='64 64 896 896'%3E%3Cpath d='M868 545.5L536.1 163a31.96 31.96 0 00-48.3 0L156 545.5a7.97 7.97 0 006 13.2h81c4.6 0 9-2 12.1-5.5L474 300.9V864c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V300.9l218.9 252.3c3 3.5 7.4 5.5 12.1 5.5h81c6.8 0 10.5-8 6-13.2z'/%3E%3C/svg%3E");
+ }
+
+ .ant-table-column-sorter-down {
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='64 64 896 896'%3E%3Cpath d='M862 465.3h-81c-4.6 0-9 2-12.1 5.5L550 723.1V160c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v563.1L255.1 470.8c-3-3.5-7.4-5.5-12.1-5.5h-81c-6.8 0-10.5 8.1-6 13.2L487.9 861a31.96 31.96 0 0048.3 0L868 478.5c4.5-5.2.8-13.2-6-13.2z'/%3E%3C/svg%3E");
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='64 64 896 896'%3E%3Cpath d='M862 465.3h-81c-4.6 0-9 2-12.1 5.5L550 723.1V160c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v563.1L255.1 470.8c-3-3.5-7.4-5.5-12.1-5.5h-81c-6.8 0-10.5 8.1-6 13.2L487.9 861a31.96 31.96 0 0048.3 0L868 478.5c4.5-5.2.8-13.2-6-13.2z'/%3E%3C/svg%3E");
+ }
+}
+
+// 已排序时,非活跃方向的箭头隐藏不占空间
+.ant-table-column-has-sorters .ant-table-column-sorter-inner {
+ &:has(.ant-table-column-sorter-up.active) .ant-table-column-sorter-down,
+ &:has(.ant-table-column-sorter-down.active) .ant-table-column-sorter-up {
+ display: none;
}
}
@@ -170,7 +219,7 @@ mark {
}
.n9e-checkbox-padding-right-0 {
- .ant-checkbox+span {
+ .ant-checkbox + span {
padding-right: 0 !important;
}
}
@@ -244,7 +293,6 @@ mark {
&::-webkit-scrollbar-thumb {
visibility: visible;
}
-
}
&::-webkit-scrollbar-corner {
diff --git a/vite.config.ts b/vite.config.ts
index 8fd6c8d6d..38e8797a6 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -148,10 +148,10 @@ export default defineConfig(({ mode }) => {
'table-header-bg': 'var(--fc-fill-2-5)',
'table-header-color': 'var(--fc-text-3)',
'table-header-sort-bg': 'var(--fc-fill-2-5)',
- 'table-body-sort-bg': 'var(--fc-fill-2-5)',
+ 'table-body-sort-bg': 'var(--fc-fill-2)',
'table-row-hover-bg': 'rgb(var(--fc-fill-5-rgb) / 0.2)',
'table-selected-row-color': 'inherit',
- // Keep Less color functions compile-safe; runtime CSS vars are patched in theme/default.less.
+ // AntD calls color functions on selected/border tokens; patch runtime CSS vars in theme/default.less.
'table-selected-row-bg': 'rgba(228, 228, 231, 0.15)',
'table-body-selected-sort-bg': '@table-selected-row-bg',
'table-selected-row-hover-bg': 'rgba(228, 228, 231, 0.25)',
@@ -171,8 +171,8 @@ export default defineConfig(({ mode }) => {
'table-font-size-md': '14px',
'table-font-size-sm': '@table-font-size',
'table-header-cell-split-color': 'var(--fc-border-color)',
- 'table-header-sort-active-bg': 'rgb(var(--fc-fill-5-rgb) / 0.4)',
- 'table-fixed-header-sort-active-bg': 'var(--fc-fill-3)',
+ 'table-header-sort-active-bg': 'var(--fc-fill-2-5)',
+ 'table-fixed-header-sort-active-bg': 'var(--fc-fill-2-5)',
'border-radius-base': '8px',
'border-radius-sm': '4px',
'checkbox-border-radius': '2px',