feat: 모달에서 카테고리 조회 시 menuObjid 전달 기능 추가

카테고리 값을 메뉴별로 다르게 설정할 수 있도록 menuObjid를 모달 체인 전체에 전달합니다.

변경 내용:
- InteractiveDataTable: 등록/수정 모달 열 때 menuObjid를 이벤트에 포함
- EditModal: menuObjid를 state에 저장하고 하위 컴포넌트에 전달
- SaveModal: menuObjid props를 받아서 DynamicComponentRenderer에 전달
- SelectBasicComponent: getCategoryValues API 호출 시 menuObjid 파라미터 전달

이를 통해 같은 테이블/컬럼이라도 메뉴에 따라 다른 카테고리 옵션을 표시할 수 있습니다.

카테고리 API를 호출할 때 menuObjid를 전달하여 메뉴별 필터링 적용 가능하게 변경
This commit is contained in:
SeongHyun Kim 2026-01-21 16:42:11 +09:00
parent 430723df59
commit 055094308d
4 changed files with 18 additions and 4 deletions

View File

@ -33,6 +33,7 @@ interface EditModalState {
dataflowConfig?: any; dataflowConfig?: any;
dataflowTiming?: string; dataflowTiming?: string;
}; // 🆕 모달 내부 저장 버튼의 제어로직 설정 }; // 🆕 모달 내부 저장 버튼의 제어로직 설정
menuObjid?: number; // 🆕 메뉴 OBJID (카테고리 스코프용)
} }
interface EditModalProps { interface EditModalProps {
@ -91,6 +92,7 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
buttonConfig: undefined, buttonConfig: undefined,
buttonContext: undefined, buttonContext: undefined,
saveButtonConfig: undefined, saveButtonConfig: undefined,
menuObjid: undefined,
}); });
const [screenData, setScreenData] = useState<{ const [screenData, setScreenData] = useState<{
@ -234,7 +236,7 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
// 전역 모달 이벤트 리스너 // 전역 모달 이벤트 리스너
useEffect(() => { useEffect(() => {
const handleOpenEditModal = async (event: CustomEvent) => { const handleOpenEditModal = async (event: CustomEvent) => {
const { screenId, title, description, modalSize, editData, onSave, groupByColumns, tableName, isCreateMode, buttonConfig, buttonContext } = event.detail; const { screenId, title, description, modalSize, editData, onSave, groupByColumns, tableName, isCreateMode, buttonConfig, buttonContext, menuObjid } = event.detail;
// 🆕 모달 내부 저장 버튼의 제어로직 설정 조회 // 🆕 모달 내부 저장 버튼의 제어로직 설정 조회
let saveButtonConfig: EditModalState["saveButtonConfig"] = undefined; let saveButtonConfig: EditModalState["saveButtonConfig"] = undefined;
@ -258,6 +260,7 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
buttonConfig, // 🆕 버튼 설정 buttonConfig, // 🆕 버튼 설정
buttonContext, // 🆕 버튼 컨텍스트 buttonContext, // 🆕 버튼 컨텍스트
saveButtonConfig, // 🆕 모달 내부 저장 버튼의 제어로직 설정 saveButtonConfig, // 🆕 모달 내부 저장 버튼의 제어로직 설정
menuObjid, // 🆕 메뉴 OBJID (카테고리 스코프용)
}); });
// 편집 데이터로 폼 데이터 초기화 // 편집 데이터로 폼 데이터 초기화
@ -1079,6 +1082,8 @@ export const EditModal: React.FC<EditModalProps> = ({ className }) => {
id: modalState.screenId!, id: modalState.screenId!,
tableName: screenData.screenInfo?.tableName, tableName: screenData.screenInfo?.tableName,
}} }}
// 🆕 메뉴 OBJID 전달 (카테고리 스코프용)
menuObjid={modalState.menuObjid}
// 🆕 그룹 데이터가 있거나 UniversalFormModal이 없으면 EditModal.handleSave 사용 // 🆕 그룹 데이터가 있거나 UniversalFormModal이 없으면 EditModal.handleSave 사용
// groupData가 있으면 일괄 저장을 위해 반드시 EditModal.handleSave 사용 // groupData가 있으면 일괄 저장을 위해 반드시 EditModal.handleSave 사용
onSave={shouldUseEditModalSave ? handleSave : undefined} onSave={shouldUseEditModalSave ? handleSave : undefined}

View File

@ -1213,13 +1213,14 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
description: editModalDescription, description: editModalDescription,
modalSize: "lg", modalSize: "lg",
editData: initialData, editData: initialData,
menuObjid, // 🆕 메뉴 OBJID 전달 (카테고리 스코프용)
onSave: () => { onSave: () => {
loadData(); // 테이블 데이터 새로고침 loadData(); // 테이블 데이터 새로고침
}, },
}, },
}); });
window.dispatchEvent(event); window.dispatchEvent(event);
}, [selectedRows, data, getDisplayColumns, component.addModalConfig, component.editModalConfig, loadData]); }, [selectedRows, data, getDisplayColumns, component.addModalConfig, component.editModalConfig, loadData, menuObjid]);
// 수정 폼 데이터 변경 핸들러 // 수정 폼 데이터 변경 핸들러
const handleEditFormChange = useCallback((columnName: string, value: any) => { const handleEditFormChange = useCallback((columnName: string, value: any) => {
@ -2720,6 +2721,7 @@ export const InteractiveDataTable: React.FC<InteractiveDataTableProps> = ({
screenId={saveModalScreenId} screenId={saveModalScreenId}
modalSize={component.addModalConfig?.modalSize || "lg"} modalSize={component.addModalConfig?.modalSize || "lg"}
initialData={saveModalData} initialData={saveModalData}
menuObjid={menuObjid} // 🆕 메뉴 OBJID 전달 (카테고리 스코프용)
onSaveSuccess={() => { onSaveSuccess={() => {
// 저장 성공 시 테이블 새로고침 // 저장 성공 시 테이블 새로고침
loadData(currentPage, searchValues); // 현재 페이지로 다시 로드 loadData(currentPage, searchValues); // 현재 페이지로 다시 로드

View File

@ -19,6 +19,7 @@ interface SaveModalProps {
modalSize?: "sm" | "md" | "lg" | "xl" | "full"; modalSize?: "sm" | "md" | "lg" | "xl" | "full";
initialData?: any; // 수정 모드일 때 기존 데이터 initialData?: any; // 수정 모드일 때 기존 데이터
onSaveSuccess?: () => void; // 저장 성공 시 콜백 (테이블 새로고침용) onSaveSuccess?: () => void; // 저장 성공 시 콜백 (테이블 새로고침용)
menuObjid?: number; // 🆕 메뉴 OBJID (카테고리 스코프용)
} }
/** /**
@ -33,6 +34,7 @@ export const SaveModal: React.FC<SaveModalProps> = ({
modalSize = "lg", modalSize = "lg",
initialData, initialData,
onSaveSuccess, onSaveSuccess,
menuObjid,
}) => { }) => {
const { user, userName } = useAuth(); // 현재 사용자 정보 가져오기 const { user, userName } = useAuth(); // 현재 사용자 정보 가져오기
const [formData, setFormData] = useState<Record<string, any>>(initialData || {}); const [formData, setFormData] = useState<Record<string, any>>(initialData || {});
@ -373,6 +375,7 @@ export const SaveModal: React.FC<SaveModalProps> = ({
})); }));
}} }}
hideLabel={false} hideLabel={false}
menuObjid={menuObjid} // 🆕 메뉴 OBJID 전달 (카테고리 스코프용)
/> />
) : ( ) : (
<DynamicComponentRenderer <DynamicComponentRenderer
@ -385,6 +388,7 @@ export const SaveModal: React.FC<SaveModalProps> = ({
}} }}
screenId={screenId} screenId={screenId}
tableName={screenData.tableName} tableName={screenData.tableName}
menuObjid={menuObjid} // 🆕 메뉴 OBJID 전달 (카테고리 스코프용)
userId={user?.userId} // ✅ 사용자 ID 전달 userId={user?.userId} // ✅ 사용자 ID 전달
userName={user?.userName} // ✅ 사용자 이름 전달 userName={user?.userName} // ✅ 사용자 이름 전달
companyCode={user?.companyCode} // ✅ 회사 코드 전달 companyCode={user?.companyCode} // ✅ 회사 코드 전달

View File

@ -299,12 +299,14 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
tableName: component.tableName, tableName: component.tableName,
columnName: component.columnName, columnName: component.columnName,
webType, webType,
menuObjid, // 🆕 menuObjid 로깅 추가
}); });
setIsLoadingCategories(true); setIsLoadingCategories(true);
import("@/lib/api/tableCategoryValue").then(({ getCategoryValues }) => { import("@/lib/api/tableCategoryValue").then(({ getCategoryValues }) => {
getCategoryValues(component.tableName!, component.columnName!) // 🆕 menuObjid를 4번째 파라미터로 전달 (카테고리 스코프 적용)
getCategoryValues(component.tableName!, component.columnName!, false, menuObjid)
.then((response) => { .then((response) => {
console.log("🔍 [SelectBasic] 카테고리 API 응답:", response); console.log("🔍 [SelectBasic] 카테고리 API 응답:", response);
@ -324,6 +326,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
activeValuesCount: activeValues.length, activeValuesCount: activeValues.length,
options, options,
sampleOption: options[0], sampleOption: options[0],
menuObjid, // 🆕 menuObjid 로깅 추가
}); });
setCategoryOptions(options); setCategoryOptions(options);
@ -339,7 +342,7 @@ const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
}); });
}); });
} }
}, [webType, component.tableName, component.columnName]); }, [webType, component.tableName, component.columnName, menuObjid]); // 🆕 menuObjid 의존성 추가
// 디버깅: menuObjid가 제대로 전달되는지 확인 // 디버깅: menuObjid가 제대로 전달되는지 확인
useEffect(() => { useEffect(() => {