Wizard File Manager liste düzenlendi
This commit is contained in:
parent
8dda4498ef
commit
10bf95da66
6 changed files with 104 additions and 100 deletions
|
|
@ -52,6 +52,8 @@ public class WizardFileInfoDto
|
||||||
public string FileName { get; set; }
|
public string FileName { get; set; }
|
||||||
public string WizardName { get; set; }
|
public string WizardName { get; set; }
|
||||||
public string ListFormCode { get; set; }
|
public string ListFormCode { get; set; }
|
||||||
|
public string DefaultLayout { get; set; }
|
||||||
|
public string MenuIcon { get; set; }
|
||||||
public string CreatedAt { get; set; }
|
public string CreatedAt { get; set; }
|
||||||
public bool HasInsertedRecords { get; set; }
|
public bool HasInsertedRecords { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -407,6 +407,8 @@ public class ListFormWizardAppService(
|
||||||
{
|
{
|
||||||
FileName = fileName,
|
FileName = fileName,
|
||||||
WizardName = seed?.Wizard?.WizardName ?? fileName,
|
WizardName = seed?.Wizard?.WizardName ?? fileName,
|
||||||
|
DefaultLayout = seed?.Wizard?.DefaultLayout ?? string.Empty,
|
||||||
|
MenuIcon = seed?.Wizard?.MenuIcon ?? string.Empty,
|
||||||
ListFormCode = seed?.Wizard?.ListFormCode ?? string.Empty,
|
ListFormCode = seed?.Wizard?.ListFormCode ?? string.Empty,
|
||||||
CreatedAt = fileName.Length >= 12 ? fileName[..12] : fileName,
|
CreatedAt = fileName.Length >= 12 ? fileName[..12] : fileName,
|
||||||
HasInsertedRecords = seed?.InsertedRecords != null &&
|
HasInsertedRecords = seed?.InsertedRecords != null &&
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,8 @@ export interface WizardFileInfoDto {
|
||||||
fileName: string
|
fileName: string
|
||||||
wizardName: string
|
wizardName: string
|
||||||
listFormCode: string
|
listFormCode: string
|
||||||
|
defaultLayout: string
|
||||||
|
menuIcon: string
|
||||||
createdAt: string
|
createdAt: string
|
||||||
hasInsertedRecords: boolean
|
hasInsertedRecords: boolean
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useState, useEffect, useCallback, useMemo } from 'react'
|
import { useState, useEffect, useCallback, useMemo } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { Button, Input, Notification, toast } from '@/components/ui'
|
import { Badge, Button, Input, Notification, toast } from '@/components/ui'
|
||||||
import Container from '@/components/shared/Container'
|
import Container from '@/components/shared/Container'
|
||||||
import ConfirmDialog from '@/components/shared/ConfirmDialog'
|
import ConfirmDialog from '@/components/shared/ConfirmDialog'
|
||||||
import {
|
import {
|
||||||
|
|
@ -12,6 +12,7 @@ import {
|
||||||
FaExclamationTriangle,
|
FaExclamationTriangle,
|
||||||
FaSearch,
|
FaSearch,
|
||||||
FaEdit,
|
FaEdit,
|
||||||
|
FaUser,
|
||||||
} from 'react-icons/fa'
|
} from 'react-icons/fa'
|
||||||
import { FcAcceptDatabase } from 'react-icons/fc'
|
import { FcAcceptDatabase } from 'react-icons/fc'
|
||||||
import { deleteWizardFile, getWizardFiles } from '@/services/wizard.service'
|
import { deleteWizardFile, getWizardFiles } from '@/services/wizard.service'
|
||||||
|
|
@ -21,17 +22,7 @@ import { useStoreState } from '@/store/store'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
import { WizardFileInfoDto } from '@/proxy/admin/wizard/models'
|
import { WizardFileInfoDto } from '@/proxy/admin/wizard/models'
|
||||||
import { UiEvalService } from '@/services/UiEvalService'
|
import { UiEvalService } from '@/services/UiEvalService'
|
||||||
|
import navigationIcon from '@/proxy/menus/navigation-icon.config'
|
||||||
// Timestamp formatı: "202605021730" → "2026-05-02 17:30"
|
|
||||||
const formatTimestamp = (raw: string): string => {
|
|
||||||
if (raw.length < 12) return raw
|
|
||||||
const y = raw.slice(0, 4)
|
|
||||||
const mo = raw.slice(4, 6)
|
|
||||||
const d = raw.slice(6, 8)
|
|
||||||
const h = raw.slice(8, 10)
|
|
||||||
const mi = raw.slice(10, 12)
|
|
||||||
return `${y}-${mo}-${d} ${h}:${mi}`
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ConfirmState {
|
interface ConfirmState {
|
||||||
fileName: string
|
fileName: string
|
||||||
|
|
@ -50,6 +41,9 @@ const WizardFileManager = () => {
|
||||||
const [confirm, setConfirm] = useState<ConfirmState | null>(null)
|
const [confirm, setConfirm] = useState<ConfirmState | null>(null)
|
||||||
const [search, setSearch] = useState('')
|
const [search, setSearch] = useState('')
|
||||||
const [showDbMigrateDialog, setShowDbMigrateDialog] = useState(false)
|
const [showDbMigrateDialog, setShowDbMigrateDialog] = useState(false)
|
||||||
|
const IconComponent = (icon: string) => {
|
||||||
|
return navigationIcon[icon] || FaDatabase // default icon
|
||||||
|
}
|
||||||
|
|
||||||
const filteredFiles = useMemo(() => {
|
const filteredFiles = useMemo(() => {
|
||||||
const q = search.trim().toLowerCase()
|
const q = search.trim().toLowerCase()
|
||||||
|
|
@ -179,64 +173,66 @@ const WizardFileManager = () => {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{filteredFiles.map((f) => (
|
{filteredFiles.map((f) => {
|
||||||
<div
|
const Icon = IconComponent(f.menuIcon)
|
||||||
key={f.fileName}
|
return (
|
||||||
className="flex items-center justify-between p-3 rounded-lg border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800"
|
<div
|
||||||
>
|
key={f.fileName}
|
||||||
<div className="flex items-center gap-3 min-w-0">
|
className="flex items-center justify-between p-3 rounded-lg border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800"
|
||||||
<FaDatabase className="text-indigo-400 shrink-0 text-lg" />
|
>
|
||||||
<div className="min-w-0">
|
<div className="flex items-center gap-3 min-w-0">
|
||||||
<div className="font-medium text-sm text-gray-800 dark:text-gray-200 truncate">
|
<Icon className="text-indigo-400 shrink-0 text-3xl" />
|
||||||
{f.wizardName || f.fileName}
|
<div className="min-w-0">
|
||||||
</div>
|
<div className="font-medium text-sm text-gray-800 dark:text-gray-200 truncate">
|
||||||
<div className="text-xs text-gray-400 flex gap-3 mt-0.5">
|
{f.wizardName || f.fileName} <Badge content={f.defaultLayout} />
|
||||||
<span>{formatTimestamp(f.createdAt)}</span>
|
</div>
|
||||||
<span className="truncate">{f.listFormCode}</span>
|
<div className="text-xs text-gray-400 flex gap-3 mt-0.5">
|
||||||
|
<span className="truncate">{f.fileName} - {f.listFormCode}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center gap-2 shrink-0 ml-3">
|
<div className="flex items-center gap-2 shrink-0 ml-3">
|
||||||
{!f.hasInsertedRecords && (
|
{!f.hasInsertedRecords && (
|
||||||
<span
|
<span
|
||||||
title="Bu dosyada izlenen kayıt bilgisi yok. Eski format olabilir."
|
title="Bu dosyada izlenen kayıt bilgisi yok. Eski format olabilir."
|
||||||
className="text-yellow-500 text-xs flex items-center gap-1"
|
className="text-yellow-500 text-xs flex items-center gap-1"
|
||||||
|
>
|
||||||
|
<FaExclamationTriangle />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="plain"
|
||||||
|
className="text-indigo-500 hover:bg-indigo-50 dark:hover:bg-indigo-900/20"
|
||||||
|
type="button"
|
||||||
|
title={translate('::App.Platform.Edit') || 'Edit'}
|
||||||
|
onClick={() =>
|
||||||
|
navigate(ROUTES_ENUM.protected.saas.listFormManagement.wizard, {
|
||||||
|
state: { editFileName: f.fileName },
|
||||||
|
})
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<FaExclamationTriangle />
|
<FaEdit />
|
||||||
</span>
|
</Button>
|
||||||
)}
|
<Button
|
||||||
<Button
|
size="sm"
|
||||||
size="sm"
|
variant="plain"
|
||||||
variant="plain"
|
className="text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20"
|
||||||
className="text-indigo-500 hover:bg-indigo-50 dark:hover:bg-indigo-900/20"
|
type="button"
|
||||||
type="button"
|
title={translate('::App.Platform.Delete') || 'Delete'}
|
||||||
title={translate('::App.Platform.Edit') || 'Edit'}
|
loading={deletingFile === f.fileName}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
navigate(ROUTES_ENUM.protected.saas.listFormManagement.wizard, {
|
setConfirm({ fileName: f.fileName, wizardName: f.wizardName || f.fileName })
|
||||||
state: { editFileName: f.fileName },
|
}
|
||||||
})
|
>
|
||||||
}
|
<FaTrash />
|
||||||
>
|
</Button>
|
||||||
<FaEdit />
|
</div>
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="plain"
|
|
||||||
className="text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20"
|
|
||||||
type="button"
|
|
||||||
loading={deletingFile === f.fileName}
|
|
||||||
onClick={() =>
|
|
||||||
setConfirm({ fileName: f.fileName, wizardName: f.wizardName || f.fileName })
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<FaTrash />
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
))}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* DB Migrate Confirmation Dialog */}
|
{/* DB Migrate Confirmation Dialog */}
|
||||||
|
|
@ -261,34 +257,36 @@ const WizardFileManager = () => {
|
||||||
|
|
||||||
{/* Delete Confirm Dialog */}
|
{/* Delete Confirm Dialog */}
|
||||||
{confirm && (
|
{confirm && (
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
|
||||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-xl p-6 max-w-sm w-full mx-4">
|
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-xl p-6 max-w-sm w-full mx-4">
|
||||||
<div className="flex items-center gap-3 mb-4">
|
<div className="flex items-center gap-3 mb-4">
|
||||||
<FaExclamationTriangle className="text-red-500 text-xl shrink-0" />
|
<FaExclamationTriangle className="text-red-500 text-xl shrink-0" />
|
||||||
<div>
|
<div>
|
||||||
<p className="font-semibold text-gray-800 dark:text-gray-200">{translate('::App.Platform.DeleteAction')}</p>
|
<p className="font-semibold text-gray-800 dark:text-gray-200">
|
||||||
<p className="text-sm text-gray-500 mt-1">
|
{translate('::App.Platform.DeleteAction')}
|
||||||
{translate('::App.Listforms.WizardFileDeleteConfirm')}
|
</p>
|
||||||
</p>
|
<p className="text-sm text-gray-500 mt-1">
|
||||||
</div>
|
{translate('::App.Listforms.WizardFileDeleteConfirm')}
|
||||||
</div>
|
</p>
|
||||||
<div className="flex justify-end gap-2 mt-4">
|
|
||||||
<Button size="sm" variant="plain" type="button" onClick={() => setConfirm(null)}>
|
|
||||||
İptal
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="solid"
|
|
||||||
color="red"
|
|
||||||
type="button"
|
|
||||||
onClick={handleDeleteConfirm}
|
|
||||||
>
|
|
||||||
{translate('::App.Platform.Delete') || 'Yes, Delete'}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex justify-end gap-2 mt-4">
|
||||||
|
<Button size="sm" variant="plain" type="button" onClick={() => setConfirm(null)}>
|
||||||
|
İptal
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="solid"
|
||||||
|
color="red"
|
||||||
|
type="button"
|
||||||
|
onClick={handleDeleteConfirm}
|
||||||
|
>
|
||||||
|
{translate('::App.Platform.Delete') || 'Yes, Delete'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
|
)}
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -882,11 +882,11 @@ GO`,
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="xs"
|
||||||
variant="default"
|
variant="default"
|
||||||
icon={<FcAcceptDatabase />}
|
icon={<FcAcceptDatabase />}
|
||||||
onClick={() => setShowDbMigrateConfirmDialog(true)}
|
onClick={() => setShowDbMigrateConfirmDialog(true)}
|
||||||
className="shadow-sm"
|
className="shadow-sm px-2 py-1"
|
||||||
title={translate('::App.DbMigrate.StartMessage') || 'Run DB Migration'}
|
title={translate('::App.DbMigrate.StartMessage') || 'Run DB Migration'}
|
||||||
>
|
>
|
||||||
{translate('::ListForms.ListForm.DbMigrate') || 'DB Migrate'}
|
{translate('::ListForms.ListForm.DbMigrate') || 'DB Migrate'}
|
||||||
|
|
@ -895,12 +895,12 @@ GO`,
|
||||||
|
|
||||||
<div className="flex flex-wrap items-center gap-2 sm:gap-3">
|
<div className="flex flex-wrap items-center gap-2 sm:gap-3">
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="xs"
|
||||||
variant="default"
|
variant="default"
|
||||||
icon={<FaCopy />}
|
icon={<FaCopy />}
|
||||||
onClick={handleOpenCopyDialog}
|
onClick={handleOpenCopyDialog}
|
||||||
disabled={!state.selectedDataSource}
|
disabled={!state.selectedDataSource}
|
||||||
className="shadow-sm"
|
className="shadow-sm px-2 py-1"
|
||||||
title={
|
title={
|
||||||
translate('::App.Platform.CopyOrExecuteSql') ||
|
translate('::App.Platform.CopyOrExecuteSql') ||
|
||||||
'Seçili nesneleri kopyala veya SQL script calistir'
|
'Seçili nesneleri kopyala veya SQL script calistir'
|
||||||
|
|
@ -909,23 +909,23 @@ GO`,
|
||||||
{translate('::App.Platform.CopySelectedObjects') || 'Copy Selected Objects'}
|
{translate('::App.Platform.CopySelectedObjects') || 'Copy Selected Objects'}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="xs"
|
||||||
variant="default"
|
variant="default"
|
||||||
icon={<FaFileAlt />}
|
icon={<FaFileAlt />}
|
||||||
onClick={handleNewQuery}
|
onClick={handleNewQuery}
|
||||||
className="shadow-sm"
|
className="shadow-sm px-2 py-1"
|
||||||
>
|
>
|
||||||
{translate('::App.Platform.NewQuery') || 'New Query'}
|
{translate('::App.Platform.NewQuery') || 'New Query'}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="xs"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
color="blue-600"
|
color="blue-600"
|
||||||
icon={<FaPlay />}
|
icon={<FaPlay />}
|
||||||
onClick={handleExecute}
|
onClick={handleExecute}
|
||||||
loading={state.isExecuting}
|
loading={state.isExecuting}
|
||||||
disabled={!state.selectedDataSource}
|
disabled={!state.selectedDataSource}
|
||||||
className="shadow-sm"
|
className="shadow-sm px-2 py-1"
|
||||||
>
|
>
|
||||||
{translate('::App.Platform.Execute')}
|
{translate('::App.Platform.Execute')}
|
||||||
<span className="ml-1 text-xs opacity-75">(F5)</span>
|
<span className="ml-1 text-xs opacity-75">(F5)</span>
|
||||||
|
|
|
||||||
|
|
@ -127,19 +127,19 @@ export const MenuManager = () => {
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
disabled={!isDesignMode || isSaving}
|
disabled={!isDesignMode || isSaving}
|
||||||
className={`
|
className={`
|
||||||
flex items-center gap-2 px-4 py-2 rounded-lg transition-colors
|
flex items-center gap-2 px-2 py-1 rounded-lg transition-colors
|
||||||
${isDesignMode ? 'bg-green-600 hover:bg-green-700 text-white' : 'bg-gray-300 text-gray-500 cursor-not-allowed'}
|
${isDesignMode ? 'bg-green-600 hover:bg-green-700 text-white' : 'bg-gray-300 text-gray-500 cursor-not-allowed'}
|
||||||
${isSaving ? 'opacity-50' : ''}
|
${isSaving ? 'opacity-50' : ''}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
{isSaving ? (
|
{isSaving ? (
|
||||||
<>
|
<>
|
||||||
<FaSpinner size={16} className="animate-spin" />
|
<FaSpinner size={10} className="animate-spin" />
|
||||||
Saving...
|
Saving...
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<FaRegSave size={16} />
|
<FaRegSave size={10} />
|
||||||
Save Changes
|
Save Changes
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue