Sql Query Manager güncellemeleri
This commit is contained in:
parent
79c72430ab
commit
a746fea95e
5 changed files with 1841 additions and 22 deletions
|
|
@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
|
|||
namespace Sozsoft.Platform.Migrations
|
||||
{
|
||||
[DbContext(typeof(PlatformDbContext))]
|
||||
[Migration("20260225082054_Initial")]
|
||||
[Migration("20260301173343_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
|
|
@ -13,7 +13,7 @@ import type {
|
|||
} from '@/proxy/sql-query-manager/models'
|
||||
import { SqlObjectType } from '@/proxy/sql-query-manager/models'
|
||||
import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
|
||||
import { FaDatabase, FaPlay, FaSave, FaSyncAlt, FaCloudUploadAlt, FaCode } from 'react-icons/fa'
|
||||
import { FaDatabase, FaPlay, FaSave, FaCloudUploadAlt, FaCode, FaTable } from 'react-icons/fa'
|
||||
import { FaCheckCircle } from 'react-icons/fa'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import SqlObjectExplorer from './components/SqlObjectExplorer'
|
||||
|
|
@ -21,6 +21,7 @@ import SqlEditor, { SqlEditorRef } from './components/SqlEditor'
|
|||
import SqlResultsGrid from './components/SqlResultsGrid'
|
||||
import SqlObjectProperties from './components/SqlObjectProperties'
|
||||
import TemplateDialog from './components/TemplateDialog'
|
||||
import TableDesignerDialog from './components/TableDesignerDialog'
|
||||
import { Splitter } from '@/components/codeLayout/Splitter'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { useStoreState } from '@/store/store'
|
||||
|
|
@ -72,11 +73,18 @@ const SqlQueryManager = () => {
|
|||
isExistingObject: false,
|
||||
})
|
||||
const [showTemplateDialog, setShowTemplateDialog] = useState(false)
|
||||
const [showTableDesignerDialog, setShowTableDesignerDialog] = useState(false)
|
||||
const [designTableData, setDesignTableData] = useState<{ schemaName: string; tableName: string } | null>(null)
|
||||
const [showTemplateConfirmDialog, setShowTemplateConfirmDialog] = useState(false)
|
||||
const [pendingTemplate, setPendingTemplate] = useState<{ content: string; type: string } | null>(
|
||||
null,
|
||||
)
|
||||
|
||||
const handleDesignTable = (schemaName: string, tableName: string) => {
|
||||
setDesignTableData({ schemaName, tableName })
|
||||
setShowTableDesignerDialog(true)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
loadDataSources()
|
||||
}, [])
|
||||
|
|
@ -802,16 +810,6 @@ GO`,
|
|||
</div>
|
||||
|
||||
<div className="flex items-center gap-3">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="solid"
|
||||
color="orange-500"
|
||||
icon={<FaCode />}
|
||||
onClick={() => setShowTemplateDialog(true)}
|
||||
className="shadow-sm"
|
||||
>
|
||||
{translate('::App.Platform.Templates')}
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="solid"
|
||||
|
|
@ -880,6 +878,11 @@ GO`,
|
|||
selectedObject={state.selectedObject}
|
||||
onTemplateSelect={handleTemplateSelect}
|
||||
onShowTableColumns={handleShowTableColumns}
|
||||
onDesignTable={handleDesignTable}
|
||||
onNewTable={() => {
|
||||
setDesignTableData(null)
|
||||
setShowTableDesignerDialog(true)
|
||||
}}
|
||||
refreshTrigger={state.refreshTrigger}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -972,6 +975,20 @@ GO`,
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Table Designer Dialog */}
|
||||
<TableDesignerDialog
|
||||
isOpen={showTableDesignerDialog}
|
||||
onClose={() => {
|
||||
setShowTableDesignerDialog(false)
|
||||
setDesignTableData(null)
|
||||
}}
|
||||
dataSource={state.selectedDataSource}
|
||||
initialTableData={designTableData}
|
||||
onDeployed={() => {
|
||||
setState((prev) => ({ ...prev, refreshTrigger: prev.refreshTrigger + 1 }))
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Template Dialog */}
|
||||
<TemplateDialog
|
||||
isOpen={showTemplateDialog}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
FaEdit,
|
||||
FaTrash,
|
||||
FaTable,
|
||||
FaPlus,
|
||||
} from 'react-icons/fa'
|
||||
import type {
|
||||
SqlFunctionDto,
|
||||
|
|
@ -42,6 +43,8 @@ interface SqlObjectExplorerProps {
|
|||
selectedObject: SqlObject | null
|
||||
onTemplateSelect?: (template: string, templateType: string) => void
|
||||
onShowTableColumns?: (schemaName: string, tableName: string) => void
|
||||
onDesignTable?: (schemaName: string, tableName: string) => void
|
||||
onNewTable?: () => void
|
||||
refreshTrigger?: number
|
||||
}
|
||||
|
||||
|
|
@ -51,6 +54,8 @@ const SqlObjectExplorer = ({
|
|||
selectedObject,
|
||||
onTemplateSelect,
|
||||
onShowTableColumns,
|
||||
onDesignTable,
|
||||
onNewTable,
|
||||
refreshTrigger,
|
||||
}: SqlObjectExplorerProps) => {
|
||||
const { translate } = useLocalization()
|
||||
|
|
@ -506,6 +511,22 @@ const SqlObjectExplorer = ({
|
|||
className="fixed z-50 bg-white dark:bg-gray-800 shadow-lg rounded border border-gray-200 dark:border-gray-700 py-1"
|
||||
style={{ top: contextMenu.y, left: contextMenu.x }}
|
||||
>
|
||||
{contextMenu.node?.id?.startsWith('table-') && (
|
||||
<button
|
||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
||||
onClick={() => {
|
||||
const tableData = contextMenu.node?.data as any
|
||||
if (tableData && onDesignTable) {
|
||||
onDesignTable(tableData.schemaName, tableData.tableName)
|
||||
}
|
||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
||||
}}
|
||||
>
|
||||
<FaTable className="inline mr-2 text-teal-600" />
|
||||
Design
|
||||
</button>
|
||||
)}
|
||||
|
||||
{contextMenu.node?.type === 'object' && contextMenu.node?.objectType && contextMenu.node?.data?.isCustom && (
|
||||
<>
|
||||
<button
|
||||
|
|
@ -547,16 +568,94 @@ const SqlObjectExplorer = ({
|
|||
)}
|
||||
|
||||
{contextMenu.node?.type === 'folder' && (
|
||||
<button
|
||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
||||
onClick={() => {
|
||||
loadObjects()
|
||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
||||
}}
|
||||
>
|
||||
<FaSyncAlt className="inline mr-2" />
|
||||
{translate('::App.Platform.Refresh')}
|
||||
</button>
|
||||
<>
|
||||
{/* Tables folder */}
|
||||
{contextMenu.node.id === 'tables' && (
|
||||
<button
|
||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
||||
onClick={() => {
|
||||
onNewTable?.()
|
||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
||||
}}
|
||||
>
|
||||
<FaPlus className="inline mr-2 text-teal-600" />
|
||||
New Table
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Stored Procedures folder */}
|
||||
{contextMenu.node.id === 'procedures' && (
|
||||
<button
|
||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
||||
onClick={() => {
|
||||
onTemplateSelect?.('', 'create-procedure')
|
||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
||||
}}
|
||||
>
|
||||
<FaPlus className="inline mr-2 text-green-600" />
|
||||
New Stored Procedure
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Views folder */}
|
||||
{contextMenu.node.id === 'views' && (
|
||||
<button
|
||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
||||
onClick={() => {
|
||||
onTemplateSelect?.('', 'create-view')
|
||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
||||
}}
|
||||
>
|
||||
<FaPlus className="inline mr-2 text-purple-600" />
|
||||
New View
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Functions folder */}
|
||||
{contextMenu.node.id === 'functions' && (
|
||||
<button
|
||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
||||
onClick={() => {
|
||||
onTemplateSelect?.('', 'create-scalar-function')
|
||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
||||
}}
|
||||
>
|
||||
<FaPlus className="inline mr-2 text-red-500" />
|
||||
New Function
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Queries folder */}
|
||||
{contextMenu.node.id === 'queries' && (
|
||||
<button
|
||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
||||
onClick={() => {
|
||||
onTemplateSelect?.('', 'select')
|
||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
||||
}}
|
||||
>
|
||||
<FaPlus className="inline mr-2 text-yellow-600" />
|
||||
New Query
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Separator */}
|
||||
{contextMenu.node.id !== 'root' && (
|
||||
<div className="my-1 border-t border-gray-100 dark:border-gray-700" />
|
||||
)}
|
||||
|
||||
{/* Refresh — all folders */}
|
||||
<button
|
||||
className="w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 text-sm"
|
||||
onClick={() => {
|
||||
loadObjects()
|
||||
setContextMenu({ show: false, x: 0, y: 0, node: null })
|
||||
}}
|
||||
>
|
||||
<FaSyncAlt className="inline mr-2" />
|
||||
{translate('::App.Platform.Refresh')}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
1703
ui/src/views/sqlQueryManager/components/TableDesignerDialog.tsx
Normal file
1703
ui/src/views/sqlQueryManager/components/TableDesignerDialog.tsx
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue