2017-09-20 12:30:53 +03:00
|
|
|
import React from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import { compose, graphql } from 'react-apollo';
|
|
|
|
import { connect } from 'react-redux';
|
2017-10-04 20:27:55 +03:00
|
|
|
import { reduxForm, change } from 'redux-form';
|
2017-09-20 12:30:53 +03:00
|
|
|
import forceArray from 'force-array';
|
|
|
|
import get from 'lodash.get';
|
2017-10-04 20:27:55 +03:00
|
|
|
import sortBy from 'lodash.sortby';
|
2017-09-20 12:30:53 +03:00
|
|
|
import find from 'lodash.find';
|
|
|
|
|
2017-10-09 16:43:51 +03:00
|
|
|
import {
|
|
|
|
ViewContainer,
|
|
|
|
Title,
|
|
|
|
Message,
|
|
|
|
MessageDescription,
|
|
|
|
MessageTitle
|
|
|
|
} from 'joyent-ui-toolkit';
|
2017-09-20 12:30:53 +03:00
|
|
|
|
2017-10-04 20:27:55 +03:00
|
|
|
import ListInstances from '@graphql/list-instances.gql';
|
|
|
|
import StopInstance from '@graphql/stop-instance.gql';
|
|
|
|
import StartInstance from '@graphql/start-instance.gql';
|
|
|
|
import RebootInstance from '@graphql/reboot-instance.gql';
|
|
|
|
import ResizeInstance from '@graphql/resize-instance.gql';
|
|
|
|
import EnableInstanceFw from '@graphql/enable-instance-fw.gql';
|
|
|
|
import DisableInstanceFw from '@graphql/disable-instance-fw.gql';
|
|
|
|
import CreateSnapshot from '@graphql/create-snapshot.gql';
|
|
|
|
import StartSnapshot from '@graphql/start-from-snapshot.gql';
|
|
|
|
|
2017-09-20 12:30:53 +03:00
|
|
|
import { List as InstanceList } from '@components/instances';
|
|
|
|
import GenIndex from '@state/gen-index';
|
|
|
|
|
|
|
|
const InstanceListForm = reduxForm({
|
2017-10-04 20:27:55 +03:00
|
|
|
form: `instance-list`,
|
|
|
|
initialValues: {
|
|
|
|
sort: 'name'
|
|
|
|
}
|
2017-09-20 12:30:53 +03:00
|
|
|
})(InstanceList);
|
|
|
|
|
2017-10-04 20:27:55 +03:00
|
|
|
const List = ({
|
|
|
|
selected = [],
|
|
|
|
instances = [],
|
|
|
|
loading = false,
|
|
|
|
error,
|
|
|
|
onAction
|
|
|
|
}) => {
|
2017-09-20 12:30:53 +03:00
|
|
|
const _title = <Title>Instances</Title>;
|
|
|
|
const _instances = forceArray(instances);
|
2017-09-27 17:44:57 +03:00
|
|
|
const _loading = !instances.length && loading;
|
2017-09-20 12:30:53 +03:00
|
|
|
|
2017-10-04 20:27:55 +03:00
|
|
|
const _error =
|
|
|
|
error && !_instances.length && !_loading ? (
|
2017-10-09 16:43:51 +03:00
|
|
|
<Message error>
|
|
|
|
<MessageTitle>Ooops!</MessageTitle>
|
|
|
|
<MessageDescription>
|
|
|
|
An error occurred while loading your instances
|
|
|
|
</MessageDescription>
|
|
|
|
</Message>
|
2017-10-04 20:27:55 +03:00
|
|
|
) : null;
|
|
|
|
|
|
|
|
const handleAction = name => onAction({ name, ids: selected });
|
2017-09-20 12:30:53 +03:00
|
|
|
|
|
|
|
return (
|
2017-09-27 17:23:49 +03:00
|
|
|
<ViewContainer main>
|
2017-09-20 12:30:53 +03:00
|
|
|
{_title}
|
|
|
|
{!_loading && _error}
|
2017-10-04 20:27:55 +03:00
|
|
|
<InstanceListForm
|
|
|
|
instances={_instances}
|
|
|
|
loading={loading}
|
|
|
|
onAction={handleAction}
|
|
|
|
/>
|
2017-09-20 12:30:53 +03:00
|
|
|
</ViewContainer>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
List.propTypes = {
|
|
|
|
loading: PropTypes.bool,
|
|
|
|
instances: PropTypes.arrayOf(
|
|
|
|
PropTypes.shape({
|
|
|
|
id: PropTypes.string,
|
|
|
|
name: PropTypes.string
|
|
|
|
})
|
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
export default compose(
|
2017-10-04 20:27:55 +03:00
|
|
|
graphql(StopInstance, { name: 'stop' }),
|
|
|
|
graphql(StartInstance, { name: 'start' }),
|
|
|
|
graphql(RebootInstance, { name: 'reboot' }),
|
|
|
|
graphql(ResizeInstance, { name: 'resize' }),
|
|
|
|
graphql(EnableInstanceFw, { name: 'enableFw' }),
|
|
|
|
graphql(DisableInstanceFw, { name: 'disableFw' }),
|
|
|
|
graphql(CreateSnapshot, { name: 'createSnapshot' }),
|
|
|
|
graphql(StartSnapshot, { name: 'startSnapshot' }),
|
|
|
|
graphql(ListInstances, {
|
2017-09-20 12:30:53 +03:00
|
|
|
options: () => ({
|
|
|
|
pollInterval: 1000
|
|
|
|
}),
|
|
|
|
props: ({ ownProps, data: { machines, loading, error } }) => {
|
|
|
|
const _instances = forceArray(machines);
|
|
|
|
|
|
|
|
return {
|
|
|
|
instances: _instances,
|
|
|
|
loading,
|
|
|
|
error,
|
|
|
|
index: GenIndex(_instances)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}),
|
2017-10-04 20:27:55 +03:00
|
|
|
connect(
|
|
|
|
(state, ownProps) => {
|
|
|
|
const { index, instances = [], ...rest } = ownProps;
|
|
|
|
|
|
|
|
const form = get(state, 'form.instance-list.values', {});
|
|
|
|
const filter = get(form, 'filter');
|
|
|
|
const sort = get(form, 'sort');
|
|
|
|
|
|
|
|
const values = filter
|
|
|
|
? index.search(filter).map(({ ref }) => find(instances, ['id', ref]))
|
|
|
|
: instances;
|
|
|
|
|
|
|
|
const selected = Object.keys(form)
|
|
|
|
.map(name => find(values, ['name', name]))
|
|
|
|
.filter(Boolean)
|
|
|
|
.map(({ id }) => id);
|
|
|
|
|
|
|
|
return {
|
|
|
|
...rest,
|
|
|
|
instances: sortBy(values, value => get(value, sort)),
|
|
|
|
selected
|
|
|
|
};
|
|
|
|
},
|
|
|
|
(dispatch, { instances, ...ownProps }) => ({
|
|
|
|
onAction: ({ name, ids = [] }) => {
|
|
|
|
const types = {
|
|
|
|
stop: () =>
|
|
|
|
Promise.all(ids.map(id => ownProps.stop({ variables: { id } }))),
|
|
|
|
start: () =>
|
|
|
|
Promise.all(ids.map(id => ownProps.start({ variables: { id } }))),
|
|
|
|
reboot: () =>
|
|
|
|
Promise.all(ids.map(id => ownProps.reboot({ variables: { id } }))),
|
|
|
|
resize: () => null,
|
|
|
|
'enable-fw': () => null,
|
|
|
|
'disable-fw': () => null,
|
|
|
|
'create-snap': () => null,
|
|
|
|
'start-snap': () => null
|
|
|
|
};
|
|
|
|
|
|
|
|
const clearSelected = () => dispatch(ids.map(id => {
|
|
|
|
const form = 'instance-list';
|
|
|
|
const field = get(find(instances, ['id', id]), 'name');
|
|
|
|
const value = false;
|
|
|
|
|
|
|
|
if (!field) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return change(form, field, value);
|
|
|
|
}));
|
|
|
|
|
|
|
|
const fn = types[name];
|
|
|
|
return fn && fn().then(clearSelected);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
)
|
2017-09-20 12:30:53 +03:00
|
|
|
)(List);
|