/*
Copyright (C) 2017 Cloudbase Solutions SRL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
import * as React from "react";
import { observer } from "mobx-react";
import styled from "styled-components";
import Button from "@src/components/ui/Button";
import FieldInput from "@src/components/ui/FieldInput";
import ToggleButtonBar from "@src/components/ui/ToggleButtonBar";
import type { Field } from "@src/@types/Field";
import { ThemeProps } from "@src/components/Theme";
import LabelDictionary from "@src/utils/LabelDictionary";
import assessmentImage from "./images/assessment.svg";
const Wrapper = styled.div`
padding: 48px 32px 32px 32px;
display: flex;
flex-direction: column;
align-items: center;
min-height: 0;
`;
const Image = styled.div`
width: 96px;
height: 96px;
background: url("${assessmentImage}") center no-repeat;
`;
const ToggleButtonBarStyled = styled(ToggleButtonBar)`
margin-top: 48px;
`;
const Fields = styled.div`
display: flex;
margin-top: 32px;
flex-direction: column;
overflow: auto;
width: 100%;
min-height: 0;
`;
const FieldStyled = styled(FieldInput)`
${ThemeProps.exactWidth(`${ThemeProps.inputSizes.large.width}px`)}
margin-bottom: 16px;
`;
const Row = styled.div`
display: flex;
flex-shrink: 0;
justify-content: space-between;
`;
const Buttons = styled.div`
display: flex;
justify-content: space-between;
width: 100%;
margin-top: 32px;
`;
const generalFields = [
{
name: "use_replica",
type: "boolean",
},
{
name: "separate_vm",
type: "boolean",
},
];
const replicaFields = [
{
name: "shutdown_instances",
type: "boolean",
},
];
const migrationFields = [
{
name: "skip_os_morphing",
type: "boolean",
},
];
type Props = {
onCancelClick: () => void;
onExecuteClick: (fieldValues: { [prop: string]: any }) => void;
executeButtonDisabled: boolean;
replicaSchema: Field[];
migrationSchema: Field[];
onResizeUpdate?: (scrollableRef: HTMLElement, scrollOffset?: number) => void;
};
type State = {
fieldValues: { [prop: string]: any };
showAdvancedOptions: boolean;
};
@observer
class AssessmentMigrationOptions extends React.Component {
state: State = {
fieldValues: {
separate_vm: true,
use_replica: false,
shutdown_instances: false,
skip_os_morphing: false,
},
showAdvancedOptions: false,
};
// scrollableRef: HTMLElement | undefined | null
getFieldValue(fieldName: string) {
if (this.state.fieldValues[fieldName] != null) {
return this.state.fieldValues[fieldName];
}
return null;
}
getObjectFieldValue(fieldName: string, propName: string) {
return (
this.state.fieldValues[fieldName] &&
this.state.fieldValues[fieldName][propName]
);
}
handleValueChange(fieldName: string, value: any) {
this.setState(prevState => {
const fieldValues = { ...prevState.fieldValues };
if (value != null) {
fieldValues[fieldName] = value;
} else {
delete fieldValues[fieldName];
}
return { fieldValues };
});
}
// UNSAFE_componentDidUpdate(_: Props, prevState: State) {
// if (prevState.showAdvancedOptions !== this.state.showAdvancedOptions
// && this.props.onResizeUpdate && this.scrollableRef) {
// this.props.onResizeUpdate(this.scrollableRef)
// }
// }
handleObjectValueChange(fieldName: string, propName: string, value: any) {
this.setState(prevState => {
const fieldValues = { ...prevState.fieldValues };
if (!fieldValues[fieldName]) {
fieldValues[fieldName] = {};
}
fieldValues[fieldName][propName] = value;
return { fieldValues };
});
}
renderFields() {
let fields: any = generalFields;
const useReplica = this.getFieldValue("use_replica");
const skipFields = [
"location",
"resource_group",
"network_map",
"storage_map",
"vm_size",
"worker_size",
];
// eslint-disable-next-line no-shadow
const cleanup = (cleanupFields: any[]) =>
cleanupFields
.filter((f: { name: string }) => !skipFields.find(n => n === f.name))
.map((f: { type: string; nullableBoolean: boolean }) => {
if (f.type === "boolean") {
// eslint-disable-next-line no-param-reassign
f.nullableBoolean = true;
}
return { ...f };
});
if (useReplica) {
fields = [...fields, ...replicaFields];
if (this.state.showAdvancedOptions) {
fields = [...fields, ...cleanup(this.props.replicaSchema)];
}
} else {
fields = [...fields, ...migrationFields];
if (this.state.showAdvancedOptions) {
fields = [...fields, ...cleanup(this.props.migrationSchema)];
}
}
const sortPriority: any = {
boolean: 1,
string: 2,
object: 3,
};
fields.sort((a: any, b: any) => {
if (sortPriority[a.type] && sortPriority[b.type]) {
return sortPriority[a.type] - sortPriority[b.type];
}
if (sortPriority[a.type]) {
return -1;
}
if (sortPriority[b.type]) {
return 1;
}
return a.name.localeCompare(b.name);
});
const rows: JSX.Element[] = [];
let lastField: JSX.Element;
fields.forEach((field: any, index: number) => {
let additionalProps;
if (field.type === "object" && field.properties) {
additionalProps = {
valueCallback: (callbackField: { name: string }) =>
this.getObjectFieldValue(field.name, callbackField.name),
onChange: (value: any, callbackField: { name: string }) => {
const propName = callbackField.name.substr(
callbackField.name.lastIndexOf("/") + 1
);
this.handleObjectValueChange(field.name, propName, value);
},
properties: field.properties.map((p: any) => ({
...p,
required: false,
})),
};
} else {
const value = this.getFieldValue(field.name);
additionalProps = {
value,
// eslint-disable-next-line no-shadow
onChange: (changeValue: any) => {
this.handleValueChange(field.name, changeValue);
},
type: field.type,
};
}
const currentField = (
);
const pushRow = (field1: React.ReactNode, field2?: React.ReactNode) => {
rows.push(
{field1}
{field2}
);
};
if (index === fields.length - 1 && index % 2 === 0) {
pushRow(currentField);
} else if (index % 2 !== 0) {
pushRow(lastField, currentField);
} else {
lastField = currentField;
}
});
return (
// { this.scrollableRef = ref }}>
{rows}
);
}
render() {
return (
{
this.setState({ showAdvancedOptions: item.value === "advanced" });
}}
/>
{this.renderFields()}
);
}
}
export default AssessmentMigrationOptions;