2017-09-20 12:30:53 +03:00
|
|
|
import React from 'react';
|
2017-10-13 22:56:08 +03:00
|
|
|
import moment from 'moment';
|
2017-09-20 12:30:53 +03:00
|
|
|
import forceArray from 'force-array';
|
2017-10-13 22:56:08 +03:00
|
|
|
import { connect } from 'react-redux';
|
2017-09-20 12:30:53 +03:00
|
|
|
import { compose, graphql } from 'react-apollo';
|
|
|
|
import find from 'lodash.find';
|
2017-10-13 22:56:08 +03:00
|
|
|
import sortBy from 'lodash.sortby';
|
2017-09-20 12:30:53 +03:00
|
|
|
import get from 'lodash.get';
|
|
|
|
|
2017-10-13 22:56:08 +03:00
|
|
|
import { reduxForm, stopSubmit, startSubmit, change } from 'redux-form';
|
|
|
|
|
2017-10-09 16:43:51 +03:00
|
|
|
import {
|
|
|
|
ViewContainer,
|
|
|
|
Message,
|
|
|
|
MessageTitle,
|
|
|
|
MessageDescription
|
|
|
|
} from 'joyent-ui-toolkit';
|
2017-09-20 12:30:53 +03:00
|
|
|
|
|
|
|
import GetSnapshots from '@graphql/list-snapshots.gql';
|
2017-10-13 22:56:08 +03:00
|
|
|
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);
|
2017-09-20 12:30:53 +03:00
|
|
|
|
2017-10-13 22:56:08 +03:00
|
|
|
const Snapshots = ({
|
|
|
|
snapshots = [],
|
|
|
|
selected = [],
|
|
|
|
loading,
|
|
|
|
error,
|
|
|
|
handleAction
|
|
|
|
}) => {
|
|
|
|
const _values = forceArray(snapshots);
|
|
|
|
const _loading = !_values.length && loading;
|
2017-09-20 12:30:53 +03:00
|
|
|
|
2017-10-13 22:56:08 +03:00
|
|
|
const _error = error &&
|
2017-10-31 12:03:44 +02:00
|
|
|
!_loading &&
|
|
|
|
!_values.length && (
|
|
|
|
<Message error>
|
|
|
|
<MessageTitle>Ooops!</MessageTitle>
|
|
|
|
<MessageDescription>
|
|
|
|
An error occurred while loading your instance snapshots
|
|
|
|
</MessageDescription>
|
|
|
|
</Message>
|
|
|
|
);
|
2017-09-20 12:30:53 +03:00
|
|
|
|
|
|
|
return (
|
2017-10-13 22:56:08 +03:00
|
|
|
<ViewContainer main>
|
2017-09-20 12:30:53 +03:00
|
|
|
{_error}
|
2017-10-13 22:56:08 +03:00
|
|
|
<SnapshotsListForm
|
|
|
|
snapshots={_values}
|
|
|
|
loading={_loading}
|
|
|
|
onAction={handleAction}
|
|
|
|
selected={selected}
|
|
|
|
/>
|
2017-09-20 12:30:53 +03:00
|
|
|
</ViewContainer>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default compose(
|
2017-10-13 22:56:08 +03:00
|
|
|
graphql(StartSnapshot, { name: 'start' }),
|
|
|
|
graphql(RemoveSnapshot, { name: 'remove' }),
|
2017-09-20 12:30:53 +03:00
|
|
|
graphql(GetSnapshots, {
|
|
|
|
options: ({ match }) => ({
|
|
|
|
pollInterval: 1000,
|
|
|
|
variables: {
|
|
|
|
name: get(match, 'params.instance')
|
|
|
|
}
|
|
|
|
}),
|
2017-10-13 22:56:08 +03:00
|
|
|
props: ({ data: { loading, error, variables, ...rest } }) => {
|
|
|
|
const { name } = variables;
|
|
|
|
const instance = find(get(rest, 'machines', []), ['name', name]);
|
|
|
|
|
2017-12-22 04:11:50 +02:00
|
|
|
const snapshots = get(
|
|
|
|
instance,
|
|
|
|
'snapshots',
|
|
|
|
[]
|
|
|
|
).map(({ created, updated, ...rest }) => ({
|
|
|
|
...rest,
|
|
|
|
created: moment.utc(created).unix(),
|
|
|
|
updated: moment.utc(updated).unix()
|
|
|
|
}));
|
2017-10-13 22:56:08 +03:00
|
|
|
|
|
|
|
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)
|
|
|
|
);
|
|
|
|
}
|
2017-09-20 12:30:53 +03:00
|
|
|
})
|
2017-10-13 22:56:08 +03:00
|
|
|
)
|
2017-09-20 12:30:53 +03:00
|
|
|
)(Snapshots);
|