diff --git a/frontend/components/admin/dashboard/WidgetConfigSidebar.tsx b/frontend/components/admin/dashboard/WidgetConfigSidebar.tsx index 7ca9684b..d126d8d9 100644 --- a/frontend/components/admin/dashboard/WidgetConfigSidebar.tsx +++ b/frontend/components/admin/dashboard/WidgetConfigSidebar.tsx @@ -17,6 +17,7 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Switch } from "@/components/ui/switch"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { DatabaseConfig } from "./data-sources/DatabaseConfig"; import { ApiConfig } from "./data-sources/ApiConfig"; import { QueryEditor } from "./QueryEditor"; @@ -146,6 +147,9 @@ export function WidgetConfigSidebar({ element, isOpen, onClose, onApply }: Widge // 커스텀 메트릭 설정 const [customMetricConfig, setCustomMetricConfig] = useState({}); + // 자동 새로고침 간격 (지도 위젯용) + const [refreshInterval, setRefreshInterval] = useState(5); + // 사이드바 열릴 때 초기화 useEffect(() => { if (isOpen && element) { @@ -155,6 +159,8 @@ export function WidgetConfigSidebar({ element, isOpen, onClose, onApply }: Widge // dataSources는 element.dataSources 또는 chartConfig.dataSources에서 가져옴 setDataSources(element.dataSources || element.chartConfig?.dataSources || []); setQueryResult(null); + // 자동 새로고침 간격 초기화 + setRefreshInterval(element.chartConfig?.refreshInterval ?? 5); // 리스트 위젯 설정 초기화 if (element.subtype === "list-v2" && element.listConfig) { @@ -290,6 +296,24 @@ export function WidgetConfigSidebar({ element, isOpen, onClose, onApply }: Widge element.subtype === "custom-metric-v2" || element.subtype === "risk-alert-v2"; + // chartConfig 구성 (위젯 타입별로 다르게 처리) + let finalChartConfig = { ...chartConfig }; + + if (isMultiDataSourceWidget) { + finalChartConfig = { + ...finalChartConfig, + dataSources: dataSources, + }; + } + + // 지도 위젯인 경우 refreshInterval 추가 + if (element.subtype === "map-summary-v2") { + finalChartConfig = { + ...finalChartConfig, + refreshInterval, + }; + } + const updatedElement: DashboardElement = { ...element, customTitle: customTitle.trim() || undefined, @@ -302,8 +326,6 @@ export function WidgetConfigSidebar({ element, isOpen, onClose, onApply }: Widge ...(isMultiDataSourceWidget ? { dataSources: dataSources, - // chartConfig에도 dataSources 포함 (일부 위젯은 chartConfig에서 읽음) - chartConfig: { ...chartConfig, dataSources: dataSources }, } : {}), } @@ -314,21 +336,10 @@ export function WidgetConfigSidebar({ element, isOpen, onClose, onApply }: Widge listConfig, } : {}), - // 차트 설정 (차트 타입이거나 차트 기능이 있는 위젯) - ...(element.type === "chart" || - element.subtype === "chart" || - ["bar", "horizontal-bar", "pie", "line", "area", "stacked-bar", "donut", "combo"].includes(element.subtype) + // 차트 설정 (모든 위젯 공통) + ...(needsDataSource(element.subtype) ? { - // 다중 데이터 소스 위젯은 chartConfig에 dataSources 포함 (빈 배열도 허용 - 연결 해제) - chartConfig: isMultiDataSourceWidget - ? { ...chartConfig, dataSources: dataSources } - : chartConfig, - // 프론트엔드 호환성을 위해 dataSources도 element에 직접 포함 (빈 배열도 허용 - 연결 해제) - ...(isMultiDataSourceWidget - ? { - dataSources: dataSources, - } - : {}), + chartConfig: finalChartConfig, } : {}), // 커스텀 메트릭 설정 @@ -356,6 +367,7 @@ export function WidgetConfigSidebar({ element, isOpen, onClose, onApply }: Widge listConfig, chartConfig, customMetricConfig, + refreshInterval, onApply, onClose, ]); @@ -432,6 +444,40 @@ export function WidgetConfigSidebar({ element, isOpen, onClose, onApply }: Widge + + {/* 자동 새로고침 설정 (지도 위젯 전용) */} + {element.subtype === "map-summary-v2" && ( +
+ + +

+ 위젯의 모든 데이터를 자동으로 갱신하는 주기를 설정합니다 +

+
+ )} diff --git a/frontend/components/admin/dashboard/data-sources/MultiApiConfig.tsx b/frontend/components/admin/dashboard/data-sources/MultiApiConfig.tsx index c72cb18e..2aba31f8 100644 --- a/frontend/components/admin/dashboard/data-sources/MultiApiConfig.tsx +++ b/frontend/components/admin/dashboard/data-sources/MultiApiConfig.tsx @@ -530,30 +530,6 @@ export default function MultiApiConfig({ dataSource, onChange, onTestResult }: M ))} - {/* 마커 polling 간격 설정 (MapTestWidgetV2 전용) */} -
- - -

- 마커 데이터를 자동으로 갱신하는 주기를 설정합니다 -

-
{/* 마커 종류 선택 (MapTestWidgetV2 전용) */}
diff --git a/frontend/components/admin/dashboard/data-sources/MultiDatabaseConfig.tsx b/frontend/components/admin/dashboard/data-sources/MultiDatabaseConfig.tsx index 73b2ab4b..bdf6b6b0 100644 --- a/frontend/components/admin/dashboard/data-sources/MultiDatabaseConfig.tsx +++ b/frontend/components/admin/dashboard/data-sources/MultiDatabaseConfig.tsx @@ -321,38 +321,6 @@ ORDER BY 하위부서수 DESC`, />
- {/* 마커 polling 간격 설정 (MapTestWidgetV2 전용) */} -
- - -

마커 데이터를 자동으로 갱신하는 주기를 설정합니다

-
{/* 지도 색상 설정 (MapTestWidgetV2 전용) */}
diff --git a/frontend/components/admin/dashboard/types.ts b/frontend/components/admin/dashboard/types.ts index f5490dbf..e0fdb3a1 100644 --- a/frontend/components/admin/dashboard/types.ts +++ b/frontend/components/admin/dashboard/types.ts @@ -155,7 +155,6 @@ export interface ChartDataSource { jsonPath?: string; // JSON 응답에서 데이터 추출 경로 (예: "data.results") // 공통 - refreshInterval?: number; // 자동 새로고침 (초, 0이면 수동) lastExecuted?: string; // 마지막 실행 시간 lastError?: string; // 마지막 오류 메시지 mapDisplayType?: "auto" | "marker" | "polygon"; // 지도 표시 방식 (auto: 자동, marker: 마커, polygon: 영역) @@ -184,6 +183,9 @@ export interface ChartConfig { // 다중 데이터 소스 (테스트 위젯용) dataSources?: ChartDataSource[]; // 여러 데이터 소스 (REST API + Database 혼합 가능) + // 위젯 레벨 설정 (MapTestWidgetV2용) + refreshInterval?: number; // 위젯 전체 자동 새로고침 간격 (초, 0이면 수동) + // 멀티 차트 설정 (ChartTestWidget용) chartType?: string; // 차트 타입 (line, bar, pie, etc.) mergeMode?: boolean; // 데이터 병합 모드 (여러 데이터 소스를 하나의 라인/바로 합침) diff --git a/frontend/components/dashboard/widgets/MapTestWidgetV2.tsx b/frontend/components/dashboard/widgets/MapTestWidgetV2.tsx index dafc40fa..5df1663a 100644 --- a/frontend/components/dashboard/widgets/MapTestWidgetV2.tsx +++ b/frontend/components/dashboard/widgets/MapTestWidgetV2.tsx @@ -916,9 +916,8 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) { // 즉시 첫 로드 (마커 데이터) loadMultipleDataSources(); - // 첫 번째 데이터 소스의 새로고침 간격 사용 (초) - const firstDataSource = dataSources[0]; - const refreshInterval = firstDataSource?.refreshInterval ?? 5; + // 위젯 레벨의 새로고침 간격 사용 (초) + const refreshInterval = element?.chartConfig?.refreshInterval ?? 5; // 0이면 자동 새로고침 비활성화 if (refreshInterval === 0) { @@ -933,7 +932,7 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) { clearInterval(intervalId); }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [dataSources]); + }, [dataSources, element?.chartConfig?.refreshInterval]); // 타일맵 URL (chartConfig에서 가져오기) const tileMapUrl =