feat: add MySQL import wizard component and backend service for database restoration
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
32612
|
|
||||||
@@ -424,7 +424,7 @@ export function registerIpcHandlers(): void {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle('mysql:import-wizard:check-db', async (_event, { versionId, dbName }) => {
|
ipcMain.handle('mysql:import-wizard:check-db', async (_event, { versionId, dbName, rootPass }) => {
|
||||||
const versions = await mySqlManagerService.getVersions()
|
const versions = await mySqlManagerService.getVersions()
|
||||||
const v = versions.find(v => v.id === versionId)
|
const v = versions.find(v => v.id === versionId)
|
||||||
if (!v) return { exists: false, error: 'MySQL version not found' }
|
if (!v) return { exists: false, error: 'MySQL version not found' }
|
||||||
@@ -438,13 +438,13 @@ export function registerIpcHandlers(): void {
|
|||||||
host: '127.0.0.1',
|
host: '127.0.0.1',
|
||||||
port: v.port,
|
port: v.port,
|
||||||
rootUser: 'root',
|
rootUser: 'root',
|
||||||
rootPass: '' // Assuming root has no password by default in this setup
|
rootPass: rootPass || ''
|
||||||
}, dbName)
|
}, dbName)
|
||||||
|
|
||||||
return { exists }
|
return { exists }
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle('mysql:import-wizard:start', async (event, { versionId, filePath, dbName, user, pass, overwrite }) => {
|
ipcMain.handle('mysql:import-wizard:start', async (event, { versionId, filePath, dbName, user, pass, rootPass, overwrite }) => {
|
||||||
const versions = await mySqlManagerService.getVersions()
|
const versions = await mySqlManagerService.getVersions()
|
||||||
const v = versions.find(v => v.id === versionId)
|
const v = versions.find(v => v.id === versionId)
|
||||||
if (!v) return { success: false, message: 'MySQL version not found' }
|
if (!v) return { success: false, message: 'MySQL version not found' }
|
||||||
@@ -458,7 +458,7 @@ export function registerIpcHandlers(): void {
|
|||||||
host: '127.0.0.1',
|
host: '127.0.0.1',
|
||||||
port: v.port,
|
port: v.port,
|
||||||
rootUser: 'root',
|
rootUser: 'root',
|
||||||
rootPass: ''
|
rootPass: rootPass || ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const log = (msg: string) => event.sender.send('mysql:import:log', msg)
|
const log = (msg: string) => event.sender.send('mysql:import:log', msg)
|
||||||
|
|||||||
@@ -111,15 +111,25 @@ export class MySqlOperationService {
|
|||||||
args.push(`--password=${config.rootPass}`)
|
args.push(`--password=${config.rootPass}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using shell true to use redirecting input
|
onProgress?.(`Executing: "${mysqlPath}" ${args.join(' ')} < "${sqlFilePath}"`)
|
||||||
const command = `"${mysqlPath}" ${args.join(' ')} < "${sqlFilePath}"`
|
|
||||||
onProgress?.(`Executing: mysql ${args.join(' ')} < ${path.basename(sqlFilePath)}`)
|
|
||||||
|
|
||||||
const child = spawn('cmd.exe', ['/c', command], { windowsHide: true })
|
const child = spawn(mysqlPath, args, { windowsHide: true })
|
||||||
|
|
||||||
|
// Pipe the file content to stdin
|
||||||
|
const fileStream = fs.createReadStream(sqlFilePath)
|
||||||
|
fileStream.on('error', (err) => {
|
||||||
|
onProgress?.(`File read error: ${err.message}`)
|
||||||
|
})
|
||||||
|
fileStream.pipe(child.stdin)
|
||||||
|
|
||||||
child.stdout.on('data', (data) => onProgress?.(data.toString()))
|
child.stdout.on('data', (data) => onProgress?.(data.toString()))
|
||||||
child.stderr.on('data', (data) => onProgress?.(data.toString()))
|
child.stderr.on('data', (data) => onProgress?.(data.toString()))
|
||||||
|
|
||||||
|
child.on('error', (err) => {
|
||||||
|
onProgress?.(`Process error: ${err.message}`)
|
||||||
|
resolve({ success: false, message: `Process error: ${err.message}` })
|
||||||
|
})
|
||||||
|
|
||||||
child.on('close', (code) => {
|
child.on('close', (code) => {
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
onProgress?.('Import completed successfully.')
|
onProgress?.('Import completed successfully.')
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ const MySqlImportWizard: React.FC<MySqlImportWizardProps> = ({ open, onClose, my
|
|||||||
const [dbConfig, setDbConfig] = useState({
|
const [dbConfig, setDbConfig] = useState({
|
||||||
dbName: '',
|
dbName: '',
|
||||||
user: '',
|
user: '',
|
||||||
pass: ''
|
pass: '',
|
||||||
|
rootPass: ''
|
||||||
})
|
})
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [logs, setLogs] = useState<string[]>([])
|
const [logs, setLogs] = useState<string[]>([])
|
||||||
@@ -71,7 +72,8 @@ const MySqlImportWizard: React.FC<MySqlImportWizardProps> = ({ open, onClose, my
|
|||||||
setDbConfig({
|
setDbConfig({
|
||||||
dbName: `db_${randomStr}`,
|
dbName: `db_${randomStr}`,
|
||||||
user: `user_${randomStr}`,
|
user: `user_${randomStr}`,
|
||||||
pass: Math.random().toString(36).substring(2, 12)
|
pass: Math.random().toString(36).substring(2, 12),
|
||||||
|
rootPass: ''
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [open, mySqlVersions])
|
}, [open, mySqlVersions])
|
||||||
@@ -108,14 +110,14 @@ const MySqlImportWizard: React.FC<MySqlImportWizardProps> = ({ open, onClose, my
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleStep3Next = async () => {
|
const handleStep3Next = async () => {
|
||||||
if (!dbConfig.dbName || !dbConfig.user || !dbConfig.pass) {
|
if (!dbConfig.dbName || !dbConfig.user) {
|
||||||
Swal.fire('Hata', 'Lütfen tüm alanları doldurun.', 'error')
|
Swal.fire('Hata', 'Lütfen veritabanı adı ve kullanıcıyı doldurun.', 'error')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
const { exists } = await window.api.checkMySqlDb(selectedVersion, dbConfig.dbName)
|
const { exists } = await window.api.checkMySqlDb(selectedVersion, dbConfig.dbName, dbConfig.rootPass)
|
||||||
if (exists) {
|
if (exists) {
|
||||||
const result = await Swal.fire({
|
const result = await Swal.fire({
|
||||||
title: 'Veritabanı Mevcut!',
|
title: 'Veritabanı Mevcut!',
|
||||||
@@ -151,6 +153,7 @@ const MySqlImportWizard: React.FC<MySqlImportWizardProps> = ({ open, onClose, my
|
|||||||
dbName: dbConfig.dbName,
|
dbName: dbConfig.dbName,
|
||||||
user: dbConfig.user,
|
user: dbConfig.user,
|
||||||
pass: dbConfig.pass,
|
pass: dbConfig.pass,
|
||||||
|
rootPass: dbConfig.rootPass,
|
||||||
overwrite: true // Logic handled by checkMySqlDb before
|
overwrite: true // Logic handled by checkMySqlDb before
|
||||||
})
|
})
|
||||||
setImportResult(result)
|
setImportResult(result)
|
||||||
@@ -205,6 +208,15 @@ const MySqlImportWizard: React.FC<MySqlImportWizardProps> = ({ open, onClose, my
|
|||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
<TextField
|
||||||
|
label="Root Şifresi (Eğer varsa)"
|
||||||
|
fullWidth
|
||||||
|
sx={{ mt: 3 }}
|
||||||
|
value={dbConfig.rootPass}
|
||||||
|
type="password"
|
||||||
|
onChange={(e) => setDbConfig({ ...dbConfig, rootPass: e.target.value })}
|
||||||
|
helperText="MySQL 'root' kullanıcısının mevcut şifresini girin. Boşsa boş bırakın."
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
case 2:
|
case 2:
|
||||||
|
|||||||
Reference in New Issue
Block a user