Skip to content

Commit

Permalink
Refactor and add apply all button
Browse files Browse the repository at this point in the history
Signed-off-by: andy.lee <andy.lee@suse.com>
  • Loading branch information
a110605 committed Jun 6, 2024
1 parent 02b42ff commit 7d5bb9c
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 64 deletions.
162 changes: 99 additions & 63 deletions src/routes/backup/BulkRestoreBackupModal.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from 'react'
import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { Form, Input, InputNumber, Spin, Select, Popover, Alert, Tabs, Button } from 'antd'
import { Form, Input, InputNumber, Spin, Select, message, Popover, Alert, Tabs, Button, Checkbox, Tooltip } from 'antd'
import { ModalBlur } from '../../components'

const TabPane = Tabs.TabPane
Expand Down Expand Up @@ -31,74 +31,75 @@ const modal = ({
form: {
getFieldDecorator,
validateFields,
getFieldsError,
getFieldsValue,
getFieldValue,
setFieldsValue,
},
}) => {
const initConfigs = items.map((i) => ({
name: '',
name: i.volumeName,
numberOfReplicas: i.numberOfReplicas,
dataEngine: 'v1',
accessMode: i.accessMode || null,
latestBackup: i.backupName,
backingImage: i.backingImage,
encrypted: false,
restoreVolumeRecurringJob: 'ignored',
nodeSelector: [],
diskSelector: [],
}))

const [currentTab, setCurrentTab] = useState(0)
const [restoreBackupConfigs, setRestoreBackupConfigs] = useState(initConfigs)
const [done, setDone] = useState(false)
const lastIndex = items.length - 1

useEffect(() => {
if (currentTab === lastIndex && done) {
onOk(restoreBackupConfigs)
}
}, [restoreBackupConfigs])

function handleOk() {
validateFields((errors) => {
if (errors) {
return
}
onOk(restoreBackupConfigs)
}

const handleFieldChange = () => {
setRestoreBackupConfigs(prev => {
const newConfigs = [...prev]
const data = {
...getFieldsValue(),
name: getFieldValue('name').trimLeftAndRight(),
name: getFieldValue('name')?.trimLeftAndRight() || '',
fromBackup: items[currentTab]?.fromBackup || '',
}
setRestoreBackupConfigs(prev => {
const newConfigs = [...prev]
newConfigs.splice(currentTab, 1, data)
return newConfigs
newConfigs.splice(currentTab, 1, data)
return newConfigs
})
}

const handleApplyAll = () => {
// only apply below configs to other configs
const currentConfig = {
numberOfReplicas: getFieldValue('numberOfReplicas'),
dataEngine: getFieldValue('dataEngine'),
accessMode: getFieldValue('accessMode'),
encrypted: getFieldValue('encrypted') || false,
restoreVolumeRecurringJob: getFieldValue('restoreVolumeRecurringJob'),
nodeSelector: getFieldValue('nodeSelector'),
diskSelector: getFieldValue('diskSelector'),
}
setRestoreBackupConfigs(prev => {
const newConfigs = [...prev]
newConfigs.forEach((config, index) => {
if (index !== currentTab) {
newConfigs.splice(index, 1, { ...config, ...currentConfig })
}
})
if (currentTab !== lastIndex) {
const nextIndex = currentTab + 1
setCurrentTab(nextIndex)
const nextConfig = restoreBackupConfigs[nextIndex]
setFieldsValue({
name: nextConfig.name,
numberOfReplicas: nextConfig.numberOfReplicas,
dataEngine: nextConfig.dataEngine,
accessMode: nextConfig.accessMode,
latestBackup: nextConfig.latestBackup,
backingImage: nextConfig.backingImage,
restoreVolumeRecurringJob: nextConfig.restoreVolumeRecurringJob,
nodeSelector: nextConfig.nodeSelector,
diskSelector: nextConfig.diskSelector,
})
} else if (currentTab === lastIndex) {
setDone(true)
}
return newConfigs
})
message.success(`Successfully apply ${getFieldValue('name')} config to all other restore volumes`, 5)
}

const handleFieldChange = () => {
const handleEncryptedCheck = (e) => {
const isChecked = e.target.checked
setRestoreBackupConfigs(prev => {
const newConfigs = [...prev]
const data = {
...getFieldsValue(),
encrypted: isChecked,
name: getFieldValue('name')?.trimLeftAndRight() || '',
fromBackup: items[currentTab]?.fromBackup || '',
}
Expand All @@ -107,23 +108,54 @@ const modal = ({
})
}

const handlePrevious = () => {
const prevIdx = currentTab - 1
setCurrentTab(prevIdx)
const prevConfig = restoreBackupConfigs[prevIdx]
setFieldsValue({
name: prevConfig.name,
numberOfReplicas: prevConfig.numberOfReplicas,
dataEngine: prevConfig.dataEngine,
accessMode: prevConfig.accessMode,
latestBackup: prevConfig.latestBackup,
backingImage: prevConfig.backingImage,
restoreVolumeRecurringJob: prevConfig.restoreVolumeRecurringJob,
nodeSelector: prevConfig.nodeSelector,
diskSelector: prevConfig.diskSelector,
const allFieldsError = { ...getFieldsError() }
const hasFieldsError = Object.values(allFieldsError).some(fieldError => fieldError !== undefined) || false

const handleTabClick = (key) => {
if (hasFieldsError) {
message.error('Please fill in all required fields before switching to another restore volume tab', 5)
return
}
validateFields((errors) => {
if (errors) {
return
}
const data = {
...getFieldsValue(),
name: getFieldValue('name').trimLeftAndRight(),
fromBackup: items[currentTab]?.fromBackup || '',
}
// replace this config with the current form data
setRestoreBackupConfigs(prev => {
const newConfigs = [...prev]
newConfigs.splice(currentTab, 1, data)
return newConfigs
})
})

const newIndex = items.findIndex(i => i.backupName === key)

if (newIndex !== -1) {
setCurrentTab(newIndex)
const nextConfig = restoreBackupConfigs[newIndex]
setFieldsValue({
name: nextConfig.name,
numberOfReplicas: nextConfig.numberOfReplicas,
dataEngine: nextConfig.dataEngine,
accessMode: nextConfig.accessMode,
latestBackup: nextConfig.latestBackup,
backingImage: nextConfig.backingImage,
encrypted: nextConfig.encrypted,
restoreVolumeRecurringJob: nextConfig.restoreVolumeRecurringJob,
nodeSelector: nextConfig.nodeSelector,
diskSelector: nextConfig.diskSelector,
})
}
}

const showWarning = backupVolumes?.some((backupVolume) => backupVolume.name === getFieldsValue().name)
const alertMessage = `The restore volume name (${getFieldsValue().name}) is the same as that of this backup volume, by which the backups created after restoration reside in this backup volume as well.`
const tooltipTitle = `Apply this ${getFieldValue('name')} config to all the other restore volumes, this action will overwrite your previous filled in configs`
const modalOpts = {
title: 'Restore Multiple Latest Backups',
visible,
Expand All @@ -134,24 +166,21 @@ const modal = ({
<Button key="cancel" onClick={onCancel}>
Cancel
</Button>,
<Button key="back" onClick={handlePrevious} disabled={currentTab === 0}>
Previous
</Button>,
<Button key="submit" type="success" onClick={handleOk}>
{currentTab === lastIndex ? 'OK' : 'Next'}
<Tooltip overlayStyle={{ width: 300 }} placement="top" title={tooltipTitle}>
<Button key="applyAll" onClick={handleApplyAll}> Apply Same Config </Button>
</Tooltip>,
<Button key="submit" type="success" onClick={handleOk} disabled={hasFieldsError}>
Ok
</Button>,
],
}

const showWarning = backupVolumes?.some((backupVolume) => backupVolume.name === getFieldsValue().name)
const message = `The restore volume name (${getFieldsValue().name}) is the same as that of this backup volume, by which the backups created after restoration reside in this backup volume as well.`

const item = restoreBackupConfigs[currentTab] || {}
const activeKey = item.latestBackup

return (
<ModalBlur {...modalOpts}>
<Tabs className="restoreBackupTab" activeKey={activeKey} type="card">
<Tabs animated className="restoreBackupTab" activeKey={activeKey} onTabClick={handleTabClick} type="card">
{items.map(i => <TabPane tab={i.volumeName} key={i.backupName} />)}
</Tabs>
<Form key={currentTab} layout="horizontal">
Expand All @@ -161,11 +190,12 @@ const modal = ({
visible={showWarning}
content={
<div style={{ maxWidth: 250 }}>
<Alert message={message} type="warning" />
<Alert message={alertMessage} type="warning" />
</div>
}>
<FormItem label="Volume Name" hasFeedback {...formItemLayout}>
{getFieldDecorator('name', {
initialValue: item.name,
rules: [
{
required: true,
Expand Down Expand Up @@ -231,6 +261,12 @@ const modal = ({
{ backingImages.map(backingImage => <Option key={backingImage.name} value={backingImage.name}>{backingImage.name}</Option>) }
</Select>)}
</FormItem>
<FormItem label="Encrypted" {...formItemLayout}>
{getFieldDecorator('encrypted', {
valuePropName: 'checked',
initialValue: item.encrypted || false,
})(<Checkbox onChange={handleEncryptedCheck} />)}
</FormItem>
<FormItem label="Restore Volume Recurring Job" hasFeedback {...formItemLayout}>
{getFieldDecorator('restoreVolumeRecurringJob', {
initialValue: 'ignored',
Expand Down
8 changes: 7 additions & 1 deletion src/routes/backup/CreateStandbyVolumeModal.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import PropTypes from 'prop-types'
import { Form, Input, InputNumber, Select, Spin, Alert, Popover } from 'antd'
import { Form, Input, InputNumber, Select, Spin, Checkbox, Alert, Popover } from 'antd'
import { ModalBlur } from '../../components'
import { formatMib } from '../../utils/formatter'

Expand Down Expand Up @@ -167,6 +167,12 @@ const modal = ({
{ backingImages.map(backingImage => <Option key={backingImage.name} value={backingImage.name}>{backingImage.name}</Option>) }
</Select>)}
</FormItem>
<FormItem label="Encrypted" {...formItemLayout}>
{getFieldDecorator('encrypted', {
valuePropName: 'encrypted',
initialValue: false,
})(<Checkbox />)}
</FormItem>
<Spin spinning={tagsLoading}>
<FormItem label="Node Tag" hasFeedback {...formItemLayout}>
{getFieldDecorator('nodeSelector', {
Expand Down
6 changes: 6 additions & 0 deletions src/routes/backup/RestoreBackupModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ const modal = ({
{ backingImages.map(backingImage => <Option key={backingImage.name} value={backingImage.name}>{backingImage.name}</Option>) }
</Select>)}
</FormItem>
<FormItem label="Encrypted" {...formItemLayout}>
{getFieldDecorator('encrypted', {
valuePropName: 'encrypted',
initialValue: false,
})(<Checkbox></Checkbox>)}
</FormItem>
<FormItem label="Restore Volume Recurring Job" hasFeedback {...formItemLayout}>
{getFieldDecorator('restoreVolumeRecurringJob', {
initialValue: 'ignored',
Expand Down

0 comments on commit 7d5bb9c

Please sign in to comment.