Skip to content

Commit

Permalink
Adds EUI to Workpad Loader (elastic#669)
Browse files Browse the repository at this point in the history
* Added EUI to workpad loader

* Added EuiInMemoryTable to workpad_loader

* Changed workpad_create to a stateless component

* Added EuiCode to update_modal and workpad_upload

* Changed font color in workpad_loader

* Added height to workpad_loader

* Fixed workpad name.

* Switched to EuiBasicTable. Added logic for column sorting

* Fixed iconType issue

* Changed icon in workpad create button

* Changed height of workpad_loader
  • Loading branch information
cqliu1 committed Jun 20, 2018
1 parent 2542cbf commit da4bb14
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 126 deletions.
3 changes: 2 additions & 1 deletion public/components/link/link.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { EuiLink } from '@elastic/eui';

const isModifiedEvent = ev => !!(ev.metaKey || ev.altKey || ev.ctrlKey || ev.shiftKey);

Expand Down Expand Up @@ -41,7 +42,7 @@ export class Link extends React.PureComponent {
onClick: this.navigateTo(name, params),
};

return <a {...props}>{children}</a>;
return <EuiLink {...props}>{children}</EuiLink>;
} catch (e) {
console.error(e);
return <div>LINK ERROR: {e.message}</div>;
Expand Down
7 changes: 4 additions & 3 deletions public/components/update_modal/update_modal.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Modal, Button } from 'react-bootstrap';
import { EuiCode } from '@elastic/eui';
import { Changes } from './changes';
import goat from './goat.png';

Expand Down Expand Up @@ -38,12 +39,12 @@ export const UpdateModal = ({ filename, setFilename, changes }) => {
need these steps:
</p>
<h5>1. Stop Kibana and remove the old version of Canvas</h5>
<code>./bin/kibana-plugin remove canvas</code>
<EuiCode>./bin/kibana-plugin remove canvas</EuiCode>
<h5>2. Install the new version</h5>
<code>
<EuiCode>
NODE_OPTIONS="--max-old-space-size=4096" ./bin/kibana-plugin install
https://download.elastic.co/kibana/canvas/{filename}
</code>
</EuiCode>
<h5>3. Start Kibana and refresh your browser</h5>
You should be good to go. Good luck!
</Modal.Body>
Expand Down
47 changes: 15 additions & 32 deletions public/components/workpad_loader/workpad_create.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,19 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Button } from 'react-bootstrap';
import { EuiButton } from '@elastic/eui';

export class WorkpadCreate extends React.PureComponent {
static propTypes = {
onCreate: PropTypes.func.isRequired,
};
export const WorkpadCreate = ({ createPending, onCreate }) => (
<EuiButton
fill
onClick={onCreate}
isLoading={createPending}
iconType={!createPending ? 'plusInCircle' : null}
>
Create Workpad
</EuiButton>
);

state = {
createPending: false,
};

create = () => {
this.setState({ createPending: true });
this.props.onCreate();
};

render() {
const { createPending } = this.state;

return (
<Button
bsSize="xsmall"
bsStyle="primary"
onClick={this.create}
disabled={createPending}
className="canvas__workpad_loader--new"
>
{createPending && <i className="fa fa-spinner fa-pulse" />}
{!createPending && <i className="fa fa-plus" />}
&nbsp;New Workpad
</Button>
);
}
}
WorkpadCreate.propTypes = {
onCreate: PropTypes.func.isRequired,
createPending: PropTypes.bool,
};
162 changes: 110 additions & 52 deletions public/components/workpad_loader/workpad_loader.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Form, Table } from 'react-bootstrap';
import moment from 'moment';
import { sortByOrder } from 'lodash';
import { EuiFlexGroup, EuiFlexItem, EuiBasicTable, EuiButtonIcon, EuiSpacer } from '@elastic/eui';
import { ConfirmModal } from '../confirm_modal';
import { Link } from '../link';
import { WorkpadUpload } from './workpad_upload';
Expand All @@ -24,6 +25,8 @@ export class WorkpadLoader extends React.PureComponent {
state = {
deletingWorkpad: {},
createPending: false,
sortField: '@timestamp',
sortDirection: 'desc',
};

async componentDidMount() {
Expand Down Expand Up @@ -59,58 +62,106 @@ export class WorkpadLoader extends React.PureComponent {
this.closeRemoveConfirm();
};

renderWorkpadTable = () => {
const { workpads } = this.props;
downloadWorkpad = workpad => {
this.props.downloadWorkpad(workpad.id);
};

return (
<Table condensed className="canvas__workpad_loader--workpads">
<thead>
<tr>
<th>Workpad name</th>
<th>Created</th>
<th>Updated</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
{workpads.total === 0 && (
<tr>
<td colSpan="3">No matching workpads found</td>
</tr>
)}
{workpads.workpads.map(this.renderWorkpadRow)}
</tbody>
</Table>
);
onTableChange = ({ sort = {} }) => {
const { field: sortField, direction: sortDirection } = sort;
this.setState({
sortField,
sortDirection,
});
};

renderWorkpadRow = workpad => {
const workpadName = workpad.name.length ? workpad.name : <em>{workpad.id}</em>;
renderWorkpadTable = () => {
const { sortField, sortDirection } = this.state;
const { workpads } = this.props.workpads;

const actions = [
{
render: workpad => (
<EuiFlexGroup gutterSize="xs" alignItems="center">
<EuiFlexItem grow={false}>
<EuiButtonIcon
iconType="exportAction"
onClick={() => this.downloadWorkpad(workpad)}
aria-label="Export Workpad"
/>
</EuiFlexItem>
<EuiFlexItem>
<EuiButtonIcon
iconType="trash"
color="danger"
onClick={() => this.removeConfirm(workpad)}
aria-label="Delete Workpad"
/>
</EuiFlexItem>
</EuiFlexGroup>
),
},
];

const columns = [
{
field: 'name',
name: 'Workpad Name',
sortable: true,
dataType: 'string',
render: (name, workpad) => {
const workpadName = workpad.name.length ? workpad.name : <em>{workpad.id}</em>;

return (
<Link
name="loadWorkpad"
params={{ id: workpad.id }}
aria-label={`Load workpad ${workpadName}`}
>
{workpadName}
</Link>
);
},
},
{
field: '@created',
name: 'Created',
sortable: true,
dataType: 'date',
width: '20%',
render: date => formatDate(date),
},
{
field: '@timestamp',
name: 'Updated',
sortable: true,
dataType: 'date',
width: '20%',
render: date => formatDate(date),
},
{ name: '', actions, width: '5%' },
];

const sorting = {
sort: {
field: sortField,
direction: sortDirection,
},
};

const sortedWorkpads = sortByOrder(
workpads,
[sortField, '@timestamp'],
[sortDirection, 'desc']
);

return (
<tr key={workpad.id} className="canvas__workpad_loader--workpad">
<td width="97%" className="canvas__workpad_loader--name">
<Link
name="loadWorkpad"
params={{ id: workpad.id }}
aria-label={`Load workpad ${workpadName}`}
>
{workpadName}
</Link>
</td>
<td width="1%" className="canvas__workpad_loader--created">
{formatDate(workpad['@created'])}
</td>
<td width="1%" className="canvas__workpad_loader--updated">
{formatDate(workpad['@timestamp'])}
</td>
<td width="1%" className="canvas__workpad_loader--export">
<span onClick={() => this.props.downloadWorkpad(workpad.id)} className="fa fa-download" />
</td>
<td width="1%" className="canvas__workpad_loader--delete">
<span onClick={() => this.removeConfirm(workpad)} className="fa fa-trash" />
</td>
</tr>
<EuiBasicTable
items={sortedWorkpads}
columns={columns}
sorting={sorting}
message="No matching workpads found"
onChange={this.onTableChange}
/>
);
};

Expand All @@ -121,10 +172,16 @@ export class WorkpadLoader extends React.PureComponent {
return (
<div className="canvas__workpad_loader">
<WorkpadUpload onUpload={this.uploadWorkpad}>
<Form className="canvas__workpad_loader--controls">
<WorkpadCreate onCreate={this.createWorkpad} />
<WorkpadSearch onChange={this.props.findWorkpads} />
</Form>
<EuiFlexGroup gutterSize="s" className="canvas__workpad_loader--controls">
<EuiFlexItem grow={false}>
<WorkpadCreate createPending={createPending} onCreate={this.createWorkpad} />
</EuiFlexItem>
<EuiFlexItem className="canvas__workpad_loader--search">
<WorkpadSearch onChange={this.props.findWorkpads} />
</EuiFlexItem>
</EuiFlexGroup>

<EuiSpacer size="l" />

{createPending && <div>Creating Workpad...</div>}
{!createPending && isLoading && <div>Fetching Workpads...</div>}
Expand All @@ -133,6 +190,7 @@ export class WorkpadLoader extends React.PureComponent {

<ConfirmModal
isOpen={deletingWorkpad.id != null}
title="Remove Workpad"
message={`Are you sure you want to remove the workpad '${deletingWorkpad.name}'?`}
confirmButtonText="Remove"
onConfirm={() => this.removeWorkpad(deletingWorkpad.id)}
Expand Down
34 changes: 3 additions & 31 deletions public/components/workpad_loader/workpad_loader.scss
Original file line number Diff line number Diff line change
@@ -1,35 +1,7 @@
.canvas__workpad_loader {
height: 400px;
display: flex;
height: fit-content;

& > div {
width: 100%;
}

.canvas__workpad_loader--created,
.canvas__workpad_loader--updated {
white-space: nowrap;
}

.canvas__workpad_loader--delete:hover {
color: $euiColorDanger;
}

.canvas__workpad_loader--export:hover {
color: $euiColorSecondary;
}

.canvas__workpad_loader--workpad a {
color: $euiColorEmptyShade;
}

.canvas__workpad_loader--controls {
display: flex;
flex-direction: row;
margin-bottom: $euiSize;
}

.canvas__workpad_loader--new {
margin-right: $euiSize;
.canvas__workpad_loader--search {
color: $euiColorDarkestShade;
}
}
9 changes: 5 additions & 4 deletions public/components/workpad_loader/workpad_search.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormControl } from 'react-bootstrap';
import { EuiFieldSearch } from '@elastic/eui';
import { debounce } from 'lodash';

export class WorkpadSearch extends React.PureComponent {
Expand All @@ -23,11 +23,12 @@ export class WorkpadSearch extends React.PureComponent {

render() {
return (
<FormControl
type="text"
placeholder="Find Workpads"
<EuiFieldSearch
placeholder="Find workpad"
value={this.state.searchText}
onChange={this.setSearchText}
fullWidth
incremental
/>
);
}
Expand Down
6 changes: 3 additions & 3 deletions public/components/workpad_loader/workpad_upload.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import Dropzone from 'react-dropzone';
import { EuiCode } from '@elastic/eui';
import { getId } from '../../lib/get_id';

export class WorkpadUpload extends React.PureComponent {
Expand Down Expand Up @@ -45,12 +46,11 @@ export class WorkpadUpload extends React.PureComponent {
<center>
<p>
<i>
Tip: Drag and drop a <code>JSON</code> exported workpad into this dialog to load new
workpad from a file
Tip: Drag and drop a <EuiCode>JSON</EuiCode> exported workpad into this dialog to load
new workpad from a file
</i>
</p>
</center>

{this.props.children}
</Dropzone>
);
Expand Down
10 changes: 10 additions & 0 deletions public/style/hackery.scss
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,13 @@ html {
font-size: 0.75rem;
}
}

// TODO: remove when bootstrap is removed
// overrides code styles set by bootstrap
code {
padding: unset;
font-size: unset;
color: unset;
background-color: unset;
border-radius: unset;
}

0 comments on commit da4bb14

Please sign in to comment.