joyent-portal/packages/my-joy-beta/src/containers/instances/snapshots.js

183 lines
4.7 KiB
JavaScript

import React from 'react';
import moment from 'moment';
import forceArray from 'force-array';
import { connect } from 'react-redux';
import { compose, graphql } from 'react-apollo';
import find from 'lodash.find';
import sortBy from 'lodash.sortby';
import get from 'lodash.get';
import { reduxForm, stopSubmit, startSubmit, change } from 'redux-form';
import {
ViewContainer,
Title,
Message,
MessageTitle,
MessageDescription
} from 'joyent-ui-toolkit';
import GetSnapshots from '@graphql/list-snapshots.gql';
import StartSnapshot from '@graphql/start-from-snapshot.gql';
import RemoveSnapshot from '@graphql/remove-snapshot.gql';
import { Snapshots as SnapshotsList } from '@components/instances';
import GenIndex from '@state/gen-index';
const SnapshotsListForm = reduxForm({
form: `snapshots-list`,
initialValues: {
sort: 'name'
}
})(SnapshotsList);
const Snapshots = ({
snapshots = [],
selected = [],
loading,
error,
handleAction
}) => {
const _title = <Title>Snapshots</Title>;
const _values = forceArray(snapshots);
const _loading = !_values.length && loading;
const _error = error &&
!_loading &&
!_values.length && (
<Message error>
<MessageTitle>Ooops!</MessageTitle>
<MessageDescription>
An error occurred while loading your instance snapshots
</MessageDescription>
</Message>
);
return (
<ViewContainer main>
{_title}
{_error}
<SnapshotsListForm
snapshots={_values}
loading={_loading}
onAction={handleAction}
selected={selected}
/>
</ViewContainer>
);
};
export default compose(
graphql(StartSnapshot, { name: 'start' }),
graphql(RemoveSnapshot, { name: 'remove' }),
graphql(GetSnapshots, {
options: ({ match }) => ({
pollInterval: 1000,
variables: {
name: get(match, 'params.instance')
}
}),
props: ({ data: { loading, error, variables, ...rest } }) => {
const { name } = variables;
const instance = find(get(rest, 'machines', []), ['name', name]);
const snapshots = get(instance, 'snapshots', []).map(
({ created, updated, ...rest }) => ({
...rest,
created: moment.utc(created).unix(),
updated: moment.utc(updated).unix()
})
);
const index = GenIndex(
snapshots.map(({ name, ...rest }) => ({ ...rest, id: name }))
);
return {
index,
snapshots,
instance,
loading,
error
};
}
}),
connect(
(state, { index, snapshots = [], ...rest }) => {
const form = get(state, 'form.snapshots-list.values', {});
const filter = get(form, 'filter');
const sort = get(form, 'sort');
const values = filter
? index.search(filter).map(({ ref }) => find(snapshots, ['name', ref]))
: snapshots;
const selected = Object.keys(form)
.filter(key => Boolean(form[key]))
.map(name => find(values, ['name', name]))
.filter(Boolean)
.map(({ name }) => find(snapshots, ['name', name]))
.filter(Boolean);
return {
...rest,
snapshots: sortBy(values, value => get(value, sort)),
selected
};
},
(dispatch, { create, start, remove, instance, history, match }) => ({
handleAction: ({ name, items = [] }) => {
const form = 'snapshots-list';
const types = {
start: () =>
Promise.resolve(dispatch(startSubmit(form))).then(() =>
Promise.all(
items.map(({ name }) =>
start({ variables: { id: instance.id, snapshot: name } })
)
)
),
delete: () =>
Promise.resolve(dispatch(startSubmit(form))).then(() =>
Promise.all(
items.map(({ name }) =>
remove({ variables: { id: instance.id, snapshot: name } })
)
)
),
create: () =>
Promise.resolve(
history.push(`/instances/${instance.name}/snapshots/~create`)
)
};
const handleError = error => {
dispatch(
stopSubmit(form, {
_error: error.graphQLErrors
.map(({ message }) => message)
.join('\n')
})
);
};
const handleSuccess = () => {
dispatch(
items
.map(({ name: field }) => change(form, field, false))
.concat([stopSubmit(form)])
);
};
return (
types[name] &&
types[name]()
.then(handleSuccess)
.catch(handleError)
);
}
})
)
)(Snapshots);