Merge branch 'main' of http://39.117.244.52:3000/kjs/ERP-node into jskim-node

This commit is contained in:
kjs
2026-02-26 20:55:56 +09:00
17 changed files with 3405 additions and 1674 deletions

View File

@@ -213,6 +213,8 @@ export default function ComponentEditorPanel({
previewPageIndex={previewPageIndex}
onPreviewPage={onPreviewPage}
modals={modals}
allComponents={allComponents}
connections={connections}
/>
</TabsContent>
@@ -404,9 +406,11 @@ interface ComponentSettingsFormProps {
previewPageIndex?: number;
onPreviewPage?: (pageIndex: number) => void;
modals?: PopModalDefinition[];
allComponents?: PopComponentDefinitionV5[];
connections?: PopDataConnection[];
}
function ComponentSettingsForm({ component, onUpdate, currentMode, previewPageIndex, onPreviewPage, modals }: ComponentSettingsFormProps) {
function ComponentSettingsForm({ component, onUpdate, currentMode, previewPageIndex, onPreviewPage, modals, allComponents, connections }: ComponentSettingsFormProps) {
// PopComponentRegistry에서 configPanel 가져오기
const registeredComp = PopComponentRegistry.getComponent(component.type);
const ConfigPanel = registeredComp?.configPanel;
@@ -440,6 +444,9 @@ function ComponentSettingsForm({ component, onUpdate, currentMode, previewPageIn
onPreviewPage={onPreviewPage}
previewPageIndex={previewPageIndex}
modals={modals}
allComponents={allComponents}
connections={connections}
componentId={component.id}
/>
) : (
<div className="rounded-lg bg-gray-50 p-3">
@@ -515,3 +522,4 @@ function VisibilityForm({ component, onUpdate }: VisibilityFormProps) {
);
}

View File

@@ -272,6 +272,25 @@ function ConnectionForm({
? PopComponentRegistry.getComponent(targetComp.type)?.connectionMeta
: null;
// 보내는 값 + 받는 컴포넌트가 결정되면 받는 방식 자동 매칭
React.useEffect(() => {
if (!selectedOutput || !targetMeta?.receivable?.length) return;
// 이미 선택된 값이 있으면 건드리지 않음
if (selectedTargetInput) return;
const receivables = targetMeta.receivable;
// 1) 같은 key가 있으면 자동 매칭
const exactMatch = receivables.find((r) => r.key === selectedOutput);
if (exactMatch) {
setSelectedTargetInput(exactMatch.key);
return;
}
// 2) receivable이 1개뿐이면 자동 선택
if (receivables.length === 1) {
setSelectedTargetInput(receivables[0].key);
}
}, [selectedOutput, targetMeta, selectedTargetInput]);
// 화면에 표시 중인 컬럼
const displayColumns = React.useMemo(
() => extractDisplayColumns(targetComp || undefined),
@@ -322,6 +341,8 @@ function ConnectionForm({
const handleSubmit = () => {
if (!selectedOutput || !selectedTargetId || !selectedTargetInput) return;
const isEvent = isEventTypeConnection(meta, selectedOutput, targetMeta, selectedTargetInput);
onSubmit({
sourceComponent: component.id,
sourceField: "",
@@ -330,7 +351,7 @@ function ConnectionForm({
targetField: "",
targetInput: selectedTargetInput,
filterConfig:
filterColumns.length > 0
!isEvent && filterColumns.length > 0
? {
targetColumn: filterColumns[0],
targetColumns: filterColumns,
@@ -427,8 +448,8 @@ function ConnectionForm({
</div>
)}
{/* 필터 설정 */}
{selectedTargetInput && (
{/* 필터 설정: event 타입 연결이면 숨김 */}
{selectedTargetInput && !isEventTypeConnection(meta, selectedOutput, targetMeta, selectedTargetInput) && (
<div className="space-y-2 rounded bg-gray-50 p-2">
<p className="text-[10px] font-medium text-muted-foreground"> </p>
@@ -607,6 +628,17 @@ function ReceiveSection({
// 유틸
// ========================================
function isEventTypeConnection(
sourceMeta: ComponentConnectionMeta | undefined,
outputKey: string,
targetMeta: ComponentConnectionMeta | null | undefined,
inputKey: string,
): boolean {
const sourceItem = sourceMeta?.sendable?.find((s) => s.key === outputKey);
const targetItem = targetMeta?.receivable?.find((r) => r.key === inputKey);
return sourceItem?.type === "event" || targetItem?.type === "event";
}
function buildConnectionLabel(
source: PopComponentDefinitionV5,
_outputKey: string,