mirror of
https://github.com/fleetdm/fleet
synced 2026-05-23 00:49:03 +00:00
Add a timer component to new query screen (#944)
This commit is contained in:
parent
ed1fa22729
commit
3113ae4651
8 changed files with 144 additions and 4 deletions
|
|
@ -13,6 +13,7 @@ import queryInterface from 'interfaces/query';
|
|||
import SelectTargetsDropdown from 'components/forms/fields/SelectTargetsDropdown';
|
||||
import targetInterface from 'interfaces/target';
|
||||
import validateQuery from 'components/forms/validators/validate_query';
|
||||
import Timer from 'components/loaders/Timer';
|
||||
|
||||
const baseClass = 'query-form';
|
||||
|
||||
|
|
@ -204,6 +205,8 @@ class QueryForm extends Component {
|
|||
|
||||
return (
|
||||
<div className={`${baseClass}__button-wrap`}>
|
||||
{queryIsRunning && <Timer running={queryIsRunning} />}
|
||||
|
||||
<DropdownButton
|
||||
className={`${baseClass}__save`}
|
||||
options={dropdownBtnOptions}
|
||||
|
|
|
|||
|
|
@ -15,11 +15,10 @@
|
|||
.query-form__stop-query-btn {
|
||||
margin-left: $pad-xsmall;
|
||||
}
|
||||
}
|
||||
|
||||
&__btn-wrapper {
|
||||
margin-top: $base;
|
||||
text-align: right;
|
||||
.kolide-timer {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&__save-query-btn,
|
||||
|
|
|
|||
68
frontend/components/loaders/Timer/Timer.jsx
Normal file
68
frontend/components/loaders/Timer/Timer.jsx
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
import { convertSeconds } from './helpers';
|
||||
|
||||
const baseClass = 'kolide-timer';
|
||||
|
||||
class Timer extends Component {
|
||||
static propTypes = {
|
||||
running: PropTypes.bool,
|
||||
}
|
||||
|
||||
constructor (props) {
|
||||
super(props);
|
||||
|
||||
this.state = { totalMilliseconds: 0 };
|
||||
}
|
||||
|
||||
componentWillReceiveProps ({ running }) {
|
||||
const { running: currentRunning } = this.props;
|
||||
|
||||
if (running) {
|
||||
if (!currentRunning) {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
this.play();
|
||||
} else {
|
||||
this.pause();
|
||||
}
|
||||
}
|
||||
|
||||
play = () => {
|
||||
const { interval, update } = this;
|
||||
|
||||
if (!interval) {
|
||||
this.interval = setInterval(update, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
pause = () => {
|
||||
const { interval } = this;
|
||||
|
||||
if (interval) {
|
||||
clearInterval(interval);
|
||||
this.interval = null;
|
||||
}
|
||||
}
|
||||
|
||||
reset = () => {
|
||||
this.setState({ totalMilliseconds: 0 });
|
||||
}
|
||||
|
||||
update = () => {
|
||||
const { totalMilliseconds } = this.state;
|
||||
|
||||
this.setState({ totalMilliseconds: totalMilliseconds + 1000 });
|
||||
}
|
||||
|
||||
render () {
|
||||
const { totalMilliseconds } = this.state;
|
||||
|
||||
return (
|
||||
<span className={baseClass}>{convertSeconds(totalMilliseconds)}</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Timer;
|
||||
46
frontend/components/loaders/Timer/Timer.tests.jsx
Normal file
46
frontend/components/loaders/Timer/Timer.tests.jsx
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import expect, { spyOn, restoreSpies } from 'expect';
|
||||
|
||||
import Timer from './Timer';
|
||||
|
||||
describe('Timer - component', () => {
|
||||
afterEach(restoreSpies);
|
||||
|
||||
it('play() and pause() function', () => {
|
||||
const timer = mount(<Timer running={false} />);
|
||||
|
||||
expect(timer.node.interval).toNotExist();
|
||||
timer.setProps({ running: true });
|
||||
expect(timer.node.interval).toExist();
|
||||
timer.setProps({ running: false });
|
||||
expect(timer.node.interval).toNotExist();
|
||||
});
|
||||
|
||||
it('should reset after pause', () => {
|
||||
const timer = mount(<Timer running={false} />);
|
||||
const spy = spyOn(timer.node, 'reset').andCallThrough();
|
||||
|
||||
timer.setProps({ running: true });
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not reset when stopped', () => {
|
||||
const timer = mount(<Timer running />);
|
||||
const spy = spyOn(timer.node, 'reset').andCallThrough();
|
||||
|
||||
timer.setProps({ running: false });
|
||||
|
||||
expect(spy).toNotHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not reset when it continues', () => {
|
||||
const timer = mount(<Timer running />);
|
||||
const spy = spyOn(timer.node, 'reset').andCallThrough();
|
||||
|
||||
timer.setProps({ running: true });
|
||||
|
||||
expect(spy).toNotHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
4
frontend/components/loaders/Timer/_styles.scss
Normal file
4
frontend/components/loaders/Timer/_styles.scss
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
.kolide-timer {
|
||||
font-size: 14px;
|
||||
color: $text-medium;
|
||||
}
|
||||
7
frontend/components/loaders/Timer/helpers.js
Normal file
7
frontend/components/loaders/Timer/helpers.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import moment from 'moment';
|
||||
|
||||
export const convertSeconds = (totalMilliSeconds) => {
|
||||
return moment.utc(totalMilliSeconds).format('HH:mm:ss');
|
||||
};
|
||||
|
||||
export default { convertSeconds };
|
||||
12
frontend/components/loaders/Timer/helpers.tests.js
Normal file
12
frontend/components/loaders/Timer/helpers.tests.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import expect from 'expect';
|
||||
|
||||
import { convertSeconds } from './helpers';
|
||||
|
||||
describe('Timer convertSeconds helper', () => {
|
||||
it('converts seconds to hh:mm:ss', () => {
|
||||
expect(convertSeconds(3000)).toEqual('00:00:03');
|
||||
expect(convertSeconds(30000)).toEqual('00:00:30');
|
||||
expect(convertSeconds(300000)).toEqual('00:05:00');
|
||||
expect(convertSeconds(0)).toEqual('00:00:00');
|
||||
});
|
||||
});
|
||||
1
frontend/components/loaders/Timer/index.js
Normal file
1
frontend/components/loaders/Timer/index.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
export default from './Timer';
|
||||
Loading…
Reference in a new issue