지도 위젯 별 polling 설정 구현
This commit is contained in:
parent
b3e217c1de
commit
a3503c0b9f
|
|
@ -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<CustomMetricConfig>({});
|
||||
|
||||
// 자동 새로고침 간격 (지도 위젯용)
|
||||
const [refreshInterval, setRefreshInterval] = useState<number>(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
|
|||
<Switch id="show-header" checked={showHeader} onCheckedChange={setShowHeader} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 자동 새로고침 설정 (지도 위젯 전용) */}
|
||||
{element.subtype === "map-summary-v2" && (
|
||||
<div className="bg-background rounded-lg p-3 shadow-sm">
|
||||
<Label htmlFor="refresh-interval" className="mb-2 block text-xs font-semibold">
|
||||
자동 새로고침 간격
|
||||
</Label>
|
||||
<Select value={refreshInterval.toString()} onValueChange={(value) => setRefreshInterval(parseInt(value))}>
|
||||
<SelectTrigger id="refresh-interval" className="h-9 text-sm">
|
||||
<SelectValue placeholder="간격 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="0" className="text-sm">
|
||||
없음
|
||||
</SelectItem>
|
||||
<SelectItem value="5" className="text-sm">
|
||||
5초
|
||||
</SelectItem>
|
||||
<SelectItem value="10" className="text-sm">
|
||||
10초
|
||||
</SelectItem>
|
||||
<SelectItem value="30" className="text-sm">
|
||||
30초
|
||||
</SelectItem>
|
||||
<SelectItem value="60" className="text-sm">
|
||||
1분
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-muted-foreground mt-1.5 text-xs">
|
||||
위젯의 모든 데이터를 자동으로 갱신하는 주기를 설정합니다
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
|
|
|
|||
|
|
@ -530,30 +530,6 @@ export default function MultiApiConfig({ dataSource, onChange, onTestResult }: M
|
|||
))}
|
||||
</div>
|
||||
|
||||
{/* 마커 polling 간격 설정 (MapTestWidgetV2 전용) */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="marker-refresh-interval" className="text-xs">
|
||||
마커 새로고침 간격
|
||||
</Label>
|
||||
<Select
|
||||
value={(dataSource.refreshInterval ?? 5).toString()}
|
||||
onValueChange={(value) => onChange({ refreshInterval: parseInt(value) })}
|
||||
>
|
||||
<SelectTrigger id="marker-refresh-interval" className="h-9 text-xs">
|
||||
<SelectValue placeholder="간격 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="0" className="text-xs">없음</SelectItem>
|
||||
<SelectItem value="5" className="text-xs">5초</SelectItem>
|
||||
<SelectItem value="10" className="text-xs">10초</SelectItem>
|
||||
<SelectItem value="30" className="text-xs">30초</SelectItem>
|
||||
<SelectItem value="60" className="text-xs">1분</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-[10px] text-muted-foreground">
|
||||
마커 데이터를 자동으로 갱신하는 주기를 설정합니다
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 마커 종류 선택 (MapTestWidgetV2 전용) */}
|
||||
<div className="space-y-2">
|
||||
|
|
|
|||
|
|
@ -321,38 +321,6 @@ ORDER BY 하위부서수 DESC`,
|
|||
/>
|
||||
</div>
|
||||
|
||||
{/* 마커 polling 간격 설정 (MapTestWidgetV2 전용) */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="marker-refresh-interval" className="text-xs">
|
||||
데이터 새로고침 간격
|
||||
</Label>
|
||||
<Select
|
||||
value={(dataSource.refreshInterval ?? 5).toString()}
|
||||
onValueChange={(value) => onChange({ refreshInterval: parseInt(value) })}
|
||||
>
|
||||
<SelectTrigger id="marker-refresh-interval" className="h-8 text-xs">
|
||||
<SelectValue placeholder="간격 선택" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="0" className="text-xs">
|
||||
없음
|
||||
</SelectItem>
|
||||
<SelectItem value="5" className="text-xs">
|
||||
5초
|
||||
</SelectItem>
|
||||
<SelectItem value="10" className="text-xs">
|
||||
10초
|
||||
</SelectItem>
|
||||
<SelectItem value="30" className="text-xs">
|
||||
30초
|
||||
</SelectItem>
|
||||
<SelectItem value="60" className="text-xs">
|
||||
1분
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<p className="text-muted-foreground text-[10px]">마커 데이터를 자동으로 갱신하는 주기를 설정합니다</p>
|
||||
</div>
|
||||
|
||||
{/* 지도 색상 설정 (MapTestWidgetV2 전용) */}
|
||||
<div className="bg-muted/30 space-y-2 rounded-lg border p-2">
|
||||
|
|
|
|||
|
|
@ -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; // 데이터 병합 모드 (여러 데이터 소스를 하나의 라인/바로 합침)
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
Loading…
Reference in New Issue