fix: update V2PropertiesPanel to use V2FieldConfigPanel for input and select components
- Replaced references to V2InputConfigPanel and V2SelectConfigPanel with V2FieldConfigPanel in the V2PropertiesPanel. - This change ensures consistent configuration handling for both input and select components, improving maintainability and usability. Made-with: Cursor
This commit is contained in:
parent
7da04c6a09
commit
772a10258c
|
|
@ -183,6 +183,62 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
selectedComponent.componentConfig?.id ||
|
||||
(selectedComponent.type === "component" ? selectedComponent.id : null); // 🆕 독립 컴포넌트 (table-search-widget 등)
|
||||
|
||||
// 🆕 V2 컴포넌트 직접 감지 및 설정 패널 렌더링
|
||||
if (componentId?.startsWith("v2-")) {
|
||||
const v2ConfigPanels: Record<string, React.FC<{ config: any; onChange: (config: any) => void }>> = {
|
||||
"v2-input": require("@/components/v2/config-panels/V2FieldConfigPanel").V2FieldConfigPanel,
|
||||
"v2-select": require("@/components/v2/config-panels/V2FieldConfigPanel").V2FieldConfigPanel,
|
||||
"v2-date": require("@/components/v2/config-panels/V2DateConfigPanel").V2DateConfigPanel,
|
||||
"v2-list": require("@/components/v2/config-panels/V2ListConfigPanel").V2ListConfigPanel,
|
||||
"v2-layout": require("@/components/v2/config-panels/V2LayoutConfigPanel").V2LayoutConfigPanel,
|
||||
"v2-group": require("@/components/v2/config-panels/V2GroupConfigPanel").V2GroupConfigPanel,
|
||||
"v2-media": require("@/components/v2/config-panels/V2MediaConfigPanel").V2MediaConfigPanel,
|
||||
"v2-biz": require("@/components/v2/config-panels/V2BizConfigPanel").V2BizConfigPanel,
|
||||
"v2-hierarchy": require("@/components/v2/config-panels/V2HierarchyConfigPanel").V2HierarchyConfigPanel,
|
||||
"v2-bom-item-editor": require("@/components/v2/config-panels/V2BomItemEditorConfigPanel")
|
||||
.V2BomItemEditorConfigPanel,
|
||||
"v2-bom-tree": require("@/components/v2/config-panels/V2BomTreeConfigPanel").V2BomTreeConfigPanel,
|
||||
};
|
||||
|
||||
const V2ConfigPanel = v2ConfigPanels[componentId];
|
||||
if (V2ConfigPanel) {
|
||||
const currentConfig = selectedComponent.componentConfig || {};
|
||||
const handleV2ConfigChange = (newConfig: any) => {
|
||||
onUpdateProperty(selectedComponent.id, "componentConfig", { ...currentConfig, ...newConfig });
|
||||
};
|
||||
|
||||
// 컬럼의 inputType 가져오기 (entity 타입인지 확인용)
|
||||
const inputType = currentConfig.inputType || currentConfig.webType || (selectedComponent as any).inputType;
|
||||
|
||||
// 현재 화면의 테이블명 가져오기
|
||||
const currentTableName = tables?.[0]?.tableName;
|
||||
|
||||
// 컴포넌트별 추가 props
|
||||
const extraProps: Record<string, any> = {};
|
||||
if (componentId === "v2-select") {
|
||||
extraProps.inputType = inputType;
|
||||
extraProps.tableName = selectedComponent.tableName || currentTable?.tableName || currentTableName;
|
||||
extraProps.columnName = selectedComponent.columnName || currentConfig.fieldKey || currentConfig.columnName;
|
||||
}
|
||||
if (componentId === "v2-list") {
|
||||
extraProps.currentTableName = currentTableName;
|
||||
}
|
||||
if (componentId === "v2-bom-item-editor" || componentId === "v2-bom-tree") {
|
||||
extraProps.currentTableName = currentTableName;
|
||||
extraProps.screenTableName = selectedComponent.tableName || currentTable?.tableName || currentTableName;
|
||||
}
|
||||
if (componentId === "v2-input") {
|
||||
extraProps.allComponents = allComponents;
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={selectedComponent.id} className="space-y-4">
|
||||
<V2ConfigPanel config={currentConfig} onChange={handleV2ConfigChange} {...extraProps} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (componentId) {
|
||||
const definition = ComponentRegistry.getComponent(componentId);
|
||||
|
||||
|
|
@ -219,7 +275,9 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
allTables={allTables}
|
||||
screenTableName={selectedComponent.tableName || currentTable?.tableName || currentTableName}
|
||||
tableName={selectedComponent.tableName || currentTable?.tableName || currentTableName}
|
||||
columnName={(selectedComponent as any).columnName || currentConfig?.columnName || currentConfig?.fieldName}
|
||||
columnName={
|
||||
(selectedComponent as any).columnName || currentConfig?.columnName || currentConfig?.fieldName
|
||||
}
|
||||
inputType={(selectedComponent as any).inputType || currentConfig?.inputType}
|
||||
componentType={componentType}
|
||||
tableColumns={currentTable?.columns || []}
|
||||
|
|
@ -334,11 +392,11 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
return (
|
||||
<div className="space-y-1">
|
||||
{/* DIMENSIONS 섹션 */}
|
||||
<div className="border-b border-border/50 pb-3 mb-3">
|
||||
<h4 className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground py-2">DIMENSIONS</h4>
|
||||
<div className="border-border/50 mb-3 border-b pb-3">
|
||||
<h4 className="text-muted-foreground py-2 text-[10px] font-semibold tracking-wider uppercase">DIMENSIONS</h4>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex-1">
|
||||
<Label className="text-[10px] text-muted-foreground">너비</Label>
|
||||
<Label className="text-muted-foreground text-[10px]">너비</Label>
|
||||
<Input
|
||||
type="number"
|
||||
min={10}
|
||||
|
|
@ -372,7 +430,7 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
/>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<Label className="text-[10px] text-muted-foreground">높이</Label>
|
||||
<Label className="text-muted-foreground text-[10px]">높이</Label>
|
||||
<Input
|
||||
type="number"
|
||||
value={localHeight}
|
||||
|
|
@ -404,7 +462,7 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
/>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<Label className="text-[10px] text-muted-foreground">Z-Index</Label>
|
||||
<Label className="text-muted-foreground text-[10px]">Z-Index</Label>
|
||||
<Input
|
||||
type="number"
|
||||
step="1"
|
||||
|
|
@ -418,10 +476,10 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
|
||||
{/* Title (group/area) */}
|
||||
{(selectedComponent.type === "group" || selectedComponent.type === "area") && (
|
||||
<div className="border-b border-border/50 pb-3 mb-3">
|
||||
<h4 className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground py-2">CONTENT</h4>
|
||||
<div className="border-border/50 mb-3 border-b pb-3">
|
||||
<h4 className="text-muted-foreground py-2 text-[10px] font-semibold tracking-wider uppercase">CONTENT</h4>
|
||||
<div className="flex items-center justify-between py-1.5">
|
||||
<span className="text-xs text-muted-foreground">제목</span>
|
||||
<span className="text-muted-foreground text-xs">제목</span>
|
||||
<div className="w-[160px]">
|
||||
<Input
|
||||
value={group.title || area.title || ""}
|
||||
|
|
@ -433,7 +491,7 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
</div>
|
||||
{selectedComponent.type === "area" && (
|
||||
<div className="flex items-center justify-between py-1.5">
|
||||
<span className="text-xs text-muted-foreground">설명</span>
|
||||
<span className="text-muted-foreground text-xs">설명</span>
|
||||
<div className="w-[160px]">
|
||||
<Input
|
||||
value={area.description || ""}
|
||||
|
|
@ -448,36 +506,46 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
)}
|
||||
|
||||
{/* OPTIONS 섹션 */}
|
||||
<div className="border-b border-border/50 pb-3 mb-3">
|
||||
<h4 className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground py-2">OPTIONS</h4>
|
||||
{(isInputField || widget.required !== undefined) && (() => {
|
||||
const colName = widget.columnName || selectedComponent?.columnName;
|
||||
const colMeta = colName ? currentTable?.columns?.find(
|
||||
(c: any) => (c.columnName || c.column_name || "").toLowerCase() === colName.toLowerCase()
|
||||
) : null;
|
||||
const isNotNull = colMeta && ((colMeta as any).isNullable === "NO" || (colMeta as any).isNullable === "N" || (colMeta as any).is_nullable === "NO" || (colMeta as any).is_nullable === "N");
|
||||
return (
|
||||
<div className="flex items-center justify-between py-1.5">
|
||||
<span className="text-xs text-muted-foreground">
|
||||
필수
|
||||
{isNotNull && <span className="text-muted-foreground/60 ml-1">(NOT NULL)</span>}
|
||||
</span>
|
||||
<Checkbox
|
||||
checked={isNotNull || widget.required === true || selectedComponent.componentConfig?.required === true}
|
||||
onCheckedChange={(checked) => {
|
||||
if (isNotNull) return;
|
||||
handleUpdate("required", checked);
|
||||
handleUpdate("componentConfig.required", checked);
|
||||
}}
|
||||
disabled={!!isNotNull}
|
||||
className="h-4 w-4"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
<div className="border-border/50 mb-3 border-b pb-3">
|
||||
<h4 className="text-muted-foreground py-2 text-[10px] font-semibold tracking-wider uppercase">OPTIONS</h4>
|
||||
{(isInputField || widget.required !== undefined) &&
|
||||
(() => {
|
||||
const colName = widget.columnName || selectedComponent?.columnName;
|
||||
const colMeta = colName
|
||||
? currentTable?.columns?.find(
|
||||
(c: any) => (c.columnName || c.column_name || "").toLowerCase() === colName.toLowerCase(),
|
||||
)
|
||||
: null;
|
||||
const isNotNull =
|
||||
colMeta &&
|
||||
((colMeta as any).isNullable === "NO" ||
|
||||
(colMeta as any).isNullable === "N" ||
|
||||
(colMeta as any).is_nullable === "NO" ||
|
||||
(colMeta as any).is_nullable === "N");
|
||||
return (
|
||||
<div className="flex items-center justify-between py-1.5">
|
||||
<span className="text-muted-foreground text-xs">
|
||||
필수
|
||||
{isNotNull && <span className="text-muted-foreground/60 ml-1">(NOT NULL)</span>}
|
||||
</span>
|
||||
<Checkbox
|
||||
checked={
|
||||
isNotNull || widget.required === true || selectedComponent.componentConfig?.required === true
|
||||
}
|
||||
onCheckedChange={(checked) => {
|
||||
if (isNotNull) return;
|
||||
handleUpdate("required", checked);
|
||||
handleUpdate("componentConfig.required", checked);
|
||||
}}
|
||||
disabled={!!isNotNull}
|
||||
className="h-4 w-4"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
{(isInputField || widget.readonly !== undefined) && (
|
||||
<div className="flex items-center justify-between py-1.5">
|
||||
<span className="text-xs text-muted-foreground">읽기전용</span>
|
||||
<span className="text-muted-foreground text-xs">읽기전용</span>
|
||||
<Checkbox
|
||||
checked={widget.readonly === true || selectedComponent.componentConfig?.readonly === true}
|
||||
onCheckedChange={(checked) => {
|
||||
|
|
@ -489,7 +557,7 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
</div>
|
||||
)}
|
||||
<div className="flex items-center justify-between py-1.5">
|
||||
<span className="text-xs text-muted-foreground">숨김</span>
|
||||
<span className="text-muted-foreground text-xs">숨김</span>
|
||||
<Checkbox
|
||||
checked={selectedComponent.hidden === true || selectedComponent.componentConfig?.hidden === true}
|
||||
onCheckedChange={(checked) => {
|
||||
|
|
@ -505,13 +573,13 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
{isInputField && (
|
||||
<Collapsible>
|
||||
<CollapsibleTrigger className="flex w-full items-center justify-between py-0.5 text-left">
|
||||
<span className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">LABEL</span>
|
||||
<ChevronDown className="h-3 w-3 shrink-0 text-muted-foreground/50" />
|
||||
<span className="text-muted-foreground text-[10px] font-semibold tracking-wider uppercase">LABEL</span>
|
||||
<ChevronDown className="text-muted-foreground/50 h-3 w-3 shrink-0" />
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent className="mt-1.5 space-y-1">
|
||||
{/* 라벨 텍스트 */}
|
||||
<div className="flex items-center justify-between py-1.5">
|
||||
<span className="text-xs text-muted-foreground">텍스트</span>
|
||||
<span className="text-muted-foreground text-xs">텍스트</span>
|
||||
<div className="w-[160px]">
|
||||
<Input
|
||||
value={
|
||||
|
|
@ -531,7 +599,7 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
{/* 위치 + 간격 */}
|
||||
<div className="flex gap-2">
|
||||
<div className="flex-1">
|
||||
<Label className="text-[10px] text-muted-foreground">위치</Label>
|
||||
<Label className="text-muted-foreground text-[10px]">위치</Label>
|
||||
<Select
|
||||
value={selectedComponent.style?.labelPosition || "top"}
|
||||
onValueChange={(value) => handleUpdate("style.labelPosition", value)}
|
||||
|
|
@ -548,12 +616,13 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
</Select>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<Label className="text-[10px] text-muted-foreground">간격</Label>
|
||||
<Label className="text-muted-foreground text-[10px]">간격</Label>
|
||||
<Input
|
||||
value={
|
||||
(selectedComponent.style?.labelPosition === "left" || selectedComponent.style?.labelPosition === "right")
|
||||
? (selectedComponent.style?.labelGap || "8px")
|
||||
: (selectedComponent.style?.labelMarginBottom || "4px")
|
||||
selectedComponent.style?.labelPosition === "left" ||
|
||||
selectedComponent.style?.labelPosition === "right"
|
||||
? selectedComponent.style?.labelGap || "8px"
|
||||
: selectedComponent.style?.labelMarginBottom || "4px"
|
||||
}
|
||||
onChange={(e) => {
|
||||
const pos = selectedComponent.style?.labelPosition;
|
||||
|
|
@ -570,7 +639,7 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
{/* 크기 + 색상 */}
|
||||
<div className="flex gap-2">
|
||||
<div className="flex-1">
|
||||
<Label className="text-[10px] text-muted-foreground">크기</Label>
|
||||
<Label className="text-muted-foreground text-[10px]">크기</Label>
|
||||
<Input
|
||||
value={selectedComponent.style?.labelFontSize || "12px"}
|
||||
onChange={(e) => handleUpdate("style.labelFontSize", e.target.value)}
|
||||
|
|
@ -578,7 +647,7 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
/>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<Label className="text-[10px] text-muted-foreground">색상</Label>
|
||||
<Label className="text-muted-foreground text-[10px]">색상</Label>
|
||||
<ColorPickerWithTransparent
|
||||
value={selectedComponent.style?.labelColor}
|
||||
onChange={(value) => handleUpdate("style.labelColor", value)}
|
||||
|
|
@ -589,7 +658,7 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
</div>
|
||||
{/* 굵기 */}
|
||||
<div className="flex items-center justify-between py-1.5">
|
||||
<span className="text-xs text-muted-foreground">굵기</span>
|
||||
<span className="text-muted-foreground text-xs">굵기</span>
|
||||
<div className="w-[160px]">
|
||||
<Select
|
||||
value={selectedComponent.style?.labelFontWeight || "500"}
|
||||
|
|
@ -609,7 +678,7 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
</div>
|
||||
{/* 표시 */}
|
||||
<div className="flex items-center justify-between py-1.5">
|
||||
<span className="text-xs text-muted-foreground">표시</span>
|
||||
<span className="text-muted-foreground text-xs">표시</span>
|
||||
<Checkbox
|
||||
checked={selectedComponent.style?.labelDisplay === true || selectedComponent.labelDisplay === true}
|
||||
onCheckedChange={(checked) => {
|
||||
|
|
@ -965,7 +1034,7 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
|
||||
{/* 🆕 테이블 데이터 자동 입력 (모든 widget 컴포넌트) */}
|
||||
<Separator />
|
||||
<div className="space-y-3 border-4 border-destructive bg-amber-100 p-4">
|
||||
<div className="border-destructive space-y-3 border-4 bg-amber-100 p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Database className="text-primary h-4 w-4" />
|
||||
<h4 className="text-xs font-semibold">테이블 데이터 자동 입력</h4>
|
||||
|
|
@ -1134,7 +1203,7 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
<Zap className="text-primary h-3 w-3" />
|
||||
<h4 className="text-xs font-semibold">조건부 표시</h4>
|
||||
</div>
|
||||
<div className="rounded-md border border-border p-2">
|
||||
<div className="border-border rounded-md border p-2">
|
||||
<ConditionalConfigPanel
|
||||
config={
|
||||
(selectedComponent as any).conditional || {
|
||||
|
|
|
|||
Loading…
Reference in New Issue