From f2652dbb44b22f38938f90f4be17e13e0be4e75c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96zt=C3=BCrk?= Date: Fri, 27 Feb 2026 23:57:11 +0300 Subject: [PATCH] =?UTF-8?q?Wizard=20Step3=20ve=20Wizard=20Step4=20g=C3=BCn?= =?UTF-8?q?cellemesi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Seeds/LanguagesData.json | 4 +- .../Seeds/MenusData.json | 4 +- ui/src/views/admin/listForm/Wizard.tsx | 69 +- ui/src/views/admin/listForm/WizardStep3.tsx | 766 ++++++++++++++++++ ui/src/views/admin/listForm/WizardStep4.tsx | 382 +++++++++ 5 files changed, 1203 insertions(+), 22 deletions(-) create mode 100644 ui/src/views/admin/listForm/WizardStep3.tsx create mode 100644 ui/src/views/admin/listForm/WizardStep4.tsx diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json index 11e405f..46b6f95 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json @@ -1401,8 +1401,8 @@ { "resourceName": "Platform", "key": "App.Listforms.Wizard", - "en": "Wizard", - "tr": "Sihirbaz" + "en": "Listform Wizard", + "tr": "Listform Sihirbazı" }, { "resourceName": "Platform", diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/MenusData.json b/api/src/Sozsoft.Platform.DbMigrator/Seeds/MenusData.json index 47dca34..2912244 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/MenusData.json +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/MenusData.json @@ -1050,10 +1050,10 @@ "IsDisabled": false }, { - "ParentCode": "App.Administration", + "ParentCode": "App.DeveloperKit", "Code": "App.Listforms.Wizard", "DisplayName": "App.Listforms.Wizard", - "Order": 10, + "Order": 9, "Url": "/admin/listform/wizard", "Icon": "FcFlashAuto", "RequiredPermissionName": "App.Listforms.Wizard", diff --git a/ui/src/views/admin/listForm/Wizard.tsx b/ui/src/views/admin/listForm/Wizard.tsx index 8f72a7b..6f1b554 100644 --- a/ui/src/views/admin/listForm/Wizard.tsx +++ b/ui/src/views/admin/listForm/Wizard.tsx @@ -24,6 +24,8 @@ import WizardStep1, { findRootCode, } from './WizardStep1' import WizardStep2, { sqlDataTypeToDbType } from './WizardStep2' +import WizardStep3, { WizardGroup } from './WizardStep3' +import WizardStep4 from './WizardStep4' import { Container } from '@/components/shared' // ─── Formik initial values & validation ────────────────────────────────────── @@ -114,10 +116,14 @@ const Wizard = () => { const [isLoadingColumns, setIsLoadingColumns] = useState(false) const [selectedColumns, setSelectedColumns] = useState>(new Set()) + // ── Editing Form Groups (Step 3) ── + const [editingGroups, setEditingGroups] = useState([]) + const loadColumns = async (dsCode: string, schema: string, name: string) => { if (!dsCode || !name) { setSelectCommandColumns([]) setSelectedColumns(new Set()) + setEditingGroups([]) return } setIsLoadingColumns(true) @@ -126,11 +132,15 @@ const Wizard = () => { const cols = res.data ?? [] setSelectCommandColumns(cols) setSelectedColumns(new Set(cols.map((c) => c.columnName))) + setEditingGroups([]) // Auto-select first column as key field if (cols.length > 0) { const first = cols[0] formikRef.current?.setFieldValue('keyFieldName', first.columnName) - formikRef.current?.setFieldValue('keyFieldDbSourceType', sqlDataTypeToDbType(first.dataType)) + formikRef.current?.setFieldValue( + 'keyFieldDbSourceType', + sqlDataTypeToDbType(first.dataType), + ) } } catch { setSelectCommandColumns([]) @@ -283,6 +293,26 @@ const Wizard = () => { setCurrentStep(2) } + const handleDeploy = async () => { + if (!formikRef.current) throw new Error('Form bulunamadı') + const values = formikRef.current.values + await postListFormWizard({ ...values }) + toast.push( + + {translate('::ListForms.FormBilgileriKaydedildi')} + , + { placement: 'top-end' }, + ) + setTimeout(() => { + navigate( + ROUTES_ENUM.protected.saas.listFormManagement.edit.replace( + ':listFormCode', + values.listFormCode, + ), + ) + }, 1500) + } + return ( { > {({ touched, errors, isSubmitting, values }) => (
- + {/* ─── Step 1: Basic Info ─────────────────────────────── */} {currentStep === 0 && ( { {/* ─── Step 3: List Form Fields ───────────────────────────── */} {currentStep === 2 && ( -
- - -
+ setCurrentStep(1)} + onNext={() => setCurrentStep(3)} + /> )} {/* ─── Step 4: Deploy ───────────────────────────── */} {currentStep === 3 && ( -
- - -
+ setCurrentStep(2)} + onSubmit={handleDeploy} + /> )}
diff --git a/ui/src/views/admin/listForm/WizardStep3.tsx b/ui/src/views/admin/listForm/WizardStep3.tsx new file mode 100644 index 0000000..9437c65 --- /dev/null +++ b/ui/src/views/admin/listForm/WizardStep3.tsx @@ -0,0 +1,766 @@ +import { Button, Dialog } from '@/components/ui' +import { columnEditorTypeListOptions } from '@/views/admin/listForm/edit/options' +import type { DatabaseColumnDto } from '@/proxy/sql-query-manager/models' +import { + DndContext, + DragEndEvent, + DragOverlay, + DragStartEvent, + PointerSensor, + useDraggable, + useDroppable, + useSensor, + useSensors, +} from '@dnd-kit/core' +import { SortableContext, arrayMove, useSortable, rectSortingStrategy } from '@dnd-kit/sortable' +import { CSS } from '@dnd-kit/utilities' +import { useEffect, useState } from 'react' +import { FaGripVertical, FaPlus, FaTimes, FaTrash, FaArrowRight, FaCode } from 'react-icons/fa' + +// ─── Types ──────────────────────────────────────────────────────────────────── +export interface WizardGroupItem { + id: string + dataField: string + editorType: string + editorOptions: string + editorScript: string + colSpan: number + isRequired: boolean +} + +export interface WizardGroup { + id: string + caption: string + colCount: number + items: WizardGroupItem[] +} + +export interface WizardStep3Props { + selectedColumns: Set + selectCommandColumns: DatabaseColumnDto[] + groups: WizardGroup[] + onGroupsChange: (groups: WizardGroup[]) => void + translate: (key: string) => string + onBack: () => void + onNext: () => void +} + +// ─── Helpers ───────────────────────────────────────────────────────────────── +function inferEditorType(sqlType: string): string { + const t = sqlType?.toLowerCase() ?? '' + if (t === 'bit') return 'dxCheckBox' + if ( + [ + 'int', + 'bigint', + 'smallint', + 'tinyint', + 'decimal', + 'float', + 'real', + 'numeric', + 'money', + 'smallmoney', + ].includes(t) + ) + return 'dxNumberBox' + if (['date', 'datetime', 'datetime2', 'smalldatetime', 'datetimeoffset'].includes(t)) + return 'dxDateBox' + return 'dxTextBox' +} + +function newGroupItem(colName: string, sqlType = ''): WizardGroupItem { + return { + id: `${colName}_${Date.now()}`, + dataField: colName, + editorType: inferEditorType(sqlType), + editorOptions: '', + editorScript: '', + colSpan: 1, + isRequired: false, + } +} + +function newGroup(order: number): WizardGroup { + return { + id: `grp_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`, + caption: `Group ${order}`, + colCount: 2, + items: [], + } +} + +// ─── DnD helper IDs ─────────────────────────────────────────────────────────── +const AV_PREFIX = 'av::' +const GRP_PREFIX = 'grp::' +const ITM_PREFIX = 'itm::' + +// ─── Sub-components ─────────────────────────────────────────────────────────── + +function AvailableColumnChip({ colName }: { colName: string }) { + const { attributes, listeners, setNodeRef, isDragging } = useDraggable({ + id: `${AV_PREFIX}${colName}`, + }) + return ( +
+ + {colName} +
+ ) +} + +interface SortableItemProps { + item: WizardGroupItem + groupColCount: number + onEditorTypeChange: (val: string) => void + onEditorOptionsChange: (val: string) => void + onEditorScriptChange: (val: string) => void + onColSpanChange: (val: number) => void + onRequiredChange: (val: boolean) => void + onRemove: () => void +} + +function SortableItem({ + item, + groupColCount, + onEditorTypeChange, + onEditorOptionsChange, + onEditorScriptChange, + onColSpanChange, + onRequiredChange, + onRemove, +}: SortableItemProps) { + const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ + id: `${ITM_PREFIX}${item.id}`, + }) + const style = { + transform: CSS.Transform.toString(transform), + transition, + gridColumn: `span ${Math.min(item.colSpan, groupColCount)}`, + } + return ( +
+ {/* Top row: drag handle + field name + remove */} +
+ + + {item.dataField} + + +
+ + {/* Editor type select */} + + + {/* Editor Options */} +
+ Editor Options +