2017-09-20 12:30:53 +03:00
|
|
|
import React from 'react';
|
2017-11-23 14:18:38 +02:00
|
|
|
import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
|
|
|
|
import Value from 'react-redux-values';
|
|
|
|
import remcalc from 'remcalc';
|
2017-10-31 12:29:15 +02:00
|
|
|
import titleCase from 'title-case';
|
2017-09-20 12:30:53 +03:00
|
|
|
|
2017-09-27 17:44:57 +03:00
|
|
|
import {
|
2017-11-23 14:18:38 +02:00
|
|
|
Row,
|
|
|
|
Col,
|
|
|
|
Anchor,
|
2017-09-27 17:44:57 +03:00
|
|
|
FormGroup,
|
|
|
|
Input,
|
|
|
|
FormLabel,
|
2017-11-23 14:18:38 +02:00
|
|
|
Checkbox,
|
2017-10-13 22:51:18 +03:00
|
|
|
Button,
|
2017-10-31 12:29:15 +02:00
|
|
|
Table,
|
|
|
|
TableThead,
|
|
|
|
TableTr,
|
|
|
|
TableTh,
|
|
|
|
TableTd,
|
2017-11-23 14:18:38 +02:00
|
|
|
TableTbody,
|
|
|
|
Footer,
|
|
|
|
StatusLoader,
|
|
|
|
Message,
|
|
|
|
MessageTitle,
|
|
|
|
MessageDescription,
|
|
|
|
Popover,
|
2017-10-31 12:29:15 +02:00
|
|
|
PopoverContainer,
|
|
|
|
PopoverTarget,
|
|
|
|
PopoverItem,
|
|
|
|
PopoverDivider,
|
2017-11-23 14:18:38 +02:00
|
|
|
QueryBreakpoints,
|
|
|
|
DotIcon,
|
|
|
|
StartIcon,
|
|
|
|
StopIcon,
|
|
|
|
ResetIcon,
|
|
|
|
DeleteIcon,
|
|
|
|
ActionsIcon
|
2017-09-27 17:44:57 +03:00
|
|
|
} from 'joyent-ui-toolkit';
|
|
|
|
|
2017-11-02 15:33:43 +02:00
|
|
|
const { SmallOnly, Medium } = QueryBreakpoints;
|
2017-09-20 12:30:53 +03:00
|
|
|
|
2017-10-31 12:29:15 +02:00
|
|
|
const stateColor = {
|
|
|
|
PROVISIONING: 'primary',
|
|
|
|
RUNNING: 'green',
|
|
|
|
STOPPING: 'grey',
|
|
|
|
STOPPED: 'grey',
|
|
|
|
DELETED: 'secondaryActive',
|
|
|
|
FAILED: 'red'
|
|
|
|
};
|
|
|
|
|
2017-11-23 14:18:38 +02:00
|
|
|
export const MenuForm = ({ handleSubmit, searchable }) => (
|
|
|
|
<form onSubmit={handleSubmit}>
|
|
|
|
<Row>
|
|
|
|
<Col xs={7} sm={5}>
|
|
|
|
<FormGroup name="filter" fluid reduxForm>
|
|
|
|
<FormLabel>Filter instances</FormLabel>
|
|
|
|
<Input
|
|
|
|
placeholder="Search for name, state, tags, etc..."
|
|
|
|
disabled={!searchable}
|
|
|
|
fluid
|
|
|
|
/>
|
|
|
|
</FormGroup>
|
|
|
|
</Col>
|
|
|
|
<Col xs={5} sm={7}>
|
|
|
|
<FormGroup right>
|
|
|
|
<FormLabel>⁣</FormLabel>
|
|
|
|
<Button type="submit" small icon fluid>
|
|
|
|
Create Instance
|
|
|
|
</Button>
|
|
|
|
</FormGroup>
|
|
|
|
</Col>
|
|
|
|
</Row>
|
|
|
|
</form>
|
|
|
|
);
|
|
|
|
|
|
|
|
export const Actions = ({
|
|
|
|
submitting = false,
|
|
|
|
allowedActions = {},
|
|
|
|
onStart = () => null,
|
|
|
|
onStop = () => null,
|
|
|
|
onReboot = () => null,
|
|
|
|
onDelete = () => null
|
|
|
|
}) => (
|
|
|
|
<Footer fixed bottom>
|
|
|
|
<Row between="xs" middle="xs">
|
|
|
|
<Col xs={7}>
|
|
|
|
<Value name="instance-list-starting">
|
|
|
|
{({ value: starting }) => [
|
|
|
|
<SmallOnly key="small-only">
|
|
|
|
<Button
|
|
|
|
type="button"
|
|
|
|
onClick={onStart}
|
|
|
|
disabled={submitting || !allowedActions.start}
|
|
|
|
loading={submitting && starting}
|
|
|
|
secondary
|
|
|
|
small
|
|
|
|
icon
|
|
|
|
rect
|
|
|
|
>
|
|
|
|
<StartIcon disabled={submitting || !allowedActions.start} />
|
|
|
|
</Button>
|
|
|
|
</SmallOnly>,
|
|
|
|
<Medium key="medium">
|
|
|
|
<Button
|
|
|
|
type="button"
|
|
|
|
onClick={onStart}
|
|
|
|
disabled={submitting || !allowedActions.start}
|
|
|
|
loading={submitting && starting}
|
|
|
|
secondary
|
|
|
|
icon
|
|
|
|
rect
|
|
|
|
>
|
|
|
|
<StartIcon disabled={submitting || !allowedActions.start} />
|
|
|
|
<span>Start</span>
|
|
|
|
</Button>
|
|
|
|
</Medium>
|
|
|
|
]}
|
|
|
|
</Value>
|
|
|
|
<Value name="instance-list-stoping">
|
|
|
|
{({ value: stoping }) => [
|
|
|
|
<SmallOnly key="small-only">
|
|
|
|
<Button
|
|
|
|
type="button"
|
|
|
|
onClick={onStop}
|
|
|
|
disabled={submitting || !allowedActions.stop}
|
|
|
|
loading={submitting && stoping}
|
|
|
|
secondary
|
|
|
|
small
|
|
|
|
icon
|
|
|
|
rect
|
|
|
|
>
|
|
|
|
<StopIcon disabled={submitting || !allowedActions.stop} />
|
|
|
|
</Button>
|
|
|
|
</SmallOnly>,
|
|
|
|
<Medium key="medium">
|
|
|
|
<Button
|
|
|
|
type="button"
|
|
|
|
onClick={onStop}
|
|
|
|
disabled={submitting || !allowedActions.stop}
|
|
|
|
loading={submitting && stoping}
|
|
|
|
secondary
|
|
|
|
icon
|
|
|
|
rect
|
|
|
|
>
|
|
|
|
<StopIcon disabled={submitting || !allowedActions.stop} />
|
|
|
|
<span>Stop</span>
|
|
|
|
</Button>
|
|
|
|
</Medium>
|
|
|
|
]}
|
|
|
|
</Value>
|
|
|
|
<Value name="instance-list-restarting">
|
|
|
|
{({ value: restarting }) => [
|
|
|
|
<SmallOnly key="small-only">
|
|
|
|
<Button
|
|
|
|
type="button"
|
|
|
|
onClick={onReboot}
|
|
|
|
disabled={submitting || !allowedActions.reboot}
|
|
|
|
loading={submitting && restarting}
|
|
|
|
secondary
|
|
|
|
small
|
|
|
|
icon
|
|
|
|
rect
|
|
|
|
>
|
|
|
|
<ResetIcon disabled={submitting || !allowedActions.reboot} />
|
|
|
|
</Button>
|
|
|
|
</SmallOnly>,
|
|
|
|
<Medium key="medium">
|
|
|
|
<Button
|
|
|
|
type="button"
|
|
|
|
onClick={onReboot}
|
|
|
|
disabled={submitting || !allowedActions.reboot}
|
|
|
|
loading={submitting && restarting}
|
|
|
|
secondary
|
|
|
|
icon
|
|
|
|
rect
|
|
|
|
>
|
|
|
|
<ResetIcon disabled={submitting || !allowedActions.reboot} />
|
|
|
|
<span>Reboot</span>
|
|
|
|
</Button>
|
|
|
|
</Medium>
|
|
|
|
]}
|
|
|
|
</Value>
|
|
|
|
</Col>
|
|
|
|
<Col xs={5}>
|
|
|
|
<Value name="instance-list-deleting">
|
|
|
|
{({ value: deleting }) => [
|
|
|
|
<SmallOnly key="small-only">
|
|
|
|
<Button
|
|
|
|
type="button"
|
|
|
|
onClick={onDelete}
|
|
|
|
disabled={submitting}
|
|
|
|
loading={submitting && deleting}
|
|
|
|
secondary
|
|
|
|
right
|
|
|
|
small
|
|
|
|
icon
|
|
|
|
rect
|
|
|
|
>
|
|
|
|
<DeleteIcon disabled={submitting} />
|
|
|
|
</Button>
|
|
|
|
</SmallOnly>,
|
|
|
|
<Medium key="medium">
|
|
|
|
<Button
|
|
|
|
type="button"
|
|
|
|
onClick={onDelete}
|
|
|
|
disabled={submitting}
|
|
|
|
loading={submitting && deleting}
|
|
|
|
secondary
|
|
|
|
right
|
|
|
|
icon
|
|
|
|
rect
|
|
|
|
>
|
|
|
|
<DeleteIcon disabled={submitting} />
|
|
|
|
<span>Delete</span>
|
|
|
|
</Button>
|
|
|
|
</Medium>
|
|
|
|
]}
|
|
|
|
</Value>
|
|
|
|
</Col>
|
|
|
|
</Row>
|
|
|
|
</Footer>
|
|
|
|
);
|
|
|
|
|
|
|
|
export const Item = ({
|
|
|
|
id = '',
|
2017-10-31 12:29:15 +02:00
|
|
|
name,
|
|
|
|
state,
|
2017-11-23 14:18:38 +02:00
|
|
|
created,
|
|
|
|
allowedActions = {},
|
|
|
|
submitting,
|
2017-10-31 12:29:15 +02:00
|
|
|
onStart,
|
2017-11-23 14:18:38 +02:00
|
|
|
onStop,
|
2017-10-31 12:29:15 +02:00
|
|
|
onReboot,
|
2017-11-23 14:18:38 +02:00
|
|
|
onDelete
|
2017-10-31 12:29:15 +02:00
|
|
|
}) => (
|
|
|
|
<TableTr>
|
2017-11-23 14:18:38 +02:00
|
|
|
<TableTd padding="0" paddingLeft={remcalc(12)} middle left>
|
|
|
|
<FormGroup name={id} paddingTop={remcalc(4)} reduxForm>
|
2017-10-31 12:29:15 +02:00
|
|
|
<Checkbox />
|
|
|
|
</FormGroup>
|
|
|
|
</TableTd>
|
2017-11-23 14:18:38 +02:00
|
|
|
<TableTd middle left>
|
2017-10-31 12:29:15 +02:00
|
|
|
<Anchor to={`/instances/${name}`}>{name}</Anchor>
|
|
|
|
</TableTd>
|
2017-11-23 14:18:38 +02:00
|
|
|
<TableTd middle left>
|
|
|
|
<Value name={`${id}-mutating`}>
|
|
|
|
{({ value: mutating }) =>
|
|
|
|
mutating ? (
|
|
|
|
<StatusLoader small />
|
|
|
|
) : (
|
|
|
|
<span>
|
|
|
|
<DotIcon
|
|
|
|
width={remcalc(11)}
|
|
|
|
height={remcalc(11)}
|
|
|
|
borderRadius={remcalc(11)}
|
|
|
|
color={stateColor[state]}
|
|
|
|
/>{' '}
|
|
|
|
{titleCase(state)}
|
|
|
|
</span>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
</Value>
|
|
|
|
</TableTd>
|
2017-12-04 20:24:24 +02:00
|
|
|
<TableTd xs="0" sm="160" middle left>
|
2017-11-23 14:18:38 +02:00
|
|
|
{distanceInWordsToNow(created)}
|
|
|
|
</TableTd>
|
2017-12-06 12:34:15 +02:00
|
|
|
<TableTd xs="0" sm="130" middle left>
|
2017-11-23 14:18:38 +02:00
|
|
|
<code>{id.substring(0, 7)}</code>
|
2017-10-31 12:29:15 +02:00
|
|
|
</TableTd>
|
2017-11-23 14:18:38 +02:00
|
|
|
<PopoverContainer clickable>
|
2017-12-04 20:24:24 +02:00
|
|
|
<TableTd padding="0" hasBorder="left">
|
2017-11-23 14:18:38 +02:00
|
|
|
<PopoverTarget box>
|
2017-11-23 14:18:38 +02:00
|
|
|
<ActionsIcon />
|
2017-10-31 12:29:15 +02:00
|
|
|
</PopoverTarget>
|
2017-11-23 14:18:38 +02:00
|
|
|
<Popover placement="right">
|
|
|
|
<PopoverItem
|
|
|
|
disabled={!allowedActions.start}
|
|
|
|
onClick={() => onStart({ id })}
|
|
|
|
>
|
|
|
|
Start
|
|
|
|
</PopoverItem>
|
|
|
|
<PopoverItem
|
|
|
|
disabled={!allowedActions.stop}
|
|
|
|
onClick={() => onStop({ id })}
|
|
|
|
>
|
|
|
|
Stop
|
|
|
|
</PopoverItem>
|
|
|
|
<PopoverItem onClick={() => onReboot({ id })}>Reboot</PopoverItem>
|
2017-10-31 12:29:15 +02:00
|
|
|
<PopoverDivider />
|
2017-11-23 14:18:38 +02:00
|
|
|
<PopoverItem onClick={() => onDelete({ id })}>Delete</PopoverItem>
|
2017-10-31 12:29:15 +02:00
|
|
|
</Popover>
|
2017-11-23 14:18:38 +02:00
|
|
|
</TableTd>
|
|
|
|
</PopoverContainer>
|
2017-10-31 12:29:15 +02:00
|
|
|
</TableTr>
|
|
|
|
);
|
2017-10-13 22:51:18 +03:00
|
|
|
|
2017-09-27 17:44:57 +03:00
|
|
|
export default ({
|
2017-11-23 14:18:38 +02:00
|
|
|
items = [],
|
|
|
|
allowedActions = {},
|
|
|
|
sortBy = 'name',
|
|
|
|
sortOrder = 'desc',
|
|
|
|
error = null,
|
2017-10-13 22:51:18 +03:00
|
|
|
submitting = false,
|
2017-11-23 14:18:38 +02:00
|
|
|
actionable = false,
|
|
|
|
allSelected = false,
|
|
|
|
toggleSelectAll = () => null,
|
|
|
|
onStart = () => null,
|
|
|
|
onStop = () => null,
|
|
|
|
onReboot = () => null,
|
|
|
|
onDelete = () => null,
|
|
|
|
onSortBy = () => null
|
|
|
|
}) => (
|
|
|
|
<form>
|
|
|
|
{error ? (
|
2017-10-31 12:03:44 +02:00
|
|
|
<Message error>
|
|
|
|
<MessageTitle>Ooops!</MessageTitle>
|
|
|
|
<MessageDescription>{error}</MessageDescription>
|
|
|
|
</Message>
|
2017-11-23 14:18:38 +02:00
|
|
|
) : null}
|
2017-10-31 12:29:15 +02:00
|
|
|
<Table>
|
|
|
|
<TableThead>
|
|
|
|
<TableTr>
|
2017-11-23 14:18:38 +02:00
|
|
|
<TableTh xs="32" padding="0" paddingLeft={remcalc(12)} middle left>
|
|
|
|
<FormGroup paddingTop={remcalc(4)}>
|
|
|
|
<Checkbox
|
|
|
|
checked={allSelected}
|
|
|
|
disabled={submitting}
|
|
|
|
onChange={toggleSelectAll}
|
|
|
|
/>
|
|
|
|
</FormGroup>
|
2017-10-31 12:29:15 +02:00
|
|
|
</TableTh>
|
2017-12-06 12:34:15 +02:00
|
|
|
<TableTh
|
|
|
|
onClick={() => onSortBy('name')}
|
|
|
|
sortOrder={sortOrder}
|
|
|
|
showSort={sortBy === 'name'}
|
|
|
|
left
|
|
|
|
middle
|
|
|
|
actionable
|
|
|
|
>
|
2017-11-23 14:18:38 +02:00
|
|
|
<span>Name </span>
|
2017-10-31 12:29:15 +02:00
|
|
|
</TableTh>
|
2017-11-23 14:18:38 +02:00
|
|
|
<TableTh
|
2017-12-04 20:24:24 +02:00
|
|
|
xs="150"
|
2017-11-23 14:18:38 +02:00
|
|
|
onClick={() => onSortBy('state')}
|
2017-12-06 12:34:15 +02:00
|
|
|
sortOrder={sortOrder}
|
|
|
|
showSort={sortBy === 'state'}
|
2017-11-23 14:18:38 +02:00
|
|
|
left
|
|
|
|
middle
|
|
|
|
actionable
|
|
|
|
>
|
|
|
|
<span>Status </span>
|
2017-10-31 12:29:15 +02:00
|
|
|
</TableTh>
|
2017-11-23 14:18:38 +02:00
|
|
|
<TableTh
|
|
|
|
xs="0"
|
2017-12-04 20:24:24 +02:00
|
|
|
sm="160"
|
2017-11-23 14:18:38 +02:00
|
|
|
onClick={() => onSortBy('created')}
|
2017-12-06 12:34:15 +02:00
|
|
|
sortOrder={sortOrder}
|
|
|
|
showSort={sortBy === 'created'}
|
2017-11-23 14:18:38 +02:00
|
|
|
left
|
|
|
|
middle
|
|
|
|
actionable
|
|
|
|
>
|
|
|
|
<span>Created </span>
|
|
|
|
</TableTh>
|
|
|
|
<TableTh
|
|
|
|
xs="0"
|
2017-12-06 12:34:15 +02:00
|
|
|
sm="130"
|
2017-11-23 14:18:38 +02:00
|
|
|
onClick={() => onSortBy('id')}
|
2017-12-06 12:34:15 +02:00
|
|
|
sortOrder={sortOrder}
|
|
|
|
showSort={sortBy === 'id'}
|
2017-11-23 14:18:38 +02:00
|
|
|
left
|
|
|
|
middle
|
|
|
|
actionable
|
|
|
|
>
|
|
|
|
<span>Short ID </span>
|
|
|
|
</TableTh>
|
2017-12-04 20:24:24 +02:00
|
|
|
<TableTh xs="60" padding="0" />
|
2017-10-31 12:29:15 +02:00
|
|
|
</TableTr>
|
|
|
|
</TableThead>
|
2017-11-02 15:33:43 +02:00
|
|
|
<TableTbody>
|
2017-11-23 14:18:38 +02:00
|
|
|
{items.map(({ id, ...rest }) => (
|
|
|
|
<Item
|
|
|
|
key={id}
|
|
|
|
id={id}
|
|
|
|
{...rest}
|
|
|
|
submitting={submitting}
|
|
|
|
onStart={onStart}
|
|
|
|
onStop={onStop}
|
|
|
|
onReboot={onReboot}
|
|
|
|
onDelete={onDelete}
|
|
|
|
/>
|
|
|
|
))}
|
2017-11-02 15:33:43 +02:00
|
|
|
</TableTbody>
|
2017-10-31 12:29:15 +02:00
|
|
|
</Table>
|
2017-11-23 14:18:38 +02:00
|
|
|
{actionable ? (
|
|
|
|
<Actions
|
|
|
|
allowedActions={allowedActions}
|
|
|
|
submitting={submitting}
|
|
|
|
onStart={onStart}
|
|
|
|
onStop={onStop}
|
|
|
|
onReboot={onReboot}
|
|
|
|
onDelete={onDelete}
|
|
|
|
/>
|
|
|
|
) : null}
|
|
|
|
</form>
|
|
|
|
);
|