feat(pop): 다중 액션 체이닝 + 외부 테이블 선택 + 카드 클릭 모달 + 필터 전 비표시
버튼 규칙 하나에 여러 액션을 순차 실행하는 다중 액션 체이닝, DB 직접 선택으로 외부 테이블에 값을 변경하는 기능, 카드 클릭 시 조건부 모달 열기, 필터 전 데이터 비표시 옵션을 추가한다. [다중 액션 체이닝] - types.ts: ActionButtonDef.clickActions 배열 추가 (하위호환 유지) - PopCardListV2Config: 액션 목록 UI (추가/삭제/순서) - cell-renderers: __allActions 배열로 config 전달 - PopCardListV2Component: actionsToRun 순차 실행, 실패 시 스킵 [외부 테이블 선택] - ActionButtonClickAction.joinConfig (sourceColumn, targetColumn) 추가 - ImmediateActionEditor: "DB에서 직접 선택..." 옵션 + 조인키 설정 UI - DbTableCombobox: 테이블명(영어)+설명(한글) 검색 가능 - Component: joinConfig 기반 lookupValue/lookupColumn 처리 [카드 클릭 모달] - types.ts: V2CardClickAction에 "modal-open", V2CardClickModalConfig 추가 - PopCardListV2Config: 동작 탭에 모달 설정 (화면 ID, 조건, 제목) - PopCardListV2Component: handleCardSelect 조건 체크 후 openPopModal [필터 전 데이터 비표시] - PopCardListV2Config.hideUntilFiltered Switch - Component: externalFilters 없을 때 안내 메시지 [버그 수정] - availableTableOptions: dataSource.table -> dataSource.tableName 수정 - popActionRoutes: INSERT 시 created_date/updated_date/writer 자동 추가, UPDATE 시 updated_date 자동 갱신 [액션 버튼 구조 개선] - evaluateShowCondition: 버튼별 조건 평가 (visible/disabled/hidden) - ActionButtonsEditor: 아코디언 UI + sessionStorage 상태 유지 - 1셀 1버튼 렌더링: 조건 맞는 버튼 1개만 표시
This commit is contained in:
@@ -273,6 +273,19 @@ router.post("/execute-action", authenticateToken, async (req: Request, res: Resp
|
||||
}
|
||||
}
|
||||
|
||||
if (!columns.includes('"created_date"')) {
|
||||
columns.push('"created_date"');
|
||||
values.push(new Date().toISOString());
|
||||
}
|
||||
if (!columns.includes('"updated_date"')) {
|
||||
columns.push('"updated_date"');
|
||||
values.push(new Date().toISOString());
|
||||
}
|
||||
if (!columns.includes('"writer"') && userId) {
|
||||
columns.push('"writer"');
|
||||
values.push(userId);
|
||||
}
|
||||
|
||||
if (columns.length > 1) {
|
||||
const placeholders = values.map((_, i) => `$${i + 1}`).join(", ");
|
||||
await client.query(
|
||||
@@ -320,8 +333,9 @@ router.post("/execute-action", authenticateToken, async (req: Request, res: Resp
|
||||
for (let i = 0; i < lookupValues.length; i++) {
|
||||
const item = items[i] ?? {};
|
||||
const resolved = resolveStatusValue("conditional", task.fixedValue ?? "", task.conditionalValue, item);
|
||||
const autoUpdated = task.targetColumn !== "updated_date" ? `, "updated_date" = NOW()` : "";
|
||||
await client.query(
|
||||
`UPDATE "${task.targetTable}" SET "${task.targetColumn}" = $1 WHERE company_code = $2 AND "${pkColumn}" = $3`,
|
||||
`UPDATE "${task.targetTable}" SET "${task.targetColumn}" = $1${autoUpdated} WHERE company_code = $2 AND "${pkColumn}" = $3`,
|
||||
[resolved, companyCode, lookupValues[i]],
|
||||
);
|
||||
processedCount++;
|
||||
@@ -339,9 +353,10 @@ router.post("/execute-action", authenticateToken, async (req: Request, res: Resp
|
||||
|
||||
const caseSql = `CASE WHEN COALESCE("${task.compareColumn}"::numeric, 0) ${op} COALESCE("${task.compareWith}"::numeric, 0) THEN $1 ELSE $2 END`;
|
||||
|
||||
const autoUpdatedDb = task.targetColumn !== "updated_date" ? `, "updated_date" = NOW()` : "";
|
||||
const placeholders = lookupValues.map((_, i) => `$${i + 4}`).join(", ");
|
||||
await client.query(
|
||||
`UPDATE "${task.targetTable}" SET "${task.targetColumn}" = ${caseSql} WHERE company_code = $3 AND "${pkColumn}" IN (${placeholders})`,
|
||||
`UPDATE "${task.targetTable}" SET "${task.targetColumn}" = ${caseSql}${autoUpdatedDb} WHERE company_code = $3 AND "${pkColumn}" IN (${placeholders})`,
|
||||
[thenVal, elseVal, companyCode, ...lookupValues],
|
||||
);
|
||||
processedCount += lookupValues.length;
|
||||
@@ -376,8 +391,9 @@ router.post("/execute-action", authenticateToken, async (req: Request, res: Resp
|
||||
setSql = `"${task.targetColumn}" = $1`;
|
||||
}
|
||||
|
||||
const autoUpdatedDate = task.targetColumn !== "updated_date" ? `, "updated_date" = NOW()` : "";
|
||||
await client.query(
|
||||
`UPDATE "${task.targetTable}" SET ${setSql} WHERE company_code = $2 AND "${pkColumn}" = $3`,
|
||||
`UPDATE "${task.targetTable}" SET ${setSql}${autoUpdatedDate} WHERE company_code = $2 AND "${pkColumn}" = $3`,
|
||||
[value, companyCode, lookupValues[i]],
|
||||
);
|
||||
processedCount++;
|
||||
@@ -578,6 +594,19 @@ router.post("/execute-action", authenticateToken, async (req: Request, res: Resp
|
||||
}
|
||||
}
|
||||
|
||||
if (!columns.includes('"created_date"')) {
|
||||
columns.push('"created_date"');
|
||||
values.push(new Date().toISOString());
|
||||
}
|
||||
if (!columns.includes('"updated_date"')) {
|
||||
columns.push('"updated_date"');
|
||||
values.push(new Date().toISOString());
|
||||
}
|
||||
if (!columns.includes('"writer"') && userId) {
|
||||
columns.push('"writer"');
|
||||
values.push(userId);
|
||||
}
|
||||
|
||||
if (columns.length > 1) {
|
||||
const placeholders = values.map((_, i) => `$${i + 1}`).join(", ");
|
||||
const sql = `INSERT INTO "${cardMapping.targetTable}" (${columns.join(", ")}) VALUES (${placeholders})`;
|
||||
@@ -611,6 +640,19 @@ router.post("/execute-action", authenticateToken, async (req: Request, res: Resp
|
||||
values.push(fieldValues[sourceField] ?? null);
|
||||
}
|
||||
|
||||
if (!columns.includes('"created_date"')) {
|
||||
columns.push('"created_date"');
|
||||
values.push(new Date().toISOString());
|
||||
}
|
||||
if (!columns.includes('"updated_date"')) {
|
||||
columns.push('"updated_date"');
|
||||
values.push(new Date().toISOString());
|
||||
}
|
||||
if (!columns.includes('"writer"') && userId) {
|
||||
columns.push('"writer"');
|
||||
values.push(userId);
|
||||
}
|
||||
|
||||
if (columns.length > 1) {
|
||||
const placeholders = values.map((_, i) => `$${i + 1}`).join(", ");
|
||||
const sql = `INSERT INTO "${fieldMapping.targetTable}" (${columns.join(", ")}) VALUES (${placeholders})`;
|
||||
@@ -662,16 +704,18 @@ router.post("/execute-action", authenticateToken, async (req: Request, res: Resp
|
||||
}
|
||||
|
||||
if (valueType === "fixed") {
|
||||
const autoUpd = rule.targetColumn !== "updated_date" ? `, "updated_date" = NOW()` : "";
|
||||
const placeholders = lookupValues.map((_, i) => `$${i + 3}`).join(", ");
|
||||
const sql = `UPDATE "${rule.targetTable}" SET "${rule.targetColumn}" = $1 WHERE company_code = $2 AND "${pkColumn}" IN (${placeholders})`;
|
||||
const sql = `UPDATE "${rule.targetTable}" SET "${rule.targetColumn}" = $1${autoUpd} WHERE company_code = $2 AND "${pkColumn}" IN (${placeholders})`;
|
||||
await client.query(sql, [fixedValue, companyCode, ...lookupValues]);
|
||||
processedCount += lookupValues.length;
|
||||
} else {
|
||||
for (let i = 0; i < lookupValues.length; i++) {
|
||||
const item = items[i] ?? {};
|
||||
const resolvedValue = resolveStatusValue(valueType, fixedValue, rule.conditionalValue, item);
|
||||
const autoUpd2 = rule.targetColumn !== "updated_date" ? `, "updated_date" = NOW()` : "";
|
||||
await client.query(
|
||||
`UPDATE "${rule.targetTable}" SET "${rule.targetColumn}" = $1 WHERE company_code = $2 AND "${pkColumn}" = $3`,
|
||||
`UPDATE "${rule.targetTable}" SET "${rule.targetColumn}" = $1${autoUpd2} WHERE company_code = $2 AND "${pkColumn}" = $3`,
|
||||
[resolvedValue, companyCode, lookupValues[i]]
|
||||
);
|
||||
processedCount++;
|
||||
|
||||
Reference in New Issue
Block a user