ImportManager problemi giderildi
This commit is contained in:
parent
66037bf001
commit
3f44b23f57
11 changed files with 347 additions and 66 deletions
|
|
@ -159,9 +159,11 @@ public class ListFormImportAppService : PlatformAppService, IImportAppService
|
|||
try
|
||||
{
|
||||
// Process the selected rows data
|
||||
var processedCount = request.SelectedRowsData?.Count ?? 0;
|
||||
var selectedRowsData = request.SelectedRowsData ?? new List<Dictionary<string, object>>();
|
||||
var processedCount = selectedRowsData.Count;
|
||||
var validCount = 0;
|
||||
var errorCount = 0;
|
||||
var errorDetails = new List<object>();
|
||||
|
||||
if (processedCount > 0)
|
||||
{
|
||||
|
|
@ -173,9 +175,9 @@ public class ListFormImportAppService : PlatformAppService, IImportAppService
|
|||
var lastUpdateIndex = 0;
|
||||
|
||||
// Process each row individually
|
||||
for (int i = 0; i < request.SelectedRowsData.Count; i++)
|
||||
for (int i = 0; i < selectedRowsData.Count; i++)
|
||||
{
|
||||
var rowData = request.SelectedRowsData[i];
|
||||
var rowData = selectedRowsData[i];
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -189,7 +191,7 @@ public class ListFormImportAppService : PlatformAppService, IImportAppService
|
|||
{
|
||||
// If database insert fails, count as error
|
||||
errorCount++;
|
||||
// Log the error if needed
|
||||
errorDetails.Add(new { row = i + 1, message = ex.Message });
|
||||
Logger.LogWarning("Error inserting row {RowIndex} during import for session {SessionId}: {ErrorMessage}", i, session.Id, ex.Message);
|
||||
}
|
||||
|
||||
|
|
@ -209,23 +211,32 @@ public class ListFormImportAppService : PlatformAppService, IImportAppService
|
|||
}
|
||||
|
||||
// Update session with final results
|
||||
execute.Status = "completed";
|
||||
execute.Status = errorCount > 0 ? "completed_with_errors" : "completed";
|
||||
execute.Progress = 100;
|
||||
execute.ExecRows = processedCount;
|
||||
execute.ValidRows = validCount;
|
||||
execute.ErrorRows = errorCount;
|
||||
execute.ErrorsJson = errorDetails.Count > 0 ? JsonSerializer.Serialize(errorDetails) : null;
|
||||
|
||||
await _importSessionExecuteRepository.UpdateAsync(execute, autoSave: true);
|
||||
|
||||
// Update parent session status to reflect execute result
|
||||
session.Status = errorCount > 0 ? "executed_with_errors" : "executed";
|
||||
await _importSessionRepository.UpdateAsync(session, autoSave: true);
|
||||
|
||||
return ObjectMapper.Map<ListFormImportExecute, ListFormImportExecuteDto>(execute);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Update session status to failed
|
||||
// Update execute status to failed
|
||||
execute.Status = "failed";
|
||||
execute.Progress = 0;
|
||||
await _importSessionExecuteRepository.UpdateAsync(execute, autoSave: true);
|
||||
|
||||
// Update parent session status to reflect failure
|
||||
session.Status = "execute_failed";
|
||||
await _importSessionRepository.UpdateAsync(session, autoSave: true);
|
||||
|
||||
throw new UserFriendlyException($"Import failed: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1476,6 +1476,84 @@
|
|||
"en": "Charts",
|
||||
"tr": "Grafikler"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.Uploading",
|
||||
"en": "Uploading...",
|
||||
"tr": "Yükleniyor..."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.Validating",
|
||||
"en": "Validating...",
|
||||
"tr": "Doğrulanıyor..."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.Processing",
|
||||
"en": "Processing...",
|
||||
"tr": "İşleniyor..."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.Uploaded",
|
||||
"en": "Uploaded",
|
||||
"tr": "Yüklendi"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.UploadedDescription",
|
||||
"en": "File uploaded but not imported yet. You can review the rows from preview tab and import.",
|
||||
"tr": "Dosya yüklendi fakat henüz içe aktarılmadı. Preview sekmesinden satırları inceleyip aktarabilirsiniz."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.Failed",
|
||||
"en": "Failed",
|
||||
"tr": "Başarısız"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.FailedDescription",
|
||||
"en": "An error occurred while uploading the file. Please make sure the file is a valid Excel/CSV file and try again.",
|
||||
"tr": "Dosya yüklenirken hata oluştu. Dosyanın geçerli bir Excel/CSV dosyası olduğundan emin olun ve tekrar deneyin."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.Executed",
|
||||
"en": "Executed",
|
||||
"tr": "Başarılı"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.ExecutedDescription",
|
||||
"en": "All rows have been imported successfully.",
|
||||
"tr": "Tüm satırlar başarıyla içe aktarıldı."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.ExecutedWithErrors",
|
||||
"en": "Executed with errors",
|
||||
"tr": "Hatalarla Tamamlandı"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.ExecutedWithErrorsDescription",
|
||||
"en": "Some rows have been imported successfully but some rows failed to import. You can review the error details below and fix the related rows to import again.",
|
||||
"tr": "Bazı satırlar içe aktarılamadı. Hata detaylarını aşağıda inceleyip ilgili satırları düzelterek tekrar yükleyebilirsiniz."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.ExecuteFailed",
|
||||
"en": "Execute Failed",
|
||||
"tr": "İçe Aktarma Başarısız"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.ExecuteFailedDescription",
|
||||
"en": "Import failed due to an unexpected error. Please try again or contact your system administrator.",
|
||||
"tr": "İçe aktarma işlemi beklenmedik bir hata nedeniyle başarısız oldu. Lütfen tekrar deneyin veya sistem yöneticisine başvurun."
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "App.Listforms.ImportManager.DropHere",
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ public static class ListFormSeeder_DefaultJsons
|
|||
R = permissionName,
|
||||
U = permissionName + ".Update",
|
||||
E = true,
|
||||
I = false,
|
||||
I = true,
|
||||
Deny = false
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ import {
|
|||
FaDownload,
|
||||
FaFileExcel,
|
||||
FaFileAlt,
|
||||
FaExclamationTriangle,
|
||||
FaChevronDown,
|
||||
FaChevronUp,
|
||||
} from 'react-icons/fa'
|
||||
import { FileUploadArea } from './FileUploadArea'
|
||||
import { ImportPreview } from './ImportPreview'
|
||||
|
|
@ -173,8 +176,12 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
const getStatusIcon = (status: string) => {
|
||||
switch (status) {
|
||||
case 'uploaded':
|
||||
case 'executed':
|
||||
return <FaCheckCircle className="w-5 h-5 text-green-500" />
|
||||
case 'executed_with_errors':
|
||||
return <FaExclamationTriangle className="w-5 h-5 text-orange-500" />
|
||||
case 'failed':
|
||||
case 'execute_failed':
|
||||
return <FaRegBell className="w-5 h-5 text-red-500" />
|
||||
case 'processing':
|
||||
case 'validating':
|
||||
|
|
@ -187,8 +194,12 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
const getStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case 'uploaded':
|
||||
case 'executed':
|
||||
return 'bg-green-50 text-green-700 border-green-200'
|
||||
case 'executed_with_errors':
|
||||
return 'bg-orange-50 text-orange-700 border-orange-200'
|
||||
case 'failed':
|
||||
case 'execute_failed':
|
||||
return 'bg-red-50 text-red-700 border-red-200'
|
||||
case 'processing':
|
||||
case 'validating':
|
||||
|
|
@ -198,6 +209,105 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
}
|
||||
}
|
||||
|
||||
const getSessionStatusLabel = (status: string) => {
|
||||
switch (status) {
|
||||
case 'uploading':
|
||||
return translate('::App.Listforms.ImportManager.Uploading')
|
||||
case 'validating':
|
||||
return translate('::App.Listforms.ImportManager.Validating')
|
||||
case 'processing':
|
||||
return translate('::App.Listforms.ImportManager.Processing')
|
||||
case 'uploaded':
|
||||
return translate('::App.Listforms.ImportManager.Uploaded')
|
||||
case 'failed':
|
||||
return translate('::App.Listforms.ImportManager.Failed')
|
||||
case 'executed':
|
||||
return translate('::App.Listforms.ImportManager.Executed')
|
||||
case 'executed_with_errors':
|
||||
return translate('::App.Listforms.ImportManager.ExecutedWithErrors')
|
||||
case 'execute_failed':
|
||||
return translate('::App.Listforms.ImportManager.ExecuteFailed')
|
||||
default:
|
||||
return status.charAt(0).toUpperCase() + status.slice(1)
|
||||
}
|
||||
}
|
||||
|
||||
const getSessionGuidance = (status: string) => {
|
||||
switch (status) {
|
||||
case 'uploaded':
|
||||
return translate('::App.Listforms.ImportManager.UploadedDescription')
|
||||
case 'executed':
|
||||
return translate('::App.Listforms.ImportManager.ExecutedDescription')
|
||||
case 'executed_with_errors':
|
||||
return translate('::App.Listforms.ImportManager.ExecutedWithErrorsDescription')
|
||||
case 'execute_failed':
|
||||
return translate('::App.Listforms.ImportManager.ExecuteFailedDescription')
|
||||
case 'failed':
|
||||
return translate('::App.Listforms.ImportManager.FailedDescription')
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const getExecuteStatusIcon = (status: string) => {
|
||||
switch (status) {
|
||||
case 'completed':
|
||||
return <FaCheckCircle className="w-4 h-4 text-green-500" />
|
||||
case 'completed_with_errors':
|
||||
return <FaExclamationTriangle className="w-4 h-4 text-orange-500" />
|
||||
case 'processing':
|
||||
return <FaSync className="w-4 h-4 text-blue-500 animate-spin" />
|
||||
case 'validating':
|
||||
return <FaClock className="w-4 h-4 text-yellow-500" />
|
||||
case 'failed':
|
||||
return <FaRegBell className="w-4 h-4 text-red-500" />
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const getExecuteStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
case 'completed':
|
||||
return 'text-green-600'
|
||||
case 'completed_with_errors':
|
||||
return 'text-orange-600'
|
||||
case 'processing':
|
||||
return 'text-blue-600'
|
||||
case 'validating':
|
||||
return 'text-yellow-600'
|
||||
case 'failed':
|
||||
return 'text-red-600'
|
||||
default:
|
||||
return 'text-slate-600'
|
||||
}
|
||||
}
|
||||
|
||||
const getExecuteStatusLabel = (status: string) => {
|
||||
if (status === 'completed_with_errors') return 'Completed with errors'
|
||||
return status.charAt(0).toUpperCase() + status.slice(1)
|
||||
}
|
||||
|
||||
const [expandedErrors, setExpandedErrors] = useState<Set<string>>(new Set())
|
||||
|
||||
const toggleErrors = (executeId: string) => {
|
||||
setExpandedErrors((prev) => {
|
||||
const next = new Set(prev)
|
||||
if (next.has(executeId)) next.delete(executeId)
|
||||
else next.add(executeId)
|
||||
return next
|
||||
})
|
||||
}
|
||||
|
||||
const parseErrors = (errorsJson?: string): { row: number; message: string }[] => {
|
||||
if (!errorsJson) return []
|
||||
try {
|
||||
return JSON.parse(errorsJson)
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
const generateTemplate = async (format: 'excel' | 'csv') => {
|
||||
setGenerating(true)
|
||||
try {
|
||||
|
|
@ -212,7 +322,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
}
|
||||
|
||||
const getEditableColumns = () => {
|
||||
return gridDto.columnFormats.filter((col: any) => col.permissionDto.i && col.fieldName !== 'Id')
|
||||
return gridDto.columnFormats.filter((col: any) => col.canCreate && col.fieldName !== 'Id')
|
||||
}
|
||||
|
||||
const editableColumns = getEditableColumns()
|
||||
|
|
@ -304,7 +414,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
{editableColumns.map((column: any) => (
|
||||
<tr key={column.fieldName} className="hover:bg-slate-50">
|
||||
<td className="px-2 py-2 font-medium text-slate-800">
|
||||
{translate('::' + column.captionName)}
|
||||
{column.fieldName}
|
||||
</td>
|
||||
<td className="px-4 py-2 text-slate-600">
|
||||
<span
|
||||
|
|
@ -458,7 +568,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
session.status,
|
||||
)}`}
|
||||
>
|
||||
{session.status.charAt(0).toUpperCase() + session.status.slice(1)}
|
||||
{getSessionStatusLabel(session.status)}
|
||||
</span>
|
||||
|
||||
<div className="flex space-x-2">
|
||||
|
|
@ -528,6 +638,34 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Guidance message */}
|
||||
{getSessionGuidance(session.status) && (
|
||||
<div
|
||||
className={`mt-2 mx-1 px-3 py-2 rounded-md text-xs flex items-start space-x-2 ${
|
||||
session.status === 'executed_with_errors' ||
|
||||
session.status === 'failed' ||
|
||||
session.status === 'execute_failed'
|
||||
? 'bg-red-50 text-red-700 border border-red-200'
|
||||
: session.status === 'uploaded'
|
||||
? 'bg-blue-50 text-blue-700 border border-blue-200'
|
||||
: 'bg-green-50 text-green-700 border border-green-200'
|
||||
}`}
|
||||
>
|
||||
<span className="mt-0.5 flex-shrink-0">
|
||||
{session.status === 'executed_with_errors' ||
|
||||
session.status === 'failed' ||
|
||||
session.status === 'execute_failed' ? (
|
||||
<FaExclamationTriangle className="w-3 h-3" />
|
||||
) : session.status === 'uploaded' ? (
|
||||
<FaRegBell className="w-3 h-3" />
|
||||
) : (
|
||||
<FaCheckCircle className="w-3 h-3" />
|
||||
)}
|
||||
</span>
|
||||
<span>{getSessionGuidance(session.status)}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Execute Details Section */}
|
||||
{expandedSessions.has(session.id) && (
|
||||
<div className="mt-3 bg-gradient-to-r from-indigo-50 to-blue-50 border border-indigo-100 rounded-lg shadow-sm hover:shadow-md transition-shadow">
|
||||
|
|
@ -582,35 +720,72 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
|
||||
{/* Sağ: Status */}
|
||||
<div className="flex items-center space-x-2 flex-shrink-0">
|
||||
{execute.status === 'completed' && (
|
||||
<FaCheckCircle className="w-4 h-4 text-green-500" />
|
||||
)}
|
||||
{execute.status === 'processing' && (
|
||||
<FaSync className="w-4 h-4 text-blue-500 animate-spin" />
|
||||
)}
|
||||
{execute.status === 'validating' && (
|
||||
<FaClock className="w-4 h-4 text-yellow-500" />
|
||||
)}
|
||||
{execute.status === 'failed' && (
|
||||
<FaRegBell className="w-4 h-4 text-red-500" />
|
||||
)}
|
||||
{getExecuteStatusIcon(execute.status)}
|
||||
<div
|
||||
className={`text-xs font-medium ${
|
||||
execute.status === 'completed'
|
||||
? 'text-green-600'
|
||||
: execute.status === 'processing'
|
||||
? 'text-blue-600'
|
||||
: execute.status === 'validating'
|
||||
? 'text-yellow-600'
|
||||
: 'text-red-600'
|
||||
}`}
|
||||
className={`text-xs font-medium ${getExecuteStatusColor(execute.status)}`}
|
||||
>
|
||||
{execute.status.charAt(0).toUpperCase() +
|
||||
execute.status.slice(1)}
|
||||
{getExecuteStatusLabel(execute.status)}
|
||||
{execute.status === 'processing' && ` (${execute.progress}%)`}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Error Details */}
|
||||
{(execute.status === 'completed_with_errors' ||
|
||||
execute.status === 'failed') &&
|
||||
execute.errorRows > 0 && (
|
||||
<div className="mt-2">
|
||||
<button
|
||||
onClick={() => toggleErrors(execute.id)}
|
||||
className="flex items-center space-x-1 text-xs text-orange-600 hover:text-orange-700 font-medium"
|
||||
>
|
||||
{expandedErrors.has(execute.id) ? (
|
||||
<FaChevronUp className="w-3 h-3" />
|
||||
) : (
|
||||
<FaChevronDown className="w-3 h-3" />
|
||||
)}
|
||||
<span>
|
||||
{execute.errorRows} hata detayı
|
||||
{expandedErrors.has(execute.id) ? ' gizle' : ' göster'}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
{expandedErrors.has(execute.id) && (
|
||||
<div className="mt-2 max-h-48 overflow-y-auto rounded border border-orange-200 bg-orange-50">
|
||||
{parseErrors(execute.errorsJson).length > 0 ? (
|
||||
<table className="w-full text-xs">
|
||||
<thead className="bg-orange-100 sticky top-0">
|
||||
<tr>
|
||||
<th className="px-3 py-1 text-left font-medium text-orange-700 w-16">
|
||||
Satır
|
||||
</th>
|
||||
<th className="px-3 py-1 text-left font-medium text-orange-700">
|
||||
Hata Mesajı
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-orange-100">
|
||||
{parseErrors(execute.errorsJson).map((err, idx) => (
|
||||
<tr key={idx} className="hover:bg-orange-100">
|
||||
<td className="px-3 py-1 text-orange-700 font-medium">
|
||||
{err.row}
|
||||
</td>
|
||||
<td className="px-3 py-1 text-slate-700">
|
||||
{err.message}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
) : (
|
||||
<p className="px-3 py-2 text-orange-600">
|
||||
Hata detayı mevcut değil.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ export interface ListFormImportDto {
|
|||
id: string
|
||||
listFormCode: string
|
||||
blobName: string
|
||||
status: 'uploading' | 'validating' | 'processing' | 'uploaded' | 'failed'
|
||||
status: 'uploading' | 'validating' | 'processing' | 'uploaded' | 'failed' | 'executed' | 'executed_with_errors' | 'execute_failed'
|
||||
totalRows: number
|
||||
creationTime: string
|
||||
}
|
||||
|
|
@ -13,11 +13,12 @@ export interface ListFormImportExecuteDto {
|
|||
id: string
|
||||
importId: string
|
||||
blobName: string
|
||||
status: 'processing' | 'validating' | 'completed' | 'failed'
|
||||
status: 'processing' | 'validating' | 'completed' | 'completed_with_errors' | 'failed'
|
||||
execRows: number
|
||||
validRows: number
|
||||
errorRows: number
|
||||
progress: number
|
||||
errorsJson?: string
|
||||
creationTime: string
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ export class ImportService {
|
|||
|
||||
if (format === 'excel') {
|
||||
// Create Excel-compatible content
|
||||
const headers = editableColumns.map((col) => col.captionName || col.fieldName)
|
||||
const headers = editableColumns.map((col) => col.fieldName)
|
||||
|
||||
// Create a simple Excel XML format that works with Excel 2010+
|
||||
const excelContent = `<?xml version="1.0"?>
|
||||
|
|
@ -85,7 +85,7 @@ ${headers
|
|||
})
|
||||
} else {
|
||||
// CSV format
|
||||
const headers = editableColumns.map((col) => col.captionName || col.fieldName)
|
||||
const headers = editableColumns.map((col) => col.fieldName)
|
||||
const content = headers.join(',') + '\n'
|
||||
return new Blob([content], { type: 'text/csv' })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,10 +147,11 @@ const ChartDrawer = ({
|
|||
{translate('::App.Platform.ChartDrawer.ChartSeries')}
|
||||
</h2>
|
||||
<Button
|
||||
size="xs"
|
||||
icon={<FaTimes />}
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="p-2 hover:bg-gray-200 rounded-full transition-colors"
|
||||
className="border-0"
|
||||
></Button>
|
||||
</div>
|
||||
|
||||
|
|
@ -158,14 +159,14 @@ const ChartDrawer = ({
|
|||
{/* Add Series Button */}
|
||||
<div className="p-3 border-b">
|
||||
<Button
|
||||
size="sm"
|
||||
block
|
||||
variant="solid"
|
||||
type="button"
|
||||
size="sm"
|
||||
icon={<FaPlus />}
|
||||
onClick={() => {
|
||||
setFieldValue('series', [...values.series, newSeriesValue()])
|
||||
}}
|
||||
className="w-full"
|
||||
>
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
{translate('::App.Platform.ChartDrawer.AddNewSeries')}
|
||||
|
|
@ -190,10 +191,10 @@ const ChartDrawer = ({
|
|||
</span>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
size="xs"
|
||||
variant="plain"
|
||||
icon={<FaMinus />}
|
||||
className="text-red-500 hover:bg-red-100"
|
||||
className="border-0 text-red-500 hover:bg-red-100"
|
||||
onClick={() => {
|
||||
remove(index)
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ import { useListFormColumns } from './useListFormColumns'
|
|||
import { DataType } from 'devextreme/common'
|
||||
import { useStoreState } from '@/store/store'
|
||||
import SubForms from '../form/SubForms'
|
||||
import { ImportDashboard } from '@/components/importManager/ImportDashboard'
|
||||
|
||||
interface TreeProps {
|
||||
listFormCode: string
|
||||
|
|
@ -1241,6 +1242,17 @@ const Tree = (props: TreeProps) => {
|
|||
<SubForms gridDto={gridDto!} formData={formData} level={level ?? 0} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<Dialog
|
||||
width={smaller.md ? '100%' : 1000}
|
||||
isOpen={filterData.isImportModalOpen || false}
|
||||
onClose={() => filterData.setIsImportModalOpen(false)}
|
||||
onRequestClose={() => filterData.setIsImportModalOpen(false)}
|
||||
>
|
||||
<Dialog.Body className="flex flex-col">
|
||||
<ImportDashboard gridDto={gridDto} />
|
||||
</Dialog.Body>
|
||||
</Dialog>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ import { usePWA } from '@/utils/hooks/usePWA'
|
|||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||
import { GanttRef } from 'devextreme-react/cjs/gantt'
|
||||
import { useStoreState } from '@/store'
|
||||
import { cssClass } from 'yet-another-react-lightbox/*'
|
||||
import classNames from 'classnames'
|
||||
|
||||
export interface ISelectBoxData {
|
||||
value?: string
|
||||
|
|
@ -284,7 +282,9 @@ const useFilters = ({
|
|||
icon: 'revert',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Import, Manage ve Export: filtre/state ayarından bağımsız olarak her zaman kontrol et
|
||||
if (checkPermission(gridDto?.gridOptions.permissionDto.i)) {
|
||||
menus.push({
|
||||
text: translate('::ListForms.ListForm.ImportManager'),
|
||||
|
|
@ -309,6 +309,8 @@ const useFilters = ({
|
|||
})
|
||||
}
|
||||
|
||||
if (menus.length > 0) {
|
||||
|
||||
// filtre islemleri ile ilgili fonksiyonlar sayisi cok oldugu icin menu icerisine alindi
|
||||
const menuFilterButtons: ToolbarItem = {
|
||||
location: 'after',
|
||||
|
|
|
|||
|
|
@ -250,6 +250,7 @@ const DatabaseSetup = () => {
|
|||
<div className="flex gap-3">
|
||||
{(status === 'idle' || status === 'error') && !dbExists && (
|
||||
<Button
|
||||
variant='solid'
|
||||
onClick={startMigration}
|
||||
className="px-4 py-2 bg-indigo-600 hover:bg-indigo-500 text-white text-sm font-medium rounded-lg transition-colors"
|
||||
>
|
||||
|
|
|
|||
Loading…
Reference in a new issue