diff --git a/src/client/components/EditableText.tsx b/src/client/components/EditableText.tsx new file mode 100644 index 0000000..f44c696 --- /dev/null +++ b/src/client/components/EditableText.tsx @@ -0,0 +1,38 @@ +import { Input } from 'antd'; +import clsx from 'clsx'; +import React, { useState } from 'react'; +import { useWatch } from '../hooks/useWatch'; + +interface EditableTextProps { + className?: string; + enable?: boolean; + defaultValue: string; + onSave: (text: string) => void; +} +export const EditableText: React.FC = React.memo((props) => { + const [text, setText] = useState(props.defaultValue); + const enable = props.enable ?? true; + + useWatch([props.defaultValue], () => { + setText(props.defaultValue); + }); + + return ( + <> + {enable ? ( + setText(e.target.value)} + onBlur={(e) => props.onSave(e.target.value)} + /> + ) : ( + {text} + )} + + ); +}); +EditableText.displayName = 'EditableText'; diff --git a/src/client/components/dashboard/Grid.tsx b/src/client/components/dashboard/Grid.tsx index de26883..ee46b2d 100644 --- a/src/client/components/dashboard/Grid.tsx +++ b/src/client/components/dashboard/Grid.tsx @@ -23,6 +23,7 @@ export const DashboardGrid: React.FC = React.memo( className={clsx('layout', isEditMode && 'select-none')} layouts={layouts} rowHeight={50} + draggableCancel=".non-draggable" isDraggable={isEditMode} isResizable={isEditMode} breakpoints={{ lg: 1200, md: 768, sm: 0 }} diff --git a/src/client/components/dashboard/items/index.tsx b/src/client/components/dashboard/items/index.tsx index 0a21daa..925fb09 100644 --- a/src/client/components/dashboard/items/index.tsx +++ b/src/client/components/dashboard/items/index.tsx @@ -2,7 +2,7 @@ import { useMemo } from 'react'; import { DashboardItem, useDashboardStore } from '../../../store/dashboard'; import { WebsiteOverviewItem } from './WebsiteOverviewItem'; import { NotFoundTip } from '../../NotFoundTip'; -import { Button, Card } from 'antd'; +import { Button, Card, Input, Typography } from 'antd'; import React from 'react'; import { DeleteOutlined } from '@ant-design/icons'; import { useEvent } from '../../../hooks/useEvent'; @@ -11,13 +11,14 @@ import { MonitorHealthBarItem } from './MonitorHealthBarItem'; import { MonitorMetricsItem } from './MonitorMetricsItem'; import { MonitorChartItem } from './MonitorChartItem'; import { MonitorEventsItem } from './MonitorEventsItem'; +import { EditableText } from '../../EditableText'; interface DashboardGridItemProps { item: DashboardItem; } export const DashboardGridItem: React.FC = React.memo( (props) => { - const { isEditMode, removeItem } = useDashboardStore(); + const { isEditMode, removeItem, changeItemTitle } = useDashboardStore(); const { key, id, title, type } = props.item; const inner = useMemo(() => { @@ -40,7 +41,6 @@ export const DashboardGridItem: React.FC = React.memo( const handleDelete = useEvent( (e: React.MouseEvent) => { - console.log('e', e, key); e.stopPropagation(); removeItem(key); } @@ -49,7 +49,14 @@ export const DashboardGridItem: React.FC = React.memo( return ( changeItemTitle(key, text)} + /> + } headStyle={{ padding: 10, minHeight: 40 }} bodyStyle={{ padding: 10 }} extra={ diff --git a/src/client/hooks/useWatch.ts b/src/client/hooks/useWatch.ts index 0cadf90..3b47331 100644 --- a/src/client/hooks/useWatch.ts +++ b/src/client/hooks/useWatch.ts @@ -2,7 +2,7 @@ import { DependencyList, useLayoutEffect } from 'react'; import { useEvent } from './useEvent'; /** - * 监听变更并触发回调 + * Listen for changes and trigger callbacks */ export function useWatch(deps: DependencyList, cb: () => void) { const memoizedFn = useEvent(cb); diff --git a/src/client/store/dashboard.ts b/src/client/store/dashboard.ts index 5183cc1..9ad3e98 100644 --- a/src/client/store/dashboard.ts +++ b/src/client/store/dashboard.ts @@ -25,6 +25,7 @@ interface DashboardState { items: DashboardItem[]; addItem: (type: DashboardItemType, id: string, title: string) => void; removeItem: (key: string) => void; + changeItemTitle: (key: string, title: string) => void; } export const defaultBlankLayouts = { @@ -69,6 +70,22 @@ export const useDashboardStore = create((set, get) => ({ }; }); }, + changeItemTitle: (key: string, title: string) => { + set((state) => { + return { + items: state.items.map((item) => { + if (item.key === key) { + return { + ...item, + title, + }; + } else { + return item; + } + }), + }; + }); + }, })); export const defaultItemLayout: Record> = { diff --git a/src/server/model/notification/token/index.ts b/src/server/model/notification/token/index.ts index a557d7d..e2df7c5 100644 --- a/src/server/model/notification/token/index.ts +++ b/src/server/model/notification/token/index.ts @@ -11,7 +11,7 @@ import { TitleContentToken, } from './type'; -export { ContentToken }; +export type { ContentToken }; export const token = { text: (content: string): TextContentToken => ({