Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
a08069c
fix(table): set table-body-sort-bg per design spec
Fiona2016 May 12, 2026
5ff8a6d
fix(table): force header nowrap per design rule §5
Fiona2016 May 12, 2026
ee0c0cc
fix(table): default pageSize 15 on alert-mutes / alert-subscribes / j…
Fiona2016 May 12, 2026
1d3dedc
fix(alert-subscribes): combine name + business group into Column1
Fiona2016 May 12, 2026
f06da5e
fix(alert-mutes): collapse name + datasource type + business group in…
Fiona2016 May 12, 2026
53afed2
fix(job-tpls): collapse title + ID + business group into Column1
Fiona2016 May 12, 2026
efa0f94
fix(job-tasks): collapse title + ID + business group into Column1
Fiona2016 May 12, 2026
3d661d8
fix(users): collapse identity columns into Column1
Fiona2016 May 12, 2026
f5b951b
fix(alert-rules): collapse name + cate + business group + severity in…
Fiona2016 May 12, 2026
69be9a3
fix(table): consolidate row actions into overflow menus
Fiona2016 May 13, 2026
44bce41
fix(table): use overflow menus on route list pages
Fiona2016 May 13, 2026
412fdac
fix(table): collapse remaining menu route actions
Fiona2016 May 13, 2026
ad19f99
feat(table): add shared action dropdown
Fiona2016 May 13, 2026
194da29
fix(table): align ai config actions
Fiona2016 May 13, 2026
0555ce2
fix(table): align notification actions
Fiona2016 May 13, 2026
e44a95f
fix(table): align alert event actions
Fiona2016 May 13, 2026
2fc3e1f
fix(table): align builtin component actions
Fiona2016 May 13, 2026
77a7986
fix(table): align data route actions
Fiona2016 May 13, 2026
d39465f
fix(table): align task and user actions
Fiona2016 May 13, 2026
e5b4a5b
fix(table): forward action dropdown trigger events
Fiona2016 May 13, 2026
573387d
Merge remote-tracking branch 'origin/main' into feat-table-design-srm…
Fiona2016 May 14, 2026
84b5a39
Merge remote-tracking branch 'origin/main' into feat-table-design-srm…
Fiona2016 May 15, 2026
439d4f1
refactor(table): compact primary list metadata columns
Fiona2016 May 15, 2026
d29310e
feat(table): refine users list primary column
Fiona2016 May 17, 2026
920cd99
feat(table): refine sorter interaction
Fiona2016 May 18, 2026
1934313
feat(table): unify route table tags
Fiona2016 May 18, 2026
0871dc4
style(table): align sorted column body bg with header
Fiona2016 May 18, 2026
1d4e465
fix(table): keep fixed cells opaque
Fiona2016 May 18, 2026
fab7e0a
feat(table): fix route table action columns
Fiona2016 May 18, 2026
617fcfe
fix(table): remove measure-row collapse and tune fixed-column edge
Fiona2016 May 18, 2026
73b5a4c
fix(table): stabilize task table layouts
Fiona2016 May 18, 2026
552d2b4
fix(table): refine dropdown interactions and sorter style
Fiona2016 May 18, 2026
46c0542
fix(table): align sorter icon with title
Fiona2016 May 18, 2026
8142e2e
fix(table): use fill-2-5 for sorted column bg
Fiona2016 May 18, 2026
dad392d
fix(table): remove sorted column color override
Fiona2016 May 18, 2026
f74a5cc
feat(alerts): add event tag collapse toggle
Fiona2016 May 18, 2026
5de23be
fix(table): apply acceptance feedback on 0517
Fiona2016 May 20, 2026
0691219
feat(table): normalize table action dropdown alignment and trigger
jsers May 20, 2026
60ac063
fix(table): comment out selected row styles to prevent fixed column b…
jsers May 20, 2026
1a8f2d9
feat(alertRules): replace event count column icons with Tags component
jsers May 20, 2026
79c38e1
refactor(tags): relocate Tags component to shared directory and adopt…
jsers May 20, 2026
3bf95de
feat(alertRules): replace TableTags with generic Tags and add severit…
jsers May 20, 2026
a53ed5c
refactor(alertRules): render null instead of '-' for empty datasource…
jsers May 20, 2026
d27dde7
refactor(table): unify table styling and Tags component usage
jsers May 20, 2026
5338bb0
refactor(table): unify tag rendering and replace TableTags with Tags …
jsers May 21, 2026
0d17533
refactor: add explicit type annotations to callback parameters
jsers May 21, 2026
e6cd901
Merge remote-tracking branch 'origin/main' into feat-table-design-srm…
Fiona2016 May 22, 2026
1cd69fa
Merge remote-tracking branch 'origin/main' into feat-table-design-srm…
Fiona2016 May 26, 2026
b781a7c
fix(table): add shared sorter icon theme
Fiona2016 May 26, 2026
130e222
fix(table): use move icons for sorted columns
Fiona2016 May 26, 2026
20498d2
fix(table): scope sorter icon style to accepted tables
Fiona2016 May 26, 2026
f4dd39e
fix(table): opt in sortable fe tables
Fiona2016 May 26, 2026
5977c84
Revert "fix(table): opt in sortable fe tables"
Fiona2016 May 27, 2026
4ae5372
fix(table): use global sorter icon theme
Fiona2016 May 27, 2026
1076c25
fix(table): collapse remaining row actions into dropdown
Fiona2016 May 31, 2026
fdc085c
feat(table): surface frequent row actions as inline icons beside the …
Fiona2016 May 31, 2026
45825fb
Merge pull request #2117 from n9e/feat-table-action-expose-0531
Fiona2016 May 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions src/App.less
Original file line number Diff line number Diff line change
Expand Up @@ -381,26 +381,6 @@ input::placeholder {
}
}

// antd表格排序icon特殊处理
.ant-table-column-has-sorters .ant-table-column-sorter-inner {
.ant-table-column-sorter-up,
.ant-table-column-sorter-down {
transition: all 0.2s;
}

&:has(.ant-table-column-sorter-up.active) {
.ant-table-column-sorter-down {
opacity: 0;
}
}

&:has(.ant-table-column-sorter-down.active) {
.ant-table-column-sorter-up {
opacity: 0;
}
}
}

.theme-light.theme-light-gold {
.login-main.integration {
.ant-btn-primary {
Expand Down
114 changes: 64 additions & 50 deletions src/components/Contacts/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react';
import { Drawer, Table, Switch, Space, Button, Modal, message } from 'antd';
import { Drawer, Table, Switch, Space, Button, Modal, Dropdown, Menu, message } from 'antd';
import { TableActionButton, TableActionTrigger } from '@/components/TableActionDropdown';
import { useTranslation } from 'react-i18next';
import _ from 'lodash';
import { CloseOutlined } from '@ant-design/icons';
Expand Down Expand Up @@ -97,59 +98,72 @@ export default function ContactDrawer(props: Props) {
},
{
title: t('common:table.operations'),
width: 100,
width: 64,
fixed: 'right' as const,
render: (reocrd) => {
return (
<Space>
<a
onClick={() => {
EditModal({
initialValues: reocrd,
onOk: (values) => {
const oldIndex = _.findIndex(data, (item) => item.ident === reocrd.ident);
const newData = _.map(data, (item, idx) => {
if (idx === oldIndex) {
return values;
}
return item;
});
putNotifyContacts(newData).then(() => {
setData(newData);
message.success(t('common:success.edit'));
});
},
});
}}
>
{t('common:btn.edit')}
</a>
{!reocrd.built_in && (
<Button
size='small'
type='link'
danger
style={{
padding: 0,
}}
onClick={() => {
Modal.confirm({
title: t('common:confirm.delete'),
onOk: () => {
const newData = _.filter(data, (item) => item.ident !== reocrd.ident);
putNotifyContacts(newData).then(() => {
setData(newData);
message.success(t('common:success.delete'));
<Dropdown
trigger={['click']}
overlayClassName='fc-table-action-dropdown'
overlay={
<Menu>
<Menu.Item>
<TableActionButton
actionIcon='edit'
onClick={() => {
EditModal({
initialValues: reocrd,
onOk: (values) => {
const oldIndex = _.findIndex(data, (item) => item.ident === reocrd.ident);
const newData = _.map(data, (item, idx) => {
if (idx === oldIndex) {
return values;
}
return item;
});
putNotifyContacts(newData).then(() => {
setData(newData);
message.success(t('common:success.edit'));
});
},
});
},
}}
>
{t('common:btn.edit')}
</TableActionButton>
</Menu.Item>
{!reocrd.built_in && (
<>
<Menu.Divider />
<Menu.Item>
<TableActionButton
actionIcon='delete'
danger
onClick={() => {
Modal.confirm({
title: t('common:confirm.delete'),
onOk: () => {
const newData = _.filter(data, (item) => item.ident !== reocrd.ident);
putNotifyContacts(newData).then(() => {
setData(newData);
message.success(t('common:success.delete'));
});
},

onCancel() {},
});
}}
>
{t('common:btn.delete')}
</Button>
)}
</Space>
onCancel() {},
});
}}
>
{t('common:btn.delete')}
</TableActionButton>
</Menu.Item>
</>
)}
</Menu>
}
>
<TableActionTrigger />
</Dropdown>
);
},
},
Expand Down
96 changes: 96 additions & 0 deletions src/components/TableActionDropdown/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React from 'react';
import { Button, Tooltip } from 'antd';
import type { ButtonProps } from 'antd/lib/button';
import {
CheckCircle,
Copy,
ExternalLink,
Eye,
Link as LinkIcon,
MoreVertical,
Network,
Pencil,
Play,
Search,
Settings,
ShieldCheck,
Sparkles,
Trash2,
} from 'lucide-react';
import classNames from 'classnames';
import { Link, LinkProps } from 'react-router-dom';

import './style.less';

const tableActionIconMap = {
default: CheckCircle,
edit: Pencil,
view: Eye,
settings: Settings,
access: Network,
permission: ShieldCheck,
copy: Copy,
delete: Trash2,
run: Play,
search: Search,
open: ExternalLink,
link: LinkIcon,
ai: Sparkles,
};

export type TableActionIconName = keyof typeof tableActionIconMap;

export function TableActionIcon({ name }: { name: TableActionIconName }) {
const Icon = tableActionIconMap[name];
return <Icon className='fc-table-action-menu-icon' />;
}

interface TableActionButtonProps extends Omit<ButtonProps, 'icon'> {
actionIcon?: TableActionIconName;
icon?: React.ReactNode;
}

export function TableActionButton({ actionIcon, icon, className, type = 'link', ...rest }: TableActionButtonProps) {
return (
<Button
type={type}
className={classNames('fc-table-action-menu-button', className)}
icon={icon || (actionIcon ? <TableActionIcon name={actionIcon} /> : undefined)}
{...rest}
/>
);
}

interface TableActionIconButtonProps extends Omit<ButtonProps, 'icon' | 'title'> {
actionIcon: TableActionIconName;
title: React.ReactNode;
}

export function TableActionIconButton({ actionIcon, title, className, type = 'text', ...rest }: TableActionIconButtonProps) {
return (
<Tooltip title={title}>
<Button type={type} className={classNames('fc-table-action-icon-btn', className)} icon={<TableActionIcon name={actionIcon} />} {...rest} />
</Tooltip>
);
}

export function TableActionCell({ children, className }: { children: React.ReactNode; className?: string }) {
return <div className={classNames('fc-table-action-cell', className)}>{children}</div>;
}

interface TableActionLinkProps extends LinkProps {
actionIcon?: TableActionIconName;
}

export function TableActionLink({ actionIcon, className, children, ...rest }: TableActionLinkProps) {
return (
<Link className={classNames('fc-table-action-menu-link', className)} {...rest}>
{actionIcon && <TableActionIcon name={actionIcon} />}
<span>{children}</span>
</Link>
);
}

export const TableActionTrigger = React.forwardRef<HTMLElement, ButtonProps>(function TableActionTrigger({ type = 'text', icon, ...rest }, ref) {
return <Button ref={ref as any} type={type} icon={icon || <MoreVertical size={16} />} {...rest} />;
});
116 changes: 116 additions & 0 deletions src/components/TableActionDropdown/style.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
.fc-table-action-dropdown {
.ant-dropdown-menu {
min-width: 112px;
padding: 8px 0;
border-radius: 8px;
}

.ant-dropdown-menu-item {
padding: 0;
line-height: normal;
}

.ant-dropdown-menu-item-divider {
margin: 4px 0;
background-color: var(--fc-border-color);
}

.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;
}

.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;
}

.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;
}

.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);
}

.fc-table-action-menu-button.ant-btn-dangerous {
color: var(--fc-fill-error);
}

.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);
}

.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);
}
}

// 行内暴露的特色操作图标(与 3 个点的 dropdown 并排)
.fc-table-action-cell {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 4px;
}

.fc-table-action-icon-btn.ant-btn {
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
padding: 0;
color: var(--fc-text-3);

.fc-table-action-menu-icon {
width: 16px;
height: 16px;
margin: 0;
stroke-width: 2;
}

&:hover,
&:focus {
color: var(--fc-text-2);
}

&.ant-btn-dangerous {
color: var(--fc-fill-error);
}

&[disabled],
&[disabled]:hover {
color: var(--fc-text-4);
}
}
Loading