설정들 고친거
This commit is contained in:
@@ -96,22 +96,35 @@ export function ListTestWidget({ element }: ListTestWidgetProps) {
|
||||
|
||||
// 추가 데이터 조회 설정이 있으면 실행
|
||||
const additionalQuery = config.rowDetailPopup?.additionalQuery;
|
||||
if (additionalQuery?.enabled && additionalQuery.tableName && additionalQuery.matchColumn) {
|
||||
const sourceColumn = additionalQuery.sourceColumn || additionalQuery.matchColumn;
|
||||
const matchValue = row[sourceColumn];
|
||||
|
||||
if (matchValue !== undefined && matchValue !== null) {
|
||||
if (additionalQuery?.enabled) {
|
||||
const queryMode = additionalQuery.queryMode || "table";
|
||||
|
||||
// 커스텀 쿼리 모드
|
||||
if (queryMode === "custom" && additionalQuery.customQuery) {
|
||||
setDetailPopupLoading(true);
|
||||
try {
|
||||
const query = `
|
||||
SELECT *
|
||||
FROM ${additionalQuery.tableName}
|
||||
WHERE ${additionalQuery.matchColumn} = '${matchValue}'
|
||||
LIMIT 1;
|
||||
`;
|
||||
// 쿼리에서 {컬럼명} 형태의 파라미터를 실제 값으로 치환
|
||||
let query = additionalQuery.customQuery;
|
||||
// console.log("🔍 [ListTestWidget] 커스텀 쿼리 파라미터 치환 시작");
|
||||
// console.log("🔍 [ListTestWidget] 클릭한 행 데이터:", row);
|
||||
// console.log("🔍 [ListTestWidget] 행 컬럼 목록:", Object.keys(row));
|
||||
|
||||
Object.keys(row).forEach((key) => {
|
||||
const value = row[key];
|
||||
const placeholder = new RegExp(`\\{${key}\\}`, "g");
|
||||
// SQL 인젝션 방지를 위해 값 이스케이프
|
||||
const safeValue = typeof value === "string"
|
||||
? value.replace(/'/g, "''")
|
||||
: value;
|
||||
query = query.replace(placeholder, String(safeValue ?? ""));
|
||||
// console.log(`🔍 [ListTestWidget] 치환: {${key}} → ${safeValue}`);
|
||||
});
|
||||
|
||||
// console.log("🔍 [ListTestWidget] 최종 쿼리:", query);
|
||||
|
||||
const { dashboardApi } = await import("@/lib/api/dashboard");
|
||||
const result = await dashboardApi.executeQuery(query);
|
||||
// console.log("🔍 [ListTestWidget] 쿼리 결과:", result);
|
||||
|
||||
if (result.success && result.rows.length > 0) {
|
||||
setAdditionalDetailData(result.rows[0]);
|
||||
@@ -119,12 +132,43 @@ export function ListTestWidget({ element }: ListTestWidgetProps) {
|
||||
setAdditionalDetailData({});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("추가 데이터 로드 실패:", err);
|
||||
console.error("커스텀 쿼리 실행 실패:", err);
|
||||
setAdditionalDetailData({});
|
||||
} finally {
|
||||
setDetailPopupLoading(false);
|
||||
}
|
||||
}
|
||||
// 테이블 조회 모드
|
||||
else if (queryMode === "table" && additionalQuery.tableName && additionalQuery.matchColumn) {
|
||||
const sourceColumn = additionalQuery.sourceColumn || additionalQuery.matchColumn;
|
||||
const matchValue = row[sourceColumn];
|
||||
|
||||
if (matchValue !== undefined && matchValue !== null) {
|
||||
setDetailPopupLoading(true);
|
||||
try {
|
||||
const query = `
|
||||
SELECT *
|
||||
FROM ${additionalQuery.tableName}
|
||||
WHERE ${additionalQuery.matchColumn} = '${matchValue}'
|
||||
LIMIT 1;
|
||||
`;
|
||||
|
||||
const { dashboardApi } = await import("@/lib/api/dashboard");
|
||||
const result = await dashboardApi.executeQuery(query);
|
||||
|
||||
if (result.success && result.rows.length > 0) {
|
||||
setAdditionalDetailData(result.rows[0]);
|
||||
} else {
|
||||
setAdditionalDetailData({});
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("추가 데이터 로드 실패:", err);
|
||||
setAdditionalDetailData({});
|
||||
} finally {
|
||||
setDetailPopupLoading(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
[config.rowDetailPopup],
|
||||
@@ -222,13 +266,21 @@ export function ListTestWidget({ element }: ListTestWidgetProps) {
|
||||
const getDefaultFieldGroups = (row: Record<string, any>, additional: Record<string, any> | null): FieldGroup[] => {
|
||||
const groups: FieldGroup[] = [];
|
||||
const displayColumns = config.rowDetailPopup?.additionalQuery?.displayColumns;
|
||||
const queryMode = config.rowDetailPopup?.additionalQuery?.queryMode || "table";
|
||||
|
||||
// 커스텀 쿼리 모드일 때는 additional 데이터를 우선 사용
|
||||
// row와 additional을 병합하되, 커스텀 쿼리 결과(additional)가 우선
|
||||
const mergedData = queryMode === "custom" && additional && Object.keys(additional).length > 0
|
||||
? { ...row, ...additional } // additional이 row를 덮어씀
|
||||
: row;
|
||||
|
||||
// 기본 정보 그룹 - displayColumns가 있으면 해당 컬럼만, 없으면 전체
|
||||
const allKeys = Object.keys(row).filter((key) => !key.startsWith("_")); // _source 등 내부 필드 제외
|
||||
const allKeys = Object.keys(mergedData).filter((key) => !key.startsWith("_")); // _source 등 내부 필드 제외
|
||||
let basicFields: { column: string; label: string }[] = [];
|
||||
|
||||
if (displayColumns && displayColumns.length > 0) {
|
||||
// DisplayColumnConfig 형식 지원
|
||||
// 커스텀 쿼리 모드일 때는 mergedData에서 컬럼 확인
|
||||
basicFields = displayColumns
|
||||
.map((colConfig) => {
|
||||
const column = typeof colConfig === 'object' ? colConfig.column : colConfig;
|
||||
@@ -237,8 +289,14 @@ export function ListTestWidget({ element }: ListTestWidgetProps) {
|
||||
})
|
||||
.filter((item) => allKeys.includes(item.column));
|
||||
} else {
|
||||
// 전체 컬럼
|
||||
basicFields = allKeys.map((key) => ({ column: key, label: key }));
|
||||
// 전체 컬럼 - 커스텀 쿼리 모드일 때는 additional 컬럼만 표시
|
||||
if (queryMode === "custom" && additional && Object.keys(additional).length > 0) {
|
||||
basicFields = Object.keys(additional)
|
||||
.filter((key) => !key.startsWith("_"))
|
||||
.map((key) => ({ column: key, label: key }));
|
||||
} else {
|
||||
basicFields = allKeys.map((key) => ({ column: key, label: key }));
|
||||
}
|
||||
}
|
||||
|
||||
groups.push({
|
||||
@@ -253,8 +311,8 @@ export function ListTestWidget({ element }: ListTestWidgetProps) {
|
||||
})),
|
||||
});
|
||||
|
||||
// 추가 데이터가 있고 vehicles 테이블인 경우 운행/공차 정보 추가
|
||||
if (additional && Object.keys(additional).length > 0) {
|
||||
// 추가 데이터가 있고 vehicles 테이블인 경우 운행/공차 정보 추가 (테이블 모드일 때만)
|
||||
if (queryMode === "table" && additional && Object.keys(additional).length > 0) {
|
||||
// 운행 정보
|
||||
if (additional.last_trip_start || additional.last_trip_end) {
|
||||
groups.push({
|
||||
|
||||
@@ -203,11 +203,15 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) {
|
||||
setTripInfoLoading(identifier);
|
||||
|
||||
try {
|
||||
// user_id 또는 vehicle_number로 조회
|
||||
// user_id 또는 vehicle_number로 조회 (시간은 KST로 변환)
|
||||
const query = `SELECT
|
||||
id, vehicle_number, user_id,
|
||||
last_trip_start, last_trip_end, last_trip_distance, last_trip_time,
|
||||
last_empty_start, last_empty_end, last_empty_distance, last_empty_time,
|
||||
(last_trip_start AT TIME ZONE 'Asia/Seoul')::timestamp as last_trip_start,
|
||||
(last_trip_end AT TIME ZONE 'Asia/Seoul')::timestamp as last_trip_end,
|
||||
last_trip_distance, last_trip_time,
|
||||
(last_empty_start AT TIME ZONE 'Asia/Seoul')::timestamp as last_empty_start,
|
||||
(last_empty_end AT TIME ZONE 'Asia/Seoul')::timestamp as last_empty_end,
|
||||
last_empty_distance, last_empty_time,
|
||||
departure, arrival, status
|
||||
FROM vehicles
|
||||
WHERE user_id = '${identifier}'
|
||||
@@ -277,12 +281,16 @@ export default function MapTestWidgetV2({ element }: MapTestWidgetV2Props) {
|
||||
if (identifiers.length === 0) return;
|
||||
|
||||
try {
|
||||
// 모든 마커의 운행/공차 정보를 한 번에 조회
|
||||
// 모든 마커의 운행/공차 정보를 한 번에 조회 (시간은 KST로 변환)
|
||||
const placeholders = identifiers.map((_, i) => `$${i + 1}`).join(", ");
|
||||
const query = `SELECT
|
||||
id, vehicle_number, user_id,
|
||||
last_trip_start, last_trip_end, last_trip_distance, last_trip_time,
|
||||
last_empty_start, last_empty_end, last_empty_distance, last_empty_time,
|
||||
(last_trip_start AT TIME ZONE 'Asia/Seoul')::timestamp as last_trip_start,
|
||||
(last_trip_end AT TIME ZONE 'Asia/Seoul')::timestamp as last_trip_end,
|
||||
last_trip_distance, last_trip_time,
|
||||
(last_empty_start AT TIME ZONE 'Asia/Seoul')::timestamp as last_empty_start,
|
||||
(last_empty_end AT TIME ZONE 'Asia/Seoul')::timestamp as last_empty_end,
|
||||
last_empty_distance, last_empty_time,
|
||||
departure, arrival, status
|
||||
FROM vehicles
|
||||
WHERE user_id IN (${identifiers.map(id => `'${id}'`).join(", ")})
|
||||
|
||||
Reference in New Issue
Block a user