[agent-pipeline] pipe-20260329112709-ncml round-1

This commit is contained in:
DDD1542
2026-03-29 22:56:00 +09:00
parent b3f2383ef0
commit a5f4cd5ba9
397 changed files with 4011 additions and 4161 deletions
@@ -50,9 +50,9 @@ export const AutoConfigPanel: React.FC<AutoConfigPanelProps> = ({
type="number"
min={1}
max={10}
value={config.sequenceLength || 3}
value={config.sequence_length || 3}
onChange={(e) =>
onChange({ ...config, sequenceLength: parseInt(e.target.value) || 3 })
onChange({ ...config, sequence_length: parseInt(e.target.value) || 3 })
}
disabled={isPreview}
className="h-8 text-xs sm:h-10 sm:text-sm"
@@ -66,9 +66,9 @@ export const AutoConfigPanel: React.FC<AutoConfigPanelProps> = ({
<Input
type="number"
min={1}
value={config.startFrom || 1}
value={config.start_from || 1}
onChange={(e) =>
onChange({ ...config, startFrom: parseInt(e.target.value) || 1 })
onChange({ ...config, start_from: parseInt(e.target.value) || 1 })
}
disabled={isPreview}
className="h-8 text-xs sm:h-10 sm:text-sm"
@@ -91,9 +91,9 @@ export const AutoConfigPanel: React.FC<AutoConfigPanelProps> = ({
type="number"
min={1}
max={10}
value={config.numberLength || 4}
value={config.number_length || 4}
onChange={(e) =>
onChange({ ...config, numberLength: parseInt(e.target.value) || 4 })
onChange({ ...config, number_length: parseInt(e.target.value) || 4 })
}
disabled={isPreview}
className="h-8 text-xs sm:h-10 sm:text-sm"
@@ -107,9 +107,9 @@ export const AutoConfigPanel: React.FC<AutoConfigPanelProps> = ({
<Input
type="number"
min={0}
value={config.numberValue || 0}
value={config.number_value || 0}
onChange={(e) =>
onChange({ ...config, numberValue: parseInt(e.target.value) || 0 })
onChange({ ...config, number_value: parseInt(e.target.value) || 0 })
}
disabled={isPreview}
className="h-8 text-xs sm:h-10 sm:text-sm"
@@ -139,8 +139,8 @@ export const AutoConfigPanel: React.FC<AutoConfigPanelProps> = ({
<div>
<Label className="text-xs font-medium sm:text-sm"> </Label>
<Input
value={config.textValue || ""}
onChange={(e) => onChange({ ...config, textValue: e.target.value })}
value={config.text_value || ""}
onChange={(e) => onChange({ ...config, text_value: e.target.value })}
placeholder="예: PRJ, CODE, PROD"
disabled={isPreview}
className="h-8 text-xs sm:h-10 sm:text-sm"
@@ -205,9 +205,9 @@ const DateConfigPanel: React.FC<DateConfigPanelProps> = ({
const [columnComboboxOpen, setColumnComboboxOpen] = useState(false);
// 체크박스 상태
const useColumnValue = config.useColumnValue || false;
const sourceTableName = config.sourceTableName || "";
const sourceColumnName = config.sourceColumnName || "";
const useColumnValue = config.use_column_value || false;
const sourceTableName = config.source_table_name || "";
const sourceColumnName = config.source_column_name || "";
// 테이블 목록 로드
useEffect(() => {
@@ -294,8 +294,8 @@ const DateConfigPanel: React.FC<DateConfigPanelProps> = ({
<div>
<Label className="text-xs font-medium sm:text-sm"> </Label>
<Select
value={config.dateFormat || "YYYYMMDD"}
onValueChange={(value) => onChange({ ...config, dateFormat: value })}
value={config.date_format || "YYYYMMDD"}
onValueChange={(value) => onChange({ ...config, date_format: value })}
disabled={isPreview}
>
<SelectTrigger className="h-8 text-xs sm:h-10 sm:text-sm">
@@ -324,9 +324,9 @@ const DateConfigPanel: React.FC<DateConfigPanelProps> = ({
onCheckedChange={(checked) => {
onChange({
...config,
useColumnValue: checked,
use_column_value: checked,
// 체크 해제 시 테이블/컬럼 초기화
...(checked ? {} : { sourceTableName: "", sourceColumnName: "" }),
...(checked ? {} : { source_table_name: "", source_column_name: "" }),
});
}}
disabled={isPreview}
@@ -386,8 +386,8 @@ const DateConfigPanel: React.FC<DateConfigPanelProps> = ({
onSelect={() => {
onChange({
...config,
sourceTableName: table.table_name,
sourceColumnName: "", // 테이블 변경 시 컬럼 초기화
source_table_name: table.table_name,
source_column_name: "", // 테이블 변경 시 컬럼 초기화
});
setTableComboboxOpen(false);
}}
@@ -453,7 +453,7 @@ const DateConfigPanel: React.FC<DateConfigPanelProps> = ({
key={column.column_name}
value={`${column.display_name} ${column.column_name}`}
onSelect={() => {
onChange({ ...config, sourceColumnName: column.column_name });
onChange({ ...config, source_column_name: column.column_name });
setColumnComboboxOpen(false);
}}
className="text-xs sm:text-sm"
@@ -510,8 +510,8 @@ interface CategoryValueNode {
interface CategoryConfigPanelProps {
config?: {
categoryKey?: string;
categoryMappings?: CategoryFormatMapping[];
category_key?: string;
category_mappings?: CategoryFormatMapping[];
};
onChange: (config: any) => void;
isPreview?: boolean;
@@ -552,14 +552,14 @@ const CategoryConfigPanel: React.FC<CategoryConfigPanelProps> = ({
// 수정 모드 진입 중 플래그 (useEffect 초기화 방지)
const isEditingRef = useRef(false);
const categoryKey = config.categoryKey || "";
const mappings = config.categoryMappings || [];
const categoryKey = config.category_key || "";
const mappings = config.category_mappings || [];
// 이미 추가된 카테고리 ID 목록 (수정 중인 항목 제외)
const addedValueIds = useMemo(() => {
return mappings
.filter(m => m.categoryValueId !== editingId)
.map(m => m.categoryValueId);
.filter(m => m.category_value_id !== editingId)
.map(m => m.category_value_id);
}, [mappings, editingId]);
// 카테고리 옵션 로드
@@ -712,23 +712,23 @@ const CategoryConfigPanel: React.FC<CategoryConfigPanelProps> = ({
if (!selectedInfo || !newFormat.trim()) return;
const newMapping: CategoryFormatMapping = {
categoryValueId: selectedInfo.valueId,
categoryValueCode: selectedInfo.valueCode, // V2Select에서 valueCode를 value로 사용하므로 매칭용 저장
categoryValueLabel: selectedInfo.valueLabel,
categoryValuePath: selectedInfo.valuePath,
category_value_id: selectedInfo.valueId,
category_value_code: selectedInfo.valueCode, // V2Select에서 valueCode를 value로 사용하므로 매칭용 저장
category_value_label: selectedInfo.valueLabel,
category_value_path: selectedInfo.valuePath,
format: newFormat.trim(),
};
let updatedMappings: CategoryFormatMapping[];
if (editingId !== null) {
// 수정 모드: 기존 항목 교체
updatedMappings = mappings.map(m =>
m.categoryValueId === editingId ? newMapping : m
updatedMappings = mappings.map(m =>
m.category_value_id === editingId ? newMapping : m
);
} else {
// 추가 모드: 중복 체크
const exists = mappings.some(m => m.categoryValueId === selectedInfo.valueId);
const exists = mappings.some(m => m.category_value_id === selectedInfo.valueId);
if (exists) {
alert("이미 추가된 카테고리입니다");
return;
@@ -738,7 +738,7 @@ const CategoryConfigPanel: React.FC<CategoryConfigPanelProps> = ({
onChange({
...config,
categoryMappings: updatedMappings,
category_mappings: updatedMappings,
});
// 초기화
@@ -768,17 +768,17 @@ const CategoryConfigPanel: React.FC<CategoryConfigPanelProps> = ({
return null;
};
const parentPath = findParentIds(categoryValues, mapping.categoryValueId);
const parentPath = findParentIds(categoryValues, mapping.category_value_id);
if (parentPath && parentPath.length > 0) {
setLevel1Id(parentPath[0] || null);
if (parentPath.length === 2) {
// 3단계: 대분류 > 중분류 > 소분류
setLevel2Id(parentPath[1]);
setLevel3Id(mapping.categoryValueId);
setLevel3Id(mapping.category_value_id);
} else if (parentPath.length === 1) {
// 2단계: 대분류 > 중분류
setLevel2Id(mapping.categoryValueId);
setLevel2Id(mapping.category_value_id);
setLevel3Id(null);
} else {
setLevel2Id(null);
@@ -786,13 +786,13 @@ const CategoryConfigPanel: React.FC<CategoryConfigPanelProps> = ({
}
} else {
// 루트 레벨 항목 (1단계)
setLevel1Id(mapping.categoryValueId);
setLevel1Id(mapping.category_value_id);
setLevel2Id(null);
setLevel3Id(null);
}
setNewFormat(mapping.format);
setEditingId(mapping.categoryValueId);
setEditingId(mapping.category_value_id);
// 다음 렌더링 사이클에서 플래그 해제
setTimeout(() => {
@@ -813,7 +813,7 @@ const CategoryConfigPanel: React.FC<CategoryConfigPanelProps> = ({
const handleRemoveMapping = (valueId: number) => {
onChange({
...config,
categoryMappings: mappings.filter(m => m.categoryValueId !== valueId),
category_mappings: mappings.filter(m => m.category_value_id !== valueId),
});
};
@@ -850,7 +850,7 @@ const CategoryConfigPanel: React.FC<CategoryConfigPanelProps> = ({
key={opt.displayName}
value={opt.displayLabel}
onSelect={() => {
onChange({ ...config, categoryKey: opt.displayName, categoryMappings: [] });
onChange({ ...config, category_key: opt.displayName, category_mappings: [] });
setCategoryKeyOpen(false);
}}
className="text-xs sm:text-sm"
@@ -1064,15 +1064,15 @@ const CategoryConfigPanel: React.FC<CategoryConfigPanelProps> = ({
<div className="space-y-1">
{mappings.map((m) => (
<div
key={m.categoryValueId}
key={m.category_value_id}
className={cn(
"flex cursor-pointer items-center justify-between rounded px-2 py-1 transition-colors hover:bg-muted",
editingId === m.categoryValueId ? "bg-primary/10 ring-1 ring-primary" : "bg-muted/50"
editingId === m.category_value_id ? "bg-primary/10 ring-1 ring-primary" : "bg-muted/50"
)}
onClick={() => !isPreview && handleEditMapping(m)}
>
<div className="flex items-center gap-2 text-xs">
<span className="text-muted-foreground">{m.categoryValuePath || m.categoryValueLabel}</span>
<span className="text-muted-foreground">{m.category_value_path || m.category_value_label}</span>
<span></span>
<span className="font-mono font-medium">{m.format}</span>
</div>
@@ -1081,7 +1081,7 @@ const CategoryConfigPanel: React.FC<CategoryConfigPanelProps> = ({
size="icon"
onClick={(e) => {
e.stopPropagation();
handleRemoveMapping(m.categoryValueId);
handleRemoveMapping(m.category_value_id);
}}
disabled={isPreview}
className="h-5 w-5"
@@ -1157,9 +1157,9 @@ function ReferenceConfigSection({
<div>
<Label className="text-xs font-medium sm:text-sm"> </Label>
<Select
value={config.referenceColumnName || ""}
value={config.reference_column_name || ""}
onValueChange={(value) =>
onChange({ ...config, referenceColumnName: value })
onChange({ ...config, reference_column_name: value })
}
disabled={isPreview || loadingCols}
>