Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

Add routed tabs to the Settings page to prepare for Conversion Hosts settings #851

Merged
merged 6 commits into from
Jan 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/javascript/react/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ export const links = [
component: Settings,
menu_item_id: 'menu_item_settings'
},
{
path: 'settings/conversion_hosts',
component: Settings,
menu_item_id: 'menu_item_settings'
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just making sure... we don't need an entry here for settings/general because by default, entering the settings route opens the general tab?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michaelkro That's correct. There's no /settings/general route, /settings and /settings/conversion_hosts are the routes to each tab.

{
path: 'plan/:id',
component: PlanContainer,
Expand Down
113 changes: 30 additions & 83 deletions app/javascript/react/screens/App/Settings/Settings.js
Original file line number Diff line number Diff line change
@@ -1,100 +1,47 @@
import React from 'react';
import PropTypes from 'prop-types';
import { reduxForm, Field } from 'redux-form';
import { Breadcrumb, Form, Button, Spinner } from 'patternfly-react';
import { Breadcrumb, Tabs, Tab } from 'patternfly-react';
import Toolbar from '../../../config/Toolbar';
import NumberInput from '../common/forms/NumberInput';
import GeneralSettings from './screens/GeneralSettings';
import ConversionHostsSettings from './screens/ConversionHostsSettings';

export class Settings extends React.Component {
componentDidMount() {
const { fetchServersAction, fetchServersUrl, fetchSettingsAction, fetchSettingsUrl } = this.props;
fetchServersAction(fetchServersUrl);
fetchSettingsAction(fetchSettingsUrl);
}
const Settings = props => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function Settings has 62 lines of code (exceeds 25 allowed). Consider refactoring.

const { match, redirectTo } = props;

onApplyClick = () => {
const { patchSettingsAction, servers, settingsForm } = this.props;
patchSettingsAction(servers, settingsForm.values);
};
// TODO remove this when we are ready to release ConversionHostsSettings
const hideConversionHostSettings = true;

render() {
const { isFetchingServers, isFetchingSettings, isSavingSettings, savedSettings, settingsForm } = this.props;

const toolbarContent = (
return (
<React.Fragment>
<Toolbar>
<Breadcrumb.Item href="/dashboard/maintab?tab=compute">{__('Compute')}</Breadcrumb.Item>
<Breadcrumb.Item href="#/plans">{__('Migration')}</Breadcrumb.Item>
<Breadcrumb.Item active>{__('Migration Settings')}</Breadcrumb.Item>
</Toolbar>
);

const hasUnsavedChanges =
settingsForm &&
settingsForm.values &&
Object.keys(savedSettings).some(key => savedSettings[key] !== settingsForm.values[key]);

const settingsContent = (
<Spinner loading={isFetchingServers || isFetchingSettings} style={{ marginTop: 15 }}>
<div className="migration-settings">
{hideConversionHostSettings ? (
<React.Fragment>
<h2>{__('Concurrent Migrations')}</h2>
<Form style={{ padding: '0 20px' }}>
<Form.FormGroup>
<Form.ControlLabel>{__('Maximum concurrent migrations per conversion host')}</Form.ControlLabel>
<div style={{ width: 100 }}>
<Field
id="max_concurrent_tasks_per_host"
name="max_concurrent_tasks_per_host"
component={NumberInput}
normalize={NumberInput.normalizeStringToInt}
min={1}
/>
</div>
</Form.FormGroup>
<Form.FormGroup>
<Button bsStyle="primary" onClick={this.onApplyClick} disabled={!hasUnsavedChanges || isSavingSettings}>
{__('Apply')}
</Button>
<br />
{isSavingSettings && (
<div style={{ paddingTop: 10 }}>
<Spinner loading size="xs" inline />
{__(' Applying...')}
</div>
)}
</Form.FormGroup>
</Form>
<GeneralSettings />
</React.Fragment>
) : (
<div style={{ marginTop: 10 }}>
<Tabs id="settings-tabs" activeKey={match.path} onSelect={key => redirectTo(key)}>
<Tab eventKey="/settings" title={__('Concurrent Migrations')}>
<GeneralSettings />
</Tab>
<Tab eventKey="/settings/conversion_hosts" title={__('Conversion Hosts')}>
<ConversionHostsSettings />
</Tab>
</Tabs>
</div>
</Spinner>
);

return (
<React.Fragment>
{toolbarContent}
{settingsContent}
</React.Fragment>
);
}
}

Settings.propTypes = {
fetchServersAction: PropTypes.func,
fetchSettingsAction: PropTypes.func,
patchSettingsAction: PropTypes.func,
isFetchingServers: PropTypes.bool,
isFetchingSettings: PropTypes.bool,
isSavingSettings: PropTypes.bool,
servers: PropTypes.array,
savedSettings: PropTypes.object,
settingsForm: PropTypes.object,
fetchServersUrl: PropTypes.string,
fetchSettingsUrl: PropTypes.string
)}
</React.Fragment>
);
};

Settings.defaultProps = {
fetchServersUrl: '/api/servers',
fetchSettingsUrl: '/api/settings'
Settings.propTypes = {
match: PropTypes.object,
redirectTo: PropTypes.func
};

export default reduxForm({
form: 'settings'
})(Settings);
export default Settings;

This file was deleted.

16 changes: 3 additions & 13 deletions app/javascript/react/screens/App/Settings/index.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
import { connect } from 'react-redux';
import Settings from './Settings';

import * as SettingsActions from './SettingsActions';
import * as NotificationActions from '../common/NotificationList/NotificationListActions';

import reducer from './SettingsReducer';
import * as RouterActions from '../../../../redux/actions/routerActions';

export const reducers = { settings: reducer };

const mapStateToProps = ({ settings, form }, ownProps) => ({
...settings,
...ownProps.data,
settingsForm: form.settings,
initialValues: settings.savedSettings,
enableReinitialize: true,
destroyOnUnmount: false
});
const mapStateToProps = () => ({});

const mergeProps = (stateProps, dispatchProps, ownProps) => Object.assign(stateProps, ownProps.data, dispatchProps);

export default connect(
mapStateToProps,
Object.assign(SettingsActions, NotificationActions),
RouterActions,
mergeProps
)(Settings);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from 'react';

const ConversionHostsSettings = () => <h2>Hello World</h2>;

export default ConversionHostsSettings;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import ConversionHostsSettings from './ConversionHostsSettings';

export default ConversionHostsSettings;
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React from 'react';
import PropTypes from 'prop-types';
import { reduxForm, Field } from 'redux-form';
import { Form, Button, Spinner } from 'patternfly-react';
import NumberInput from '../../../common/forms/NumberInput';

export class GeneralSettings extends React.Component {
componentDidMount() {
const { fetchServersAction, fetchServersUrl, fetchSettingsAction, fetchSettingsUrl } = this.props;
fetchServersAction(fetchServersUrl);
fetchSettingsAction(fetchSettingsUrl);
}

onApplyClick = () => {
const { patchSettingsAction, servers, settingsForm } = this.props;
patchSettingsAction(servers, settingsForm.values);
};

render() {
const { isFetchingServers, isFetchingSettings, isSavingSettings, savedSettings, settingsForm } = this.props;

const hasUnsavedChanges =
settingsForm &&
settingsForm.values &&
Object.keys(savedSettings).some(key => savedSettings[key] !== settingsForm.values[key]);

return (
<Spinner loading={isFetchingServers || isFetchingSettings} style={{ marginTop: 15 }}>
<div className="migration-settings">
<Form style={{ padding: '0 20px' }}>
<Form.FormGroup>
<Form.ControlLabel>{__('Maximum concurrent migrations per conversion host')}</Form.ControlLabel>
<div style={{ width: 100 }}>
<Field
id="max_concurrent_tasks_per_host"
name="max_concurrent_tasks_per_host"
component={NumberInput}
normalize={NumberInput.normalizeStringToInt}
min={1}
/>
</div>
</Form.FormGroup>
<Form.FormGroup>
<Button bsStyle="primary" onClick={this.onApplyClick} disabled={!hasUnsavedChanges || isSavingSettings}>
{__('Apply')}
</Button>
<br />
{isSavingSettings && (
<div style={{ paddingTop: 10 }}>
<Spinner loading size="xs" inline />
{__(' Applying...')}
</div>
)}
</Form.FormGroup>
</Form>
</div>
</Spinner>
);
}
}

GeneralSettings.propTypes = {
fetchServersAction: PropTypes.func,
fetchSettingsAction: PropTypes.func,
patchSettingsAction: PropTypes.func,
isFetchingServers: PropTypes.bool,
isFetchingSettings: PropTypes.bool,
isSavingSettings: PropTypes.bool,
servers: PropTypes.array,
savedSettings: PropTypes.object,
settingsForm: PropTypes.object,
fetchServersUrl: PropTypes.string,
fetchSettingsUrl: PropTypes.string
};

GeneralSettings.defaultProps = {
fetchServersUrl: '/api/servers',
fetchSettingsUrl: '/api/settings'
};

export default reduxForm({
form: 'settings'
})(GeneralSettings);
Loading