buster/apps/web/src/controllers/DashboardController/DashboardViewDashboardContr.../DashboardEditTitle.tsx

83 lines
2.6 KiB
TypeScript
Raw Normal View History

import React, { useEffect, useRef } from 'react';
2025-08-31 14:20:30 +08:00
import { useUpdateDashboard } from '@/api/buster_rest/dashboards';
import { InputTextArea, type InputTextAreaRef } from '@/components/ui/inputs/InputTextArea';
2025-08-31 14:20:30 +08:00
import { EditableTitle } from '@/components/ui/typography/EditableTitle';
import { useDebounce } from '@/hooks/useDebounce';
2025-08-31 14:20:30 +08:00
import { useMount } from '@/hooks/useMount';
import { useSize } from '@/hooks/useSize';
2025-08-31 14:20:30 +08:00
2025-09-02 06:30:34 +08:00
export const DASHBOARD_TITLE_INPUT_ID = (dashboardId: string) => `${dashboardId}-title-input`;
2025-08-31 14:20:30 +08:00
const DEFAULT_TITLE = 'Untitled Dashboard';
export const DashboardEditTitles: React.FC<{
title: string;
description: string;
readOnly?: boolean;
dashboardId: string;
}> = React.memo(({ readOnly, title, description, dashboardId }) => {
const titleRef = useRef<HTMLInputElement>(null);
const inputTextAreaRef = useRef<InputTextAreaRef>(null);
const size = useSize(titleRef);
const debouncedWidth = useDebounce(size?.width, { wait: 50, maxWait: 85 });
2025-08-31 14:20:30 +08:00
const { mutateAsync: onUpdateDashboard } = useUpdateDashboard({
saveToServer: false,
});
const onChangeTitle = (name: string) => {
if (!readOnly) onUpdateDashboard({ name, id: dashboardId, description });
};
const onChangeDashboardDescription = (value: React.ChangeEvent<HTMLTextAreaElement>) => {
if (!readOnly) {
2025-08-31 14:20:30 +08:00
onUpdateDashboard({ description: value.target.value, id: dashboardId, name: title });
}
2025-08-31 14:20:30 +08:00
};
useMount(() => {
const isDefaultTitle = title === DEFAULT_TITLE;
if (isDefaultTitle && titleRef.current) {
titleRef.current.focus();
titleRef.current.select();
}
});
useEffect(() => {
if (debouncedWidth) {
inputTextAreaRef.current?.forceRecalculateHeight();
}
}, [debouncedWidth]);
2025-08-31 14:20:30 +08:00
return (
<div className="flex flex-col space-y-1.5">
<EditableTitle
ref={titleRef}
className="w-full truncate"
readOnly={readOnly}
onSetValue={onChangeTitle}
onChange={onChangeTitle}
2025-09-02 06:30:34 +08:00
id={DASHBOARD_TITLE_INPUT_ID(dashboardId)}
2025-08-31 14:20:30 +08:00
placeholder="New dashboard"
level={3}
>
{title}
</EditableTitle>
{(description || !readOnly) && (
<InputTextArea
ref={inputTextAreaRef}
2025-08-31 14:20:30 +08:00
variant="ghost"
readOnly={false}
2025-08-31 14:20:30 +08:00
onChange={onChangeDashboardDescription}
value={description}
minRows={1}
maxRows={25}
2025-09-16 05:26:30 +08:00
className={'py-0! pl-0! text-gray-dark!'}
2025-08-31 14:20:30 +08:00
placeholder="Add description..."
/>
)}
</div>
);
});
DashboardEditTitles.displayName = 'DashboardEditTitles';