/* 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 . */ // @flow import React from 'react' import styled from 'styled-components' import configLoader from '../../../utils/Config' import ToggleButtonBar from '../../../components/atoms/ToggleButtonBar' import type { Field } from '../../../types/Field' import { Wrapper, Fields, FieldStyled, Row } from '../default/ContentPlugin' const ToggleButtonBarStyled = styled(ToggleButtonBar)` margin-top: 16px; ` type Props = { connectionInfoSchema: Field[], validation: { valid: boolean, validation: { message: string } }, invalidFields: string[], getFieldValue: (field: ?Field) => any, handleFieldChange: (field: ?Field, value: any) => void, disabled: boolean, cancelButtonText: string, validating: boolean, onRef: (contentPlugin: any) => void, onResizeUpdate: (scrollOfset: number) => void, scrollableRef: (ref: HTMLElement) => void, } type State = { useAdvancedOptions: boolean, } class ContentPlugin extends React.Component { state = { useAdvancedOptions: false, } previouslySelectedChoices: string[] = [] get useCurrentUser(): boolean { return Boolean(this.getFieldValue(this.props.connectionInfoSchema.find(n => n.name === 'openstack_use_current_user'))) } componentDidMount() { this.props.onRef(this) } componentDidUpdate(prevProps: Props, prevState: State) { if (prevState.useAdvancedOptions !== this.state.useAdvancedOptions) { this.props.onResizeUpdate(0) } } componentWillUnmount() { this.props.onRef(undefined) } getApiVersion(): number { return this.props.getFieldValue(this.props.connectionInfoSchema.find(n => n.name === 'identity_api_version')) } getFieldValue(field: ?Field) { let fieldValue = this.props.getFieldValue(field) if (fieldValue) { return fieldValue } let getInputChoiceValue = (fieldBaseName: string): string => { let id = this.props.getFieldValue(this.props.connectionInfoSchema.find(n => n.name === `${fieldBaseName}_id`)) let previouslySelected = this.previouslySelectedChoices.find(f => f === `${fieldBaseName}_id`) if (id || previouslySelected) { if (!previouslySelected) this.previouslySelectedChoices.push(`${fieldBaseName}_id`) return `${fieldBaseName}_id` } return `${fieldBaseName}_name` } if (field && field.name === 'user_domain') { return getInputChoiceValue('user_domain') } if (field && field.name === 'project_domain') { return getInputChoiceValue('project_domain') } return fieldValue } handleAdvancedOptionsToggle(useAdvancedOptions: boolean) { this.setState({ useAdvancedOptions }) } findInvalidFields = () => { let inputChoices = ['user_domain', 'project_domain'] const invalidFields = this.props.connectionInfoSchema.filter(field => { if (this.isFieldRequired(field)) { let value = this.getFieldValue(field) return !value } let inputChoice = inputChoices.find(c => c === field.name) if (inputChoice && this.getApiVersion() > 2) { let selectionValue = this.getFieldValue(this.props.connectionInfoSchema.find(f => f.name === inputChoice)) let itemValue = this.getFieldValue(this.props.connectionInfoSchema.find(f => f.name === selectionValue)) return !itemValue } return false }).map(f => f.name) return invalidFields } filterSimpleAdvanced(): Field[] { let extraAdvancedFields = ['description', 'glance_api_version', 'identity_api_version', 'openstack_use_current_user'] if (this.getApiVersion() > 2) { extraAdvancedFields = extraAdvancedFields.concat(['user_domain', 'project_domain']) } let ignoreFields = ['user_domain_id', 'project_domain_id', 'user_domain_name', 'project_domain_name'] if (!configLoader.config.showOpenstackCurrentUserSwitch) { ignoreFields.push('openstack_use_current_user') } return this.props.connectionInfoSchema.filter(f => !ignoreFields.find(i => i === f.name)).filter(field => { if (this.state.useAdvancedOptions) { return true } return field.required || extraAdvancedFields.find(fieldName => field.name === fieldName) }) } isFieldRequired(field: Field) { return this.useCurrentUser ? field.name === 'name' : field.required } renderSimpleAdvancedToggle() { return ( { this.handleAdvancedOptionsToggle(item.value === 'advanced') }} /> ) } renderFields() { const rows = [] let lastField let fields = this.filterSimpleAdvanced() fields.forEach((field, i) => { let disabled = this.props.disabled || (this.useCurrentUser && field.name !== 'name' && field.name !== 'description' && field.name !== 'openstack_use_current_user') let required = this.isFieldRequired(field) || (this.getApiVersion() > 2 ? field.name === 'user_domain' || field.name === 'project_domain' : false) const currentField = ( fn === field.name) > -1} value={this.getFieldValue(field)} onChange={value => { this.props.handleFieldChange(field, value) }} getFieldValue={fieldName => this.getFieldValue(this.props.connectionInfoSchema.find(n => n.name === fieldName))} onFieldChange={(fieldName, fieldValue) => { this.props.handleFieldChange(this.props.connectionInfoSchema.find(n => n.name === fieldName), fieldValue) }} /> ) if (i % 2 !== 0) { rows.push(( {lastField} {currentField} )) } else if (i === fields.length - 1) { rows.push(( {currentField} )) } lastField = currentField }) return ( { this.props.scrollableRef(ref) }}> {rows} ) } render() { return ( {this.renderSimpleAdvancedToggle()} {this.renderFields()} ) } } export default ContentPlugin