rest api 작동 구현
This commit is contained in:
parent
64658d5d5d
commit
84ce175d95
|
|
@ -48,9 +48,6 @@ export default function CustomMetricWidget({ element }: CustomMetricWidgetProps)
|
|||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("🎯 CustomMetricWidget mounted, element:", element);
|
||||
console.log("📊 dataSource:", element?.dataSource);
|
||||
console.log("📈 customMetricConfig:", element?.customMetricConfig);
|
||||
loadData();
|
||||
|
||||
// 자동 새로고침 (30초마다)
|
||||
|
|
@ -63,51 +60,127 @@ export default function CustomMetricWidget({ element }: CustomMetricWidgetProps)
|
|||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
// 쿼리나 설정이 없으면 초기 상태로 반환
|
||||
if (!element?.dataSource?.query || !element?.customMetricConfig?.metrics) {
|
||||
console.log("⚠️ 쿼리 또는 지표 설정이 없습니다");
|
||||
console.log("- dataSource.query:", element?.dataSource?.query);
|
||||
console.log("- customMetricConfig.metrics:", element?.customMetricConfig?.metrics);
|
||||
// 데이터 소스 타입 확인
|
||||
const dataSourceType = element?.dataSource?.type;
|
||||
|
||||
// 설정이 없으면 초기 상태로 반환
|
||||
if (!element?.customMetricConfig?.metrics) {
|
||||
setMetrics([]);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("✅ 쿼리 실행 시작:", element.dataSource.query);
|
||||
// Database 타입
|
||||
if (dataSourceType === "database") {
|
||||
if (!element?.dataSource?.query) {
|
||||
setMetrics([]);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const token = localStorage.getItem("authToken");
|
||||
const response = await fetch("/api/dashboards/execute-query", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: element.dataSource.query,
|
||||
connectionType: element.dataSource.connectionType || "current",
|
||||
connectionId: element.dataSource.connectionId,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error("데이터 로딩 실패");
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success && result.data?.rows) {
|
||||
const rows = result.data.rows;
|
||||
|
||||
// 각 메트릭 계산
|
||||
const calculatedMetrics = element.customMetricConfig.metrics.map((metric) => {
|
||||
const value = calculateMetric(rows, metric.field, metric.aggregation);
|
||||
return {
|
||||
...metric,
|
||||
calculatedValue: value,
|
||||
};
|
||||
const token = localStorage.getItem("authToken");
|
||||
const response = await fetch("/api/dashboards/execute-query", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
query: element.dataSource.query,
|
||||
connectionType: element.dataSource.connectionType || "current",
|
||||
connectionId: element.dataSource.connectionId,
|
||||
}),
|
||||
});
|
||||
|
||||
setMetrics(calculatedMetrics);
|
||||
if (!response.ok) throw new Error("데이터 로딩 실패");
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success && result.data?.rows) {
|
||||
const rows = result.data.rows;
|
||||
|
||||
const calculatedMetrics = element.customMetricConfig.metrics.map((metric) => {
|
||||
const value = calculateMetric(rows, metric.field, metric.aggregation);
|
||||
return {
|
||||
...metric,
|
||||
calculatedValue: value,
|
||||
};
|
||||
});
|
||||
|
||||
setMetrics(calculatedMetrics);
|
||||
} else {
|
||||
throw new Error(result.message || "데이터 로드 실패");
|
||||
}
|
||||
}
|
||||
// API 타입
|
||||
else if (dataSourceType === "api") {
|
||||
if (!element?.dataSource?.endpoint) {
|
||||
setMetrics([]);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const token = localStorage.getItem("authToken");
|
||||
const response = await fetch("/api/dashboards/fetch-external-api", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
method: element.dataSource.method || "GET",
|
||||
url: element.dataSource.endpoint,
|
||||
headers: element.dataSource.headers || {},
|
||||
body: element.dataSource.body,
|
||||
authType: element.dataSource.authType,
|
||||
authConfig: element.dataSource.authConfig,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error("API 호출 실패");
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success && result.data) {
|
||||
// API 응답 데이터 구조 확인 및 처리
|
||||
let rows: any[] = [];
|
||||
|
||||
// result.data가 배열인 경우
|
||||
if (Array.isArray(result.data)) {
|
||||
rows = result.data;
|
||||
}
|
||||
// result.data.results가 배열인 경우 (일반적인 API 응답 구조)
|
||||
else if (result.data.results && Array.isArray(result.data.results)) {
|
||||
rows = result.data.results;
|
||||
}
|
||||
// result.data.items가 배열인 경우
|
||||
else if (result.data.items && Array.isArray(result.data.items)) {
|
||||
rows = result.data.items;
|
||||
}
|
||||
// result.data.data가 배열인 경우
|
||||
else if (result.data.data && Array.isArray(result.data.data)) {
|
||||
rows = result.data.data;
|
||||
}
|
||||
// 그 외의 경우 단일 객체를 배열로 래핑
|
||||
else {
|
||||
rows = [result.data];
|
||||
}
|
||||
|
||||
const calculatedMetrics = element.customMetricConfig.metrics.map((metric) => {
|
||||
const value = calculateMetric(rows, metric.field, metric.aggregation);
|
||||
return {
|
||||
...metric,
|
||||
calculatedValue: value,
|
||||
};
|
||||
});
|
||||
|
||||
setMetrics(calculatedMetrics);
|
||||
} else {
|
||||
throw new Error("API 응답 형식 오류");
|
||||
}
|
||||
} else {
|
||||
throw new Error(result.message || "데이터 로드 실패");
|
||||
setMetrics([]);
|
||||
setLoading(false);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("메트릭 로드 실패:", err);
|
||||
|
|
@ -144,7 +217,12 @@ export default function CustomMetricWidget({ element }: CustomMetricWidgetProps)
|
|||
);
|
||||
}
|
||||
|
||||
if (!element?.dataSource?.query || !element?.customMetricConfig?.metrics || metrics.length === 0) {
|
||||
// 데이터 소스가 없거나 설정이 없는 경우
|
||||
const hasDataSource =
|
||||
(element?.dataSource?.type === "database" && element?.dataSource?.query) ||
|
||||
(element?.dataSource?.type === "api" && element?.dataSource?.endpoint);
|
||||
|
||||
if (!hasDataSource || !element?.customMetricConfig?.metrics || metrics.length === 0) {
|
||||
return (
|
||||
<div className="flex h-full items-center justify-center bg-white p-4">
|
||||
<div className="max-w-xs space-y-2 text-center">
|
||||
|
|
|
|||
Loading…
Reference in New Issue