mirror of
https://github.com/OpenNebula/one.git
synced 2025-02-01 05:47:01 +03:00
F OpenNebula/one#6029: Add NAME and INCREMENT_ID on FSunstone (#2505)
(cherry picked from commit ef6faaa0cdf9a72b65830e6e01441099c8c7daa7)
This commit is contained in:
parent
f47bfa4a5c
commit
7591cf0dd3
@ -13,9 +13,10 @@
|
|||||||
* See the License for the specific language governing permissions and *
|
* See the License for the specific language governing permissions and *
|
||||||
* limitations under the License. *
|
* limitations under the License. *
|
||||||
* ------------------------------------------------------------------------- */
|
* ------------------------------------------------------------------------- */
|
||||||
import { boolean, object, ObjectSchema } from 'yup'
|
import { INPUT_TYPES, T } from 'client/constants'
|
||||||
import { Field, getValidationFromFields } from 'client/utils'
|
import { timeFromMilliseconds } from 'client/models/Helper'
|
||||||
import { T, INPUT_TYPES } from 'client/constants'
|
import { Field, arrayToOptions, getValidationFromFields } from 'client/utils'
|
||||||
|
import { ObjectSchema, boolean, object, string } from 'yup'
|
||||||
|
|
||||||
const NO_NIC = {
|
const NO_NIC = {
|
||||||
name: 'no_nic',
|
name: 'no_nic',
|
||||||
@ -33,14 +34,41 @@ const NO_IP = {
|
|||||||
grid: { xs: 12, md: 6 },
|
grid: { xs: 12, md: 6 },
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
const NAME = {
|
||||||
* @returns {Field[]} Fields
|
name: 'name',
|
||||||
*/
|
label: T.Name,
|
||||||
export const FIELDS = () => [NO_NIC, NO_IP]
|
type: INPUT_TYPES.TEXT,
|
||||||
|
validation: string(),
|
||||||
|
grid: { xs: 12, md: 6 },
|
||||||
|
}
|
||||||
|
|
||||||
|
const INCREMENT_ID = ({ increments = [] }) => ({
|
||||||
|
name: 'increment_id',
|
||||||
|
label: T.IncrementId,
|
||||||
|
type: INPUT_TYPES.SELECT,
|
||||||
|
values: arrayToOptions(increments, {
|
||||||
|
addEmpty: true,
|
||||||
|
getText: (increment) =>
|
||||||
|
`${increment.id}: ${timeFromMilliseconds(increment.date)
|
||||||
|
.toFormat('ff')
|
||||||
|
.replace(',', '')} (${increment.source})`,
|
||||||
|
getValue: (increment) => increment.id,
|
||||||
|
}),
|
||||||
|
validation: string(),
|
||||||
|
grid: { xs: 12, md: 6 },
|
||||||
|
fieldProps: {
|
||||||
|
disabled: increments.length === 0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {object} [stepProps] - Step props
|
* @param {object} [data] - Backup data
|
||||||
|
* @returns {Field[]} Fields
|
||||||
|
*/
|
||||||
|
export const FIELDS = (data = {}) => [NAME, INCREMENT_ID(data), NO_NIC, NO_IP]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {object} [data] - Backup data
|
||||||
* @returns {ObjectSchema} Schema
|
* @returns {ObjectSchema} Schema
|
||||||
*/
|
*/
|
||||||
export const SCHEMA = (stepProps) =>
|
export const SCHEMA = (data) => object(getValidationFromFields(FIELDS(data)))
|
||||||
object(getValidationFromFields(FIELDS(stepProps)))
|
|
||||||
|
@ -21,21 +21,32 @@ import DatastoresTable, {
|
|||||||
} from 'client/components/Forms/Backup/RestoreForm/Steps/DatastoresTable'
|
} from 'client/components/Forms/Backup/RestoreForm/Steps/DatastoresTable'
|
||||||
import { createSteps } from 'client/utils'
|
import { createSteps } from 'client/utils'
|
||||||
|
|
||||||
const Steps = createSteps(
|
const Steps = createSteps([BasicConfiguration, DatastoresTable], {
|
||||||
(app) => [BasicConfiguration, DatastoresTable].filter(Boolean),
|
transformInitialValue: (increments, schema) => {
|
||||||
{
|
const castedValuesBasic = schema.cast(
|
||||||
transformInitialValue: (app, schema) =>
|
{ [BASIC_ID]: { increments } },
|
||||||
schema.cast({}, { context: { app } }),
|
{ stripUnknown: true }
|
||||||
transformBeforeSubmit: (formData) => {
|
)
|
||||||
const { [BASIC_ID]: configuration, [DATASTORE_ID]: [datastore] = [] } =
|
|
||||||
formData
|
|
||||||
|
|
||||||
return {
|
const castedValuesDatastore = schema.cast(
|
||||||
datastore: datastore?.ID,
|
{ [DATASTORE_ID]: {} },
|
||||||
...configuration,
|
{ stripUnknown: true }
|
||||||
}
|
)
|
||||||
},
|
|
||||||
}
|
return {
|
||||||
)
|
[BASIC_ID]: castedValuesBasic[BASIC_ID],
|
||||||
|
[DATASTORE_ID]: castedValuesDatastore[DATASTORE_ID],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
transformBeforeSubmit: (formData) => {
|
||||||
|
const { [BASIC_ID]: configuration, [DATASTORE_ID]: [datastore] = [] } =
|
||||||
|
formData
|
||||||
|
|
||||||
|
return {
|
||||||
|
datastore: datastore?.ID,
|
||||||
|
...configuration,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
export default Steps
|
export default Steps
|
||||||
|
@ -24,11 +24,11 @@ import {
|
|||||||
useRestoreBackupMutation,
|
useRestoreBackupMutation,
|
||||||
} from 'client/features/OneApi/image'
|
} from 'client/features/OneApi/image'
|
||||||
|
|
||||||
import { ChangeGroupForm, ChangeUserForm } from 'client/components/Forms/Vm'
|
|
||||||
import { RestoreForm } from 'client/components/Forms/Backup'
|
import { RestoreForm } from 'client/components/Forms/Backup'
|
||||||
|
import { ChangeGroupForm, ChangeUserForm } from 'client/components/Forms/Vm'
|
||||||
import {
|
import {
|
||||||
createActions,
|
|
||||||
GlobalAction,
|
GlobalAction,
|
||||||
|
createActions,
|
||||||
} from 'client/components/Tables/Enhanced/Utils'
|
} from 'client/components/Tables/Enhanced/Utils'
|
||||||
|
|
||||||
import { Translate } from 'client/components/HOC'
|
import { Translate } from 'client/components/HOC'
|
||||||
@ -67,7 +67,7 @@ const MessageToConfirmAction = (rows) => (
|
|||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the actions to operate resources on Image table.
|
* Generates the actions to operate resources on Backup table.
|
||||||
*
|
*
|
||||||
* @returns {GlobalAction} - Actions
|
* @returns {GlobalAction} - Actions
|
||||||
*/
|
*/
|
||||||
@ -79,7 +79,7 @@ const Actions = () => {
|
|||||||
|
|
||||||
const resourcesView = getResourceView(RESOURCE_NAMES.BACKUP)?.actions
|
const resourcesView = getResourceView(RESOURCE_NAMES.BACKUP)?.actions
|
||||||
|
|
||||||
const imageActions = useMemo(
|
const backupActions = useMemo(
|
||||||
() =>
|
() =>
|
||||||
createActions({
|
createActions({
|
||||||
filters: resourcesView,
|
filters: resourcesView,
|
||||||
@ -90,22 +90,42 @@ const Actions = () => {
|
|||||||
dataCy: `image-${IMAGE_ACTIONS.RESTORE}`,
|
dataCy: `image-${IMAGE_ACTIONS.RESTORE}`,
|
||||||
label: T.Restore,
|
label: T.Restore,
|
||||||
tooltip: T.Restore,
|
tooltip: T.Restore,
|
||||||
selected: { min: 1 },
|
selected: { max: 1 },
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
dialogProps: {
|
dialogProps: {
|
||||||
title: T.SelectCluster,
|
title: T.RestoreBackup,
|
||||||
dataCy: 'modal-select-cluster',
|
dataCy: 'modal-select-cluster',
|
||||||
},
|
},
|
||||||
form: (rows) => RestoreForm(),
|
form: (row) => {
|
||||||
|
const backup = row?.[0]?.original
|
||||||
|
let increments = backup?.BACKUP_INCREMENTS?.INCREMENT || []
|
||||||
|
increments = Array.isArray(increments)
|
||||||
|
? increments
|
||||||
|
: [increments]
|
||||||
|
increments = increments.map((increment) => ({
|
||||||
|
id: increment.ID,
|
||||||
|
date: increment.DATE,
|
||||||
|
source: increment.SOURCE,
|
||||||
|
}))
|
||||||
|
|
||||||
|
return RestoreForm({
|
||||||
|
stepProps: { increments },
|
||||||
|
initialValues: increments,
|
||||||
|
})
|
||||||
|
},
|
||||||
onSubmit: (rows) => async (formData) => {
|
onSubmit: (rows) => async (formData) => {
|
||||||
const ids = rows?.map?.(({ original }) => original?.ID)
|
const ids = rows?.map?.(({ original }) => original?.ID)
|
||||||
|
let options = `NO_IP="${formData.no_ip}"\nNO_NIC="${formData.no_nic}"\n`
|
||||||
|
if (formData.name) options += `NAME="${formData.name}"\n`
|
||||||
|
if (formData.increment_id !== '')
|
||||||
|
options += `INCREMENT_ID="${formData.increment_id}"\n`
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
ids.map((id) =>
|
ids.map((id) =>
|
||||||
restoreBackup({
|
restoreBackup({
|
||||||
id: id,
|
id: id,
|
||||||
datastore: formData.datastore,
|
datastore: formData.datastore,
|
||||||
options: `NO_IP="${formData.no_ip}"\nNO_NIC="${formData.no_nic}"`,
|
options,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -183,7 +203,7 @@ const Actions = () => {
|
|||||||
[view]
|
[view]
|
||||||
)
|
)
|
||||||
|
|
||||||
return imageActions
|
return backupActions
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Actions
|
export default Actions
|
||||||
|
@ -413,6 +413,8 @@ module.exports = {
|
|||||||
Incremental: 'Incremental',
|
Incremental: 'Incremental',
|
||||||
Mode: 'Mode',
|
Mode: 'Mode',
|
||||||
ResetBackup: 'Reset',
|
ResetBackup: 'Reset',
|
||||||
|
IncrementId: 'Increment ID',
|
||||||
|
RestoreBackup: 'Restore backup',
|
||||||
|
|
||||||
/* sections - templates & instances */
|
/* sections - templates & instances */
|
||||||
Instances: 'Instances',
|
Instances: 'Instances',
|
||||||
|
@ -13,23 +13,23 @@
|
|||||||
* See the License for the specific language governing permissions and *
|
* See the License for the specific language governing permissions and *
|
||||||
* limitations under the License. *
|
* limitations under the License. *
|
||||||
* ------------------------------------------------------------------------- */
|
* ------------------------------------------------------------------------- */
|
||||||
import { ReactElement, useState, memo } from 'react'
|
import { Box, Chip, Stack, Typography } from '@mui/material'
|
||||||
import PropTypes from 'prop-types'
|
import Cancel from 'iconoir-react/dist/Cancel'
|
||||||
import GotoIcon from 'iconoir-react/dist/Pin'
|
import GotoIcon from 'iconoir-react/dist/Pin'
|
||||||
import RefreshDouble from 'iconoir-react/dist/RefreshDouble'
|
import RefreshDouble from 'iconoir-react/dist/RefreshDouble'
|
||||||
import Cancel from 'iconoir-react/dist/Cancel'
|
import PropTypes from 'prop-types'
|
||||||
import { Typography, Box, Stack, Chip } from '@mui/material'
|
import { ReactElement, memo, useState } from 'react'
|
||||||
import { Row } from 'react-table'
|
import { Row } from 'react-table'
|
||||||
|
|
||||||
import { useLazyGetImageQuery } from 'client/features/OneApi/image'
|
import { SubmitButton } from 'client/components/FormControl'
|
||||||
|
import { Tr } from 'client/components/HOC'
|
||||||
|
import MultipleTags from 'client/components/MultipleTags'
|
||||||
|
import SplitPane from 'client/components/SplitPane'
|
||||||
import { BackupsTable } from 'client/components/Tables'
|
import { BackupsTable } from 'client/components/Tables'
|
||||||
import BackupActions from 'client/components/Tables/Backups/actions'
|
import BackupActions from 'client/components/Tables/Backups/actions'
|
||||||
import BackupTabs from 'client/components/Tabs/Backup'
|
import BackupTabs from 'client/components/Tabs/Backup'
|
||||||
import SplitPane from 'client/components/SplitPane'
|
import { Image, T } from 'client/constants'
|
||||||
import MultipleTags from 'client/components/MultipleTags'
|
import { useLazyGetImageQuery } from 'client/features/OneApi/image'
|
||||||
import { SubmitButton } from 'client/components/FormControl'
|
|
||||||
import { Tr } from 'client/components/HOC'
|
|
||||||
import { T, Image } from 'client/constants'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays a list of Backups with a split pane between the list and selected row(s).
|
* Displays a list of Backups with a split pane between the list and selected row(s).
|
||||||
@ -38,7 +38,7 @@ import { T, Image } from 'client/constants'
|
|||||||
*/
|
*/
|
||||||
function Backups() {
|
function Backups() {
|
||||||
const [selectedRows, onSelectedRowsChange] = useState(() => [])
|
const [selectedRows, onSelectedRowsChange] = useState(() => [])
|
||||||
const actions = BackupActions()
|
const actions = BackupActions(selectedRows)
|
||||||
|
|
||||||
const hasSelectedRows = selectedRows?.length > 0
|
const hasSelectedRows = selectedRows?.length > 0
|
||||||
const moreThanOneSelected = selectedRows?.length > 1
|
const moreThanOneSelected = selectedRows?.length > 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user