diff --git a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/GridOptionsDto/GridEditingPopupDto.cs b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/GridOptionsDto/GridEditingPopupDto.cs index 1debf78..927b74f 100644 --- a/api/src/Sozsoft.Platform.Application.Contracts/ListForms/GridOptionsDto/GridEditingPopupDto.cs +++ b/api/src/Sozsoft.Platform.Application.Contracts/ListForms/GridOptionsDto/GridEditingPopupDto.cs @@ -22,5 +22,8 @@ public class GridEditingPopupDto /// popup ekranin kapatildiktan sonra eski konumunu hatirlamasini saglar /// public bool RestorePosition { get; set; } = true; + /// Accepted Values: 'top' | 'bottom' | 'left' | 'right' | 'center' + /// + public string Position { get; set; } = "center"; } diff --git a/ui/public/version.json b/ui/public/version.json index 4ba5c3b..155c39a 100644 --- a/ui/public/version.json +++ b/ui/public/version.json @@ -1,5 +1,5 @@ { - "commit": "dc293fc", + "commit": "168768b", "releases": [ { "version": "1.1.04", diff --git a/ui/src/components/importManager/FileUploadArea.tsx b/ui/src/components/importManager/FileUploadArea.tsx index 113db3d..dc56124 100644 --- a/ui/src/components/importManager/FileUploadArea.tsx +++ b/ui/src/components/importManager/FileUploadArea.tsx @@ -100,8 +100,8 @@ export const FileUploadArea: React.FC = ({
= ({
-
+
{dragActive ? translate('::App.Listforms.ImportManager.DropHere') : translate('::App.Listforms.ImportManager.UploadYourFile')}
-

+

{translate('::App.Listforms.ImportManager.DragOrClick')}

-
+
{translate('::App.Listforms.ImportManager.SupportedFormats')}{' '} {acceptedFormats.join(', ')} • Max size: {maxSize}MB
) : ( -
+
-
+
{selectedFile.name}
-
+
{formatFileSize(selectedFile.size)}
@@ -160,7 +160,7 @@ export const FileUploadArea: React.FC = ({ )} {error && ( -
+
{error}
diff --git a/ui/src/components/importManager/ImportDashboard.tsx b/ui/src/components/importManager/ImportDashboard.tsx index 3fdec01..ad06f9d 100644 --- a/ui/src/components/importManager/ImportDashboard.tsx +++ b/ui/src/components/importManager/ImportDashboard.tsx @@ -195,17 +195,17 @@ export const ImportDashboard: React.FC = ({ gridDto }) => switch (status) { case 'uploaded': case 'executed': - return 'bg-green-50 text-green-700 border-green-200 dark:bg-green-950/30 dark:text-green-300 dark:border-green-900/60' + return 'bg-green-50 text-green-700 border-green-200 dark:bg-gray-800 dark:text-green-300 dark:border-gray-700' case 'executed_with_errors': - return 'bg-orange-50 text-orange-700 border-orange-200 dark:bg-orange-950/30 dark:text-orange-300 dark:border-orange-900/60' + return 'bg-orange-50 text-orange-700 border-orange-200 dark:bg-gray-800 dark:text-orange-300 dark:border-gray-700' case 'failed': case 'execute_failed': - return 'bg-red-50 text-red-700 border-red-200 dark:bg-red-950/30 dark:text-red-300 dark:border-red-900/60' + return 'bg-red-50 text-red-700 border-red-200 dark:bg-gray-800 dark:text-red-300 dark:border-gray-700' case 'processing': case 'validating': - return 'bg-blue-50 text-blue-700 border-blue-200 dark:bg-blue-950/30 dark:text-blue-300 dark:border-blue-900/60' + return 'bg-blue-50 text-blue-700 border-blue-200 dark:bg-gray-800 dark:text-blue-300 dark:border-gray-700' default: - return 'bg-yellow-50 text-yellow-700 border-yellow-200 dark:bg-yellow-950/30 dark:text-yellow-300 dark:border-yellow-900/60' + return 'bg-yellow-50 text-yellow-700 border-yellow-200 dark:bg-gray-800 dark:text-yellow-300 dark:border-gray-700' } } @@ -279,7 +279,7 @@ export const ImportDashboard: React.FC = ({ gridDto }) => case 'failed': return 'text-red-600 dark:text-red-300' default: - return 'text-slate-600 dark:text-slate-400' + return 'text-gray-600 dark:text-gray-400' } } @@ -331,7 +331,7 @@ export const ImportDashboard: React.FC = ({ gridDto }) => return (
{/* Navigation Tabs */} -
+
{['import', 'preview', 'history'].map((tab) => ( @@ -382,10 +382,10 @@ export const ImportDashboard: React.FC = ({ gridDto }) => @@ -394,38 +394,38 @@ export const ImportDashboard: React.FC = ({ gridDto }) =>
- + - - - - - + {editableColumns.map((column: any) => ( - - + - -
+ {translate('::App.Listform.ListformField.Column')} + {translate('::ListForms.ListFormEdit.Type')} + {translate('::App.Required')} + {translate('::Abp.Mailing.Default')}
+
{column.fieldName} + {column.dataType} @@ -439,12 +439,12 @@ export const ImportDashboard: React.FC = ({ gridDto }) => {translate('::App.Listforms.ImportManager.Yes')} ) : ( - + {translate('::App.Listforms.ImportManager.No')} )} + {typeof column.defaultValue === 'object' ? JSON.stringify(column.defaultValue) : column.defaultValue} @@ -458,7 +458,7 @@ export const ImportDashboard: React.FC = ({ gridDto }) => {generating && (
- + {translate('::App.Listforms.ImportManager.GeneratingTemplate')}
@@ -468,8 +468,8 @@ export const ImportDashboard: React.FC = ({ gridDto }) => {/* File Upload - 1/3 width on large screens, full width on mobile */}
-
-

+
+

{translate('::App.Listforms.ImportManager.UploadData')}

@@ -506,9 +506,9 @@ export const ImportDashboard: React.FC = ({ gridDto }) => )}
) : ( -
-
- +
+
+
{translate('::App.Listforms.ImportManager.NoDataToPreview')}
@@ -520,22 +520,15 @@ export const ImportDashboard: React.FC = ({ gridDto }) => )} {activeTab === 'history' && ( -
-
-

- - {translate('::App.Listforms.ImportManager.ImportHistory')} -

-
- -
+
+
{importHistory.map((session) => (
@@ -543,15 +536,15 @@ export const ImportDashboard: React.FC = ({ gridDto }) => {getStatusIcon(session.status)}
-
+
{session.blobName}
-
+
{new Date(session.creationTime).toLocaleString()}
{currentSession?.id === session.id && ( - + {translate('::App.Status.Active')} )} @@ -560,7 +553,7 @@ export const ImportDashboard: React.FC = ({ gridDto }) =>
-
+
{session.totalRows} {translate('::App.Listforms.ImportManager.TotalRows')}
@@ -578,8 +571,8 @@ export const ImportDashboard: React.FC = ({ gridDto }) => onClick={() => toggleSessionExecutes(session.id)} className={`p-2 rounded-lg transition-colors ${ expandedSessions.has(session.id) - ? 'text-red-500 bg-red-50 hover:text-red-600 hover:bg-red-100 dark:bg-red-950/30 dark:text-red-300 dark:hover:bg-red-950/40' - : 'text-slate-400 hover:text-slate-600 hover:bg-slate-100 dark:text-slate-500 dark:hover:text-slate-300 dark:hover:bg-slate-800' + ? 'text-red-500 bg-red-50 hover:text-red-600 hover:bg-red-100 dark:bg-gray-800 dark:text-red-300 dark:hover:bg-gray-700' + : 'text-gray-400 hover:text-gray-600 hover:bg-gray-100 dark:text-gray-500 dark:hover:text-gray-300 dark:hover:bg-gray-800' }`} title={translate('::App.Listforms.ImportManager.ViewExecutionDetails')} > @@ -609,7 +602,7 @@ export const ImportDashboard: React.FC = ({ gridDto }) => } } }} - className="p-2 rounded-lg transition-colors text-slate-400 hover:text-blue-500 hover:bg-blue-50 dark:text-slate-500 dark:hover:text-blue-300 dark:hover:bg-blue-950/30" + className="p-2 rounded-lg transition-colors text-gray-400 hover:text-blue-500 hover:bg-blue-50 dark:text-gray-500 dark:hover:text-blue-300 dark:hover:bg-gray-800" title={translate('::App.Listforms.ImportManager.RefreshExecutionDetails')} > @@ -625,8 +618,8 @@ export const ImportDashboard: React.FC = ({ gridDto }) => disabled={currentSession?.id === session.id} className={`p-2 rounded-lg transition-colors ${ currentSession?.id === session.id - ? 'text-slate-300 dark:text-slate-600 cursor-not-allowed' - : 'text-slate-400 hover:text-red-500 hover:bg-red-50 dark:text-slate-500 dark:hover:text-red-300 dark:hover:bg-red-950/30' + ? 'text-gray-300 dark:text-gray-600 cursor-not-allowed' + : 'text-gray-400 hover:text-red-500 hover:bg-red-50 dark:text-gray-500 dark:hover:text-red-300 dark:hover:bg-gray-800' }`} title={ currentSession?.id === session.id @@ -647,10 +640,10 @@ export const ImportDashboard: React.FC = ({ gridDto }) => session.status === 'executed_with_errors' || session.status === 'failed' || session.status === 'execute_failed' - ? 'bg-red-50 text-red-700 border border-red-200 dark:bg-red-950/30 dark:text-red-300 dark:border-red-900/60' + ? 'bg-red-50 text-red-700 border border-red-200 dark:bg-gray-800 dark:text-red-300 dark:border-gray-700' : session.status === 'uploaded' - ? 'bg-blue-50 text-blue-700 border border-blue-200 dark:bg-blue-950/30 dark:text-blue-300 dark:border-blue-900/60' - : 'bg-green-50 text-green-700 border border-green-200 dark:bg-green-950/30 dark:text-green-300 dark:border-green-900/60' + ? 'bg-blue-50 text-blue-700 border border-blue-200 dark:bg-gray-800 dark:text-blue-300 dark:border-gray-700' + : 'bg-green-50 text-green-700 border border-green-200 dark:bg-gray-800 dark:text-green-300 dark:border-gray-700' }`} > @@ -670,10 +663,10 @@ export const ImportDashboard: React.FC = ({ gridDto }) => {/* Execute Details Section */} {expandedSessions.has(session.id) && ( -
+
{loadingExecutes.has(session.id) ? ( -
+
{translate('::App.Listforms.ImportManager.LoadingExecutionDetails')} @@ -683,22 +676,22 @@ export const ImportDashboard: React.FC = ({ gridDto }) => sessionExecutes[session.id].length > 0 ? (
{sessionExecutes[session.id].map((execute) => ( -
+
{/* Sol: Tarih */}
-
+
{new Date(execute.creationTime).toLocaleString()}
{/* Orta: Executed, Valid, Errors */} -
+
-
+
{execute.execRows}
-
+
{translate('::App.Listforms.ImportManager.Executed')}
@@ -706,7 +699,7 @@ export const ImportDashboard: React.FC = ({ gridDto }) =>
{execute.validRows}
-
+
{translate('::App.Listforms.ImportManager.Valid')}
@@ -714,7 +707,7 @@ export const ImportDashboard: React.FC = ({ gridDto }) =>
{execute.errorRows}
-
+
{translate('::App.Listforms.ImportManager.Errors')}
@@ -753,10 +746,10 @@ export const ImportDashboard: React.FC = ({ gridDto }) => {expandedErrors.has(execute.id) && ( -
+
{parseErrors(execute.errorsJson).length > 0 ? ( - + - + {parseErrors(execute.errorsJson).map((err, idx) => ( - @@ -795,7 +788,7 @@ export const ImportDashboard: React.FC = ({ gridDto }) => ))} ) : ( -
+
{translate('::App.Listforms.ImportManager.NoExecutionRecords')}
)} @@ -806,8 +799,8 @@ export const ImportDashboard: React.FC = ({ gridDto }) => ))} {importHistory.length === 0 && ( -
- +
+
{translate('::App.Listforms.ImportManager.NoImportHistory')}
diff --git a/ui/src/components/importManager/ImportPreview.tsx b/ui/src/components/importManager/ImportPreview.tsx index de4db27..93df1bc 100644 --- a/ui/src/components/importManager/ImportPreview.tsx +++ b/ui/src/components/importManager/ImportPreview.tsx @@ -100,13 +100,13 @@ export const ImportPreview: React.FC = ({ const getStatusColor = (status: string) => { switch (status) { case 'uploaded': - return 'text-green-600 bg-green-50 border-green-200 dark:text-green-300 dark:bg-green-950/30 dark:border-green-900/60' + return 'text-green-600 bg-green-50 border-green-200 dark:text-green-300 dark:bg-gray-800 dark:border-gray-700' case 'failed': - return 'text-red-600 bg-red-50 border-red-200 dark:text-red-300 dark:bg-red-950/30 dark:border-red-900/60' + return 'text-red-600 bg-red-50 border-red-200 dark:text-red-300 dark:bg-gray-800 dark:border-gray-700' case 'validating': - return 'text-yellow-600 bg-yellow-50 border-yellow-200 dark:text-yellow-300 dark:bg-yellow-950/30 dark:border-yellow-900/60' + return 'text-yellow-600 bg-yellow-50 border-yellow-200 dark:text-yellow-300 dark:bg-gray-800 dark:border-gray-700' default: - return 'text-blue-600 bg-blue-50 border-blue-200 dark:text-blue-300 dark:bg-blue-950/30 dark:border-blue-900/60' + return 'text-blue-600 bg-blue-50 border-blue-200 dark:text-blue-300 dark:bg-gray-800 dark:border-gray-700' } } @@ -145,14 +145,14 @@ export const ImportPreview: React.FC = ({ } return ( -
+
{/* Header */} -
+
{/* Başlık kısmı - Üstte mobile, solda desktop */}
-

+

{translate('::App.Listforms.ImportManager.ImportPreviewTitle')}

@@ -160,7 +160,7 @@ export const ImportPreview: React.FC = ({ {/* İstatistik kartları - Mobile'da alt alta, desktop'ta yan yana */}
-
+
{previewData?.rows?.length || session.totalRows || 0}{' '} {translate('::App.Listforms.ImportManager.TotalRows')} @@ -184,16 +184,16 @@ export const ImportPreview: React.FC = ({ {/* Preview Data */} {previewData && previewData.headers && previewData.headers.length > 0 ? ( -
-

+
+

{translate('::App.Listforms.ImportManager.DataPreviewTitle')}

-
+

Satır @@ -766,16 +759,16 @@ export const ImportDashboard: React.FC = ({ gridDto }) =>
{err.row} + {err.message}
- + - ))} - + {previewData.rows.map((row: any[], rowIndex: number) => ( @@ -242,25 +242,25 @@ export const ImportPreview: React.FC = ({ ) : previewData && previewData.headers && previewData.headers.length === 0 ? ( -
+
-

+

{translate('::App.Listforms.ImportManager.NoDataFoundTitle')}

-

+

{translate('::App.Listforms.ImportManager.NoDataFoundDescription')}

) : ( -
+
-

+

{translate('::App.Listforms.ImportManager.LoadingPreviewTitle')}

-

+

{translate('::App.Listforms.ImportManager.LoadingPreviewDescription')}

@@ -271,7 +271,7 @@ export const ImportPreview: React.FC = ({
{/* Success Message */} {showSuccessMessage && lastExecutionResult && ( -
+
@@ -314,7 +314,7 @@ export const ImportPreview: React.FC = ({
- diff --git a/ui/src/components/importManager/ImportProgress.tsx b/ui/src/components/importManager/ImportProgress.tsx index 9cd9aae..5ae6f2d 100644 --- a/ui/src/components/importManager/ImportProgress.tsx +++ b/ui/src/components/importManager/ImportProgress.tsx @@ -59,17 +59,17 @@ export const ImportProgress: React.FC = ({ session }) => { } return ( -
+
{/* Status Icon */}
{getStatusIcon()}
{/* Status Message */}
-

+

{getStatusMessage()}

-

+

{translate('::App.Listforms.Status.Processing')}{' '} {session.blobName}

@@ -77,11 +77,11 @@ export const ImportProgress: React.FC = ({ session }) => { {/* Progress Bar */}
-
+
{translate('::App.Listforms.ImportManager.ImportProgress.ProgressLabel')} {Math.round(getProgressPercentage())}%
-
+
) => void width?: string | number @@ -74,10 +75,16 @@ export interface DialogProps extends ReactModal.Props { const Dialog = (props: DialogProps) => { const currentSize = useWindowSize() const [isMaximized, setIsMaximized] = useState(false) - const [originalDimensions, setOriginalDimensions] = useState<{ - width?: string | number - height?: string | number - }>({}) + const [position, setPosition] = useState<{ x: number; y: number } | null>(null) + const [isDragHandleHovered, setIsDragHandleHovered] = useState(false) + const dragStartRef = useRef<{ + pointerX: number + pointerY: number + x: number + y: number + width: number + height: number + } | null>(null) const { bodyOpenClassName, @@ -87,6 +94,7 @@ const Dialog = (props: DialogProps) => { closable = true, closeTimeoutMS = 150, contentClassName, + draggable = true, height, isOpen, onClose, @@ -100,6 +108,37 @@ const Dialog = (props: DialogProps) => { ...rest } = props + useEffect(() => { + if (!isOpen) { + setPosition(null) + setIsMaximized(false) + setIsDragHandleHovered(false) + } + }, [isOpen]) + + useEffect(() => { + if (typeof window === 'undefined') { + return + } + + setPosition((currentPosition) => { + if (!currentPosition) { + return currentPosition + } + + const nextPosition = { + x: Math.min(currentPosition.x, window.innerWidth - 24), + y: Math.min(currentPosition.y, window.innerHeight - 24), + } + + if (nextPosition.x === currentPosition.x && nextPosition.y === currentPosition.y) { + return currentPosition + } + + return nextPosition + }) + }, [currentSize.width, currentSize.height]) + const onCloseClick = (e: MouseEvent) => { onClose?.(e) } @@ -108,12 +147,12 @@ const Dialog = (props: DialogProps) => { (e: MouseEvent) => { e.stopPropagation() if (!isMaximized) { - setOriginalDimensions({ width, height }) setIsMaximized(true) + setIsDragHandleHovered(false) onMaximize?.() } }, - [isMaximized, width, height, onMaximize], + [isMaximized, onMaximize], ) const handleRestore = useCallback( @@ -127,6 +166,125 @@ const Dialog = (props: DialogProps) => { [isMaximized, onRestore], ) + const isDragHandle = ( + target: EventTarget | null, + currentTarget: HTMLDivElement, + clientY: number, + ) => { + if (!(target instanceof HTMLElement)) { + return false + } + + const interactiveSelector = [ + 'a', + 'button', + 'input', + 'textarea', + 'select', + '[role="button"]', + '[contenteditable="true"]', + '.window-controls', + '.close-btn', + ].join(',') + + if (target.closest(interactiveSelector)) { + return false + } + + const header = target.closest('.dialog-header') + if (header && currentTarget.contains(header)) { + return true + } + + const topDragArea = 56 + const bounds = currentTarget.getBoundingClientRect() + return clientY - bounds.top <= topDragArea + } + + const handleDragStart = useCallback( + (e: MouseEvent) => { + if ( + !draggable || + isMaximized || + e.button !== 0 || + !isDragHandle(e.target, e.currentTarget, e.clientY) + ) { + return + } + + const modalElement = e.currentTarget.closest('.dialog') + if (!(modalElement instanceof HTMLElement)) { + return + } + + const bounds = modalElement.getBoundingClientRect() + + dragStartRef.current = { + pointerX: e.clientX, + pointerY: e.clientY, + x: bounds.left, + y: bounds.top, + width: bounds.width, + height: bounds.height, + } + + setPosition({ x: bounds.left, y: bounds.top }) + e.preventDefault() + }, + [draggable, isMaximized], + ) + + const handleDragCursor = useCallback( + (e: MouseEvent) => { + const nextIsDragHandle = + draggable && !isMaximized && isDragHandle(e.target, e.currentTarget, e.clientY) + + setIsDragHandleHovered((current) => + current === nextIsDragHandle ? current : nextIsDragHandle, + ) + }, + [draggable, isMaximized], + ) + + const handleDragCursorLeave = useCallback(() => { + setIsDragHandleHovered(false) + }, []) + + useEffect(() => { + if (typeof window === 'undefined') { + return + } + + const handleDragMove = (e: globalThis.MouseEvent) => { + const dragStart = dragStartRef.current + if (!dragStart) { + return + } + + const nextX = dragStart.x + e.clientX - dragStart.pointerX + const nextY = dragStart.y + e.clientY - dragStart.pointerY + const maxX = window.innerWidth - Math.min(dragStart.width, 120) + const maxY = window.innerHeight - Math.min(dragStart.height, 80) + + setPosition({ + x: Math.max(0, Math.min(nextX, maxX)), + y: Math.max(0, Math.min(nextY, maxY)), + }) + } + + const handleDragEnd = () => { + dragStartRef.current = null + } + + window.addEventListener('mousemove', handleDragMove) + window.addEventListener('mouseup', handleDragEnd) + + return () => { + window.removeEventListener('mousemove', handleDragMove) + window.removeEventListener('mouseup', handleDragEnd) + } + }, []) + const renderCloseButton = ( ) @@ -182,6 +340,15 @@ const Dialog = (props: DialogProps) => { zIndex: 1000, } } else { + if (position) { + contentStyle.content.position = 'fixed' + contentStyle.content.top = position.y + contentStyle.content.left = position.x + contentStyle.content.right = 'auto' + contentStyle.content.bottom = 'auto' + contentStyle.content.margin = 0 + } + if (currentWidth !== undefined) { contentStyle.content.width = currentWidth @@ -232,7 +399,11 @@ const Dialog = (props: DialogProps) => { style={{ width: isMaximized ? '100vw' : 'auto', height: isMaximized ? '100vh' : 'auto', + cursor: isDragHandleHovered || dragStartRef.current ? 'move' : undefined, }} + onMouseDown={handleDragStart} + onMouseMove={handleDragCursor} + onMouseLeave={handleDragCursorLeave} > {closable && !showWindowControls && renderCloseButton} {closable && showWindowControls && renderWindowControls} diff --git a/ui/src/proxy/form/models.ts b/ui/src/proxy/form/models.ts index cda9711..21b1add 100644 --- a/ui/src/proxy/form/models.ts +++ b/ui/src/proxy/form/models.ts @@ -505,6 +505,7 @@ export interface GridEditingPopupDto { resizeEnabled: boolean dragEnabled: boolean restorePosition: boolean + position?: any } export interface GridFilterRowDto { diff --git a/ui/src/views/developerKit/SqlTableDesignerDialog.tsx b/ui/src/views/developerKit/SqlTableDesignerDialog.tsx index d383d31..3607432 100644 --- a/ui/src/views/developerKit/SqlTableDesignerDialog.tsx +++ b/ui/src/views/developerKit/SqlTableDesignerDialog.tsx @@ -2739,7 +2739,7 @@ const SqlTableDesignerDialog = ({ return ( - + {/* Header */}
diff --git a/ui/src/views/list/Grid.tsx b/ui/src/views/list/Grid.tsx index 31a504e..332373d 100644 --- a/ui/src/views/list/Grid.tsx +++ b/ui/src/views/list/Grid.tsx @@ -1557,7 +1557,7 @@ const Grid = (props: GridProps) => { at: 'top center', of: typeof window !== 'undefined' ? window : undefined, } - : undefined, + : gridDto.gridOptions.editingOptionDto?.popup?.position, resizeEnabled: gridDto.gridOptions.editingOptionDto?.popup?.resizeEnabled, fullScreen: isPopupFullScreen, dragEnabled: gridDto.gridOptions.editingOptionDto?.popup?.dragEnabled, @@ -1935,7 +1935,12 @@ const Grid = (props: GridProps) => { onClose={() => filterData.setIsImportModalOpen(false)} onRequestClose={() => filterData.setIsImportModalOpen(false)} > - + +

+ {translate('::ListForms.ListForm.ImportManager')} +

+
+
diff --git a/ui/src/views/list/Tree.tsx b/ui/src/views/list/Tree.tsx index cd9261f..aabdfb1 100644 --- a/ui/src/views/list/Tree.tsx +++ b/ui/src/views/list/Tree.tsx @@ -1217,7 +1217,7 @@ const Tree = (props: TreeProps) => { at: 'top center', of: typeof window !== 'undefined' ? window : undefined, } - : undefined, + : gridDto.gridOptions.editingOptionDto?.popup?.position, resizeEnabled: gridDto.gridOptions.editingOptionDto?.popup?.resizeEnabled, fullScreen: isPopupFullScreen, dragEnabled: gridDto.gridOptions.editingOptionDto?.popup?.dragEnabled, @@ -1675,6 +1675,11 @@ const Tree = (props: TreeProps) => { onClose={() => filterData.setIsImportModalOpen(false)} onRequestClose={() => filterData.setIsImportModalOpen(false)} > + +

+ {translate('::ListForms.ListForm.ImportManager')} +

+
+ = ({ {previewData.headers.map((header: string, index: number) => ( {header}
@@ -230,7 +230,7 @@ export const ImportPreview: React.FC = ({ {row.map((cell, cellIndex) => ( {cell?.toString() || '-'}