mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
* feat: add autoplay redux boilerplate WIP auto-play settings * feat: add page cycle settings * feat: add cycle toggle hotkey * chore: add tooltip text to settings icon * settings layout * fix: handle invalid input for custom interval * chore: address nit
This commit is contained in:
parent
f196aaf261
commit
4a2f90fece
14 changed files with 382 additions and 106 deletions
|
@ -4,16 +4,13 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { Fragment, Component } from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiFlexGrid,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiButton,
|
||||
EuiLink,
|
||||
EuiFieldText,
|
||||
EuiSpacer,
|
||||
EuiHorizontalRule,
|
||||
EuiDescriptionList,
|
||||
|
@ -21,32 +18,25 @@ import {
|
|||
EuiDescriptionListDescription,
|
||||
EuiFormLabel,
|
||||
EuiText,
|
||||
EuiButtonIcon,
|
||||
EuiToolTip,
|
||||
} from '@elastic/eui';
|
||||
import { timeDurationString } from '../../../lib/time_duration';
|
||||
import { RefreshControl } from '../refresh_control';
|
||||
import { CustomInterval } from './custom_interval';
|
||||
|
||||
const ListGroup = ({ children }) => <ul style={{ listStyle: 'none', margin: 0 }}>{[children]}</ul>;
|
||||
|
||||
export class AutoRefreshControls extends Component {
|
||||
static propTypes = {
|
||||
refreshInterval: PropTypes.number,
|
||||
setRefresh: PropTypes.func.isRequired,
|
||||
disableInterval: PropTypes.func.isRequired,
|
||||
};
|
||||
export const AutoRefreshControls = ({ refreshInterval, setRefresh, disableInterval }) => {
|
||||
const RefreshItem = ({ duration, label }) => (
|
||||
<li>
|
||||
<EuiLink onClick={() => setRefresh(duration)}>{label}</EuiLink>
|
||||
</li>
|
||||
);
|
||||
|
||||
refreshInput = null;
|
||||
|
||||
render() {
|
||||
const { refreshInterval, setRefresh, disableInterval } = this.props;
|
||||
|
||||
const RefreshItem = ({ duration, label }) => (
|
||||
<li>
|
||||
<EuiLink onClick={() => setRefresh(duration)}>{label}</EuiLink>
|
||||
</li>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
return (
|
||||
<EuiFlexGroup direction="column" justifyContent="spaceBetween">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexGroup alignItems="center" justifyContent="spaceAround" gutterSize="xs">
|
||||
<EuiFlexItem>
|
||||
<EuiDescriptionList textStyle="reverse">
|
||||
|
@ -55,11 +45,6 @@ export class AutoRefreshControls extends Component {
|
|||
{refreshInterval > 0 ? (
|
||||
<Fragment>
|
||||
<span>Every {timeDurationString(refreshInterval)}</span>
|
||||
<div>
|
||||
<EuiLink size="s" onClick={disableInterval}>
|
||||
Disable auto-refresh
|
||||
</EuiLink>
|
||||
</div>
|
||||
</Fragment>
|
||||
) : (
|
||||
<span>Manually</span>
|
||||
|
@ -68,7 +53,22 @@ export class AutoRefreshControls extends Component {
|
|||
</EuiDescriptionList>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<RefreshControl />
|
||||
<EuiFlexGroup justifyContent="flexEnd" gutterSize="xs">
|
||||
{refreshInterval > 0 ? (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip position="bottom" content="Disable auto-refresh">
|
||||
<EuiButtonIcon
|
||||
iconType="cross"
|
||||
onClick={disableInterval}
|
||||
aria-label="Disable auto-refresh"
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
) : null}
|
||||
<EuiFlexItem grow={false}>
|
||||
<RefreshControl />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
|
@ -100,35 +100,17 @@ export class AutoRefreshControls extends Component {
|
|||
</EuiFlexItem>
|
||||
</EuiFlexGrid>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
<EuiFlexItem grow={false}>
|
||||
<CustomInterval onSubmit={value => setRefresh(value)} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
<form
|
||||
onSubmit={ev => {
|
||||
ev.preventDefault();
|
||||
setRefresh(this.refreshInput.value);
|
||||
}}
|
||||
>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
label="Set a custom interval"
|
||||
helpText="Use shorthand notation, like 30s, 10m, or 1h"
|
||||
compressed
|
||||
>
|
||||
<EuiFieldText inputRef={i => (this.refreshInput = i)} />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow label=" ">
|
||||
<EuiButton size="s" type="submit" style={{ minWidth: 'auto' }}>
|
||||
Set
|
||||
</EuiButton>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
AutoRefreshControls.propTypes = {
|
||||
refreshInterval: PropTypes.number,
|
||||
setRefresh: PropTypes.func.isRequired,
|
||||
disableInterval: PropTypes.func.isRequired,
|
||||
};
|
||||
|
|
|
@ -6,45 +6,29 @@
|
|||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiButtonIcon } from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiButtonIcon, EuiToolTip } from '@elastic/eui';
|
||||
import { Popover } from '../../popover';
|
||||
import { AutoRefreshControls } from './auto_refresh_controls';
|
||||
import { KioskControls } from './kiosk_controls';
|
||||
|
||||
const getRefreshInterval = (val = '') => {
|
||||
// if it's a number, just use it directly
|
||||
if (!isNaN(Number(val))) {
|
||||
return val;
|
||||
}
|
||||
|
||||
// if it's a string, try to parse out the shorthand duration value
|
||||
const match = String(val).match(/^([0-9]{1,})([hmsd])$/);
|
||||
|
||||
// TODO: do something better with improper input, like show an error...
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (match[2]) {
|
||||
case 's':
|
||||
return match[1] * 1000;
|
||||
case 'm':
|
||||
return match[1] * 1000 * 60;
|
||||
case 'h':
|
||||
return match[1] * 1000 * 60 * 60;
|
||||
case 'd':
|
||||
return match[1] * 1000 * 60 * 60 * 24;
|
||||
}
|
||||
};
|
||||
|
||||
export const ControlSettings = ({ setRefreshInterval, refreshInterval }) => {
|
||||
const setRefresh = val => setRefreshInterval(getRefreshInterval(val));
|
||||
export const ControlSettings = ({
|
||||
setRefreshInterval,
|
||||
refreshInterval,
|
||||
autoplayEnabled,
|
||||
autoplayInterval,
|
||||
enableAutoplay,
|
||||
setAutoplayInterval,
|
||||
}) => {
|
||||
const setRefresh = val => setRefreshInterval(val);
|
||||
|
||||
const disableInterval = () => {
|
||||
setRefresh(0);
|
||||
};
|
||||
|
||||
const popoverButton = handleClick => (
|
||||
<EuiButtonIcon iconType="gear" aria-label="Control settings" onClick={handleClick} />
|
||||
<EuiToolTip position="bottom" content="Control settings">
|
||||
<EuiButtonIcon iconType="gear" aria-label="Control settings" onClick={handleClick} />
|
||||
</EuiToolTip>
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -54,19 +38,21 @@ export const ControlSettings = ({ setRefreshInterval, refreshInterval }) => {
|
|||
anchorPosition="rightUp"
|
||||
panelClassName="canvasControlSettings__popover"
|
||||
>
|
||||
{({ closePopover }) => (
|
||||
{() => (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<AutoRefreshControls
|
||||
refreshInterval={refreshInterval}
|
||||
setRefresh={val => {
|
||||
setRefresh(val);
|
||||
closePopover();
|
||||
}}
|
||||
disableInterval={() => {
|
||||
disableInterval();
|
||||
closePopover();
|
||||
}}
|
||||
setRefresh={val => setRefresh(val)}
|
||||
disableInterval={() => disableInterval()}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<KioskControls
|
||||
autoplayEnabled={autoplayEnabled}
|
||||
autoplayInterval={autoplayInterval}
|
||||
onSetInterval={setAutoplayInterval}
|
||||
onSetEnabled={enableAutoplay}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
@ -78,4 +64,8 @@ export const ControlSettings = ({ setRefreshInterval, refreshInterval }) => {
|
|||
ControlSettings.propTypes = {
|
||||
refreshInterval: PropTypes.number,
|
||||
setRefreshInterval: PropTypes.func.isRequired,
|
||||
autoplayEnabled: PropTypes.bool,
|
||||
autoplayInterval: PropTypes.number,
|
||||
enableAutoplay: PropTypes.func.isRequired,
|
||||
setAutoplayInterval: PropTypes.func.isRequired,
|
||||
};
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
.canvasControlSettings__popover {
|
||||
width: 300px;
|
||||
width: 600px;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiButton, EuiFieldText } from '@elastic/eui';
|
||||
|
||||
const getRefreshInterval = (val = '') => {
|
||||
// if it's a number, there is no interval, return undefined
|
||||
if (!isNaN(Number(val))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if it's a string, try to parse out the shorthand duration value
|
||||
const match = String(val).match(/^([0-9]{1,})([hmsd])$/);
|
||||
|
||||
// if it's invalid, there is no interval, return undefined
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (match[2]) {
|
||||
case 's':
|
||||
return match[1] * 1000;
|
||||
case 'm':
|
||||
return match[1] * 1000 * 60;
|
||||
case 'h':
|
||||
return match[1] * 1000 * 60 * 60;
|
||||
case 'd':
|
||||
return match[1] * 1000 * 60 * 60 * 24;
|
||||
}
|
||||
};
|
||||
|
||||
export const CustomInterval = ({ gutterSize, buttonSize, onSubmit, defaultValue }) => {
|
||||
const [customInterval, setCustomInterval] = useState(defaultValue);
|
||||
const refreshInterval = getRefreshInterval(customInterval);
|
||||
const isInvalid = Boolean(customInterval.length && !refreshInterval);
|
||||
|
||||
const handleChange = ev => setCustomInterval(ev.target.value);
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={ev => {
|
||||
ev.preventDefault();
|
||||
onSubmit(refreshInterval);
|
||||
}}
|
||||
>
|
||||
<EuiFlexGroup gutterSize={gutterSize}>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
label="Set a custom interval"
|
||||
helpText="Use shorthand notation, like 30s, 10m, or 1h"
|
||||
compressed
|
||||
>
|
||||
<EuiFieldText isInvalid={isInvalid} value={customInterval} onChange={handleChange} />
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow label=" ">
|
||||
<EuiButton
|
||||
disabled={isInvalid}
|
||||
size={buttonSize}
|
||||
type="submit"
|
||||
style={{ minWidth: 'auto' }}
|
||||
>
|
||||
Set
|
||||
</EuiButton>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
CustomInterval.propTypes = {
|
||||
buttonSize: PropTypes.string,
|
||||
gutterSize: PropTypes.string,
|
||||
defaultValue: PropTypes.string,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
CustomInterval.defaultProps = {
|
||||
buttonSize: 's',
|
||||
gutterSize: 's',
|
||||
defaultValue: '',
|
||||
};
|
|
@ -5,16 +5,28 @@
|
|||
*/
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
import { setRefreshInterval } from '../../../state/actions/workpad';
|
||||
import { getRefreshInterval } from '../../../state/selectors/workpad';
|
||||
import {
|
||||
setRefreshInterval,
|
||||
enableAutoplay,
|
||||
setAutoplayInterval,
|
||||
} from '../../../state/actions/workpad';
|
||||
import { getRefreshInterval, getAutoplay } from '../../../state/selectors/workpad';
|
||||
import { ControlSettings as Component } from './control_settings';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
refreshInterval: getRefreshInterval(state),
|
||||
});
|
||||
const mapStateToProps = state => {
|
||||
const { enabled, interval } = getAutoplay(state);
|
||||
|
||||
return {
|
||||
refreshInterval: getRefreshInterval(state),
|
||||
autoplayEnabled: enabled,
|
||||
autoplayInterval: interval,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = {
|
||||
setRefreshInterval,
|
||||
enableAutoplay,
|
||||
setAutoplayInterval,
|
||||
};
|
||||
|
||||
export const ControlSettings = connect(
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
EuiDescriptionList,
|
||||
EuiDescriptionListDescription,
|
||||
EuiDescriptionListTitle,
|
||||
EuiFormLabel,
|
||||
EuiHorizontalRule,
|
||||
EuiLink,
|
||||
EuiSpacer,
|
||||
EuiSwitch,
|
||||
EuiText,
|
||||
EuiFlexGrid,
|
||||
EuiFlexItem,
|
||||
EuiFlexGroup,
|
||||
} from '@elastic/eui';
|
||||
import { timeDurationString } from '../../../lib/time_duration';
|
||||
import { CustomInterval } from './custom_interval';
|
||||
|
||||
const ListGroup = ({ children }) => <ul style={{ listStyle: 'none', margin: 0 }}>{[children]}</ul>;
|
||||
|
||||
export const KioskControls = ({
|
||||
autoplayEnabled,
|
||||
autoplayInterval,
|
||||
onSetEnabled,
|
||||
onSetInterval,
|
||||
}) => {
|
||||
const RefreshItem = ({ duration, label }) => (
|
||||
<li>
|
||||
<EuiLink onClick={() => onSetInterval(duration)}>{label}</EuiLink>
|
||||
</li>
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiFlexGroup direction="column" justifyContent="spaceBetween">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiDescriptionList textStyle="reverse">
|
||||
<EuiDescriptionListTitle>Cycle fullscreen pages</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>
|
||||
<span>Every {timeDurationString(autoplayInterval)}</span>
|
||||
</EuiDescriptionListDescription>
|
||||
</EuiDescriptionList>
|
||||
<EuiHorizontalRule margin="m" />
|
||||
|
||||
<div>
|
||||
<EuiSwitch
|
||||
checked={autoplayEnabled}
|
||||
label="Cycle slides automatically"
|
||||
onChange={ev => onSetEnabled(ev.target.checked)}
|
||||
/>
|
||||
<EuiSpacer size="m" />
|
||||
</div>
|
||||
|
||||
<EuiFormLabel>Change cycling interval</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<EuiText size="s">
|
||||
<EuiFlexGrid gutterSize="s" columns={2}>
|
||||
<EuiFlexItem>
|
||||
<ListGroup>
|
||||
<RefreshItem duration="5000" label="5 seconds" />
|
||||
<RefreshItem duration="10000" label="10 seconds" />
|
||||
<RefreshItem duration="30000" label="30 seconds" />
|
||||
</ListGroup>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<ListGroup>
|
||||
<RefreshItem duration="60000" label="1 minute" />
|
||||
<RefreshItem duration="300000" label="5 minutes" />
|
||||
<RefreshItem duration="900000" label="15 minute" />
|
||||
</ListGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGrid>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<CustomInterval onSubmit={value => onSetInterval(value)} />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
KioskControls.propTypes = {
|
||||
autoplayEnabled: PropTypes.bool.isRequired,
|
||||
autoplayInterval: PropTypes.number.isRequired,
|
||||
onSetEnabled: PropTypes.func.isRequired,
|
||||
onSetInterval: PropTypes.func.isRequired,
|
||||
};
|
|
@ -16,6 +16,10 @@ export class FullscreenControl extends React.PureComponent {
|
|||
if (enterFullscreen || exitFullscreen) {
|
||||
this.toggleFullscreen();
|
||||
}
|
||||
|
||||
if (action === 'PAGE_CYCLE_TOGGLE') {
|
||||
this.props.enableAutoplay(!this.props.autoplayEnabled);
|
||||
}
|
||||
};
|
||||
|
||||
toggleFullscreen = () => {
|
||||
|
|
|
@ -6,11 +6,14 @@
|
|||
|
||||
import { connect } from 'react-redux';
|
||||
import { setFullscreen, selectToplevelNodes } from '../../../state/actions/transient';
|
||||
import { enableAutoplay } from '../../../state/actions/workpad';
|
||||
import { getFullscreen } from '../../../state/selectors/app';
|
||||
import { getAutoplay } from '../../../state/selectors/workpad';
|
||||
import { FullscreenControl as Component } from './fullscreen_control';
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
isFullscreen: getFullscreen(state),
|
||||
autoplayEnabled: getAutoplay(state).enabled,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
|
@ -18,6 +21,7 @@ const mapDispatchToProps = dispatch => ({
|
|||
dispatch(setFullscreen(value));
|
||||
value && dispatch(selectToplevelNodes([]));
|
||||
},
|
||||
enableAutoplay: enabled => dispatch(enableAutoplay(enabled)),
|
||||
});
|
||||
|
||||
export const FullscreenControl = connect(
|
||||
|
|
|
@ -16,6 +16,8 @@ export const setWriteable = createAction('setWriteable');
|
|||
export const setColors = createAction('setColors');
|
||||
export const setRefreshInterval = createAction('setRefreshInterval');
|
||||
export const setWorkpadCSS = createAction('setWorkpadCSS');
|
||||
export const enableAutoplay = createAction('enableAutoplay');
|
||||
export const setAutoplayInterval = createAction('setAutoplayInterval');
|
||||
|
||||
export const initializeWorkpad = createThunk('initializeWorkpad', ({ dispatch }) => {
|
||||
dispatch(fetchAllRenderables());
|
||||
|
|
|
@ -26,6 +26,10 @@ export const getInitialState = path => {
|
|||
refresh: {
|
||||
interval: 0,
|
||||
},
|
||||
autoplay: {
|
||||
enabled: false,
|
||||
interval: 10000,
|
||||
},
|
||||
// values in resolvedArgs should live under a unique index so they can be looked up.
|
||||
// The ID of the element is a great example.
|
||||
// In there will live an object with a status (string), value (any), and error (Error) property.
|
||||
|
|
|
@ -14,6 +14,7 @@ import { historyMiddleware } from './history';
|
|||
import { inFlight } from './in_flight';
|
||||
import { workpadUpdate } from './workpad_update';
|
||||
import { workpadRefresh } from './workpad_refresh';
|
||||
import { workpadAutoplay } from './workpad_autoplay';
|
||||
import { appReady } from './app_ready';
|
||||
import { elementStats } from './element_stats';
|
||||
import { resolvedArgs } from './resolved_args';
|
||||
|
@ -30,7 +31,8 @@ const middlewares = [
|
|||
inFlight,
|
||||
appReady,
|
||||
workpadUpdate,
|
||||
workpadRefresh
|
||||
workpadRefresh,
|
||||
workpadAutoplay
|
||||
),
|
||||
];
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { inFlightComplete } from '../actions/resolved_args';
|
||||
import { getFullscreen } from '../selectors/app';
|
||||
import { getInFlight } from '../selectors/resolved_args';
|
||||
import { getWorkpad, getPages, getSelectedPageIndex, getAutoplay } from '../selectors/workpad';
|
||||
import { routerProvider } from '../../lib/router_provider';
|
||||
|
||||
export const workpadAutoplay = ({ getState }) => next => {
|
||||
let playTimeout;
|
||||
let displayInterval = 0;
|
||||
|
||||
const router = routerProvider();
|
||||
|
||||
function updateWorkpad() {
|
||||
if (displayInterval === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check the request in flight status
|
||||
const inFlightActive = getInFlight(getState());
|
||||
|
||||
// only navigate if no requests are in-flight
|
||||
if (!inFlightActive) {
|
||||
// update the elements on the workpad
|
||||
const workpadId = getWorkpad(getState()).id;
|
||||
const pageIndex = getSelectedPageIndex(getState());
|
||||
const pageCount = getPages(getState()).length;
|
||||
const nextPage = Math.min(pageIndex + 1, pageCount - 1);
|
||||
|
||||
// go to start if on the last page
|
||||
if (nextPage === pageIndex) {
|
||||
router.navigateTo('loadWorkpad', { id: workpadId, page: 1 });
|
||||
} else {
|
||||
router.navigateTo('loadWorkpad', { id: workpadId, page: nextPage + 1 });
|
||||
}
|
||||
}
|
||||
|
||||
startDelayedUpdate();
|
||||
}
|
||||
|
||||
function stopAutoUpdate() {
|
||||
clearTimeout(playTimeout); // cancel any pending update requests
|
||||
}
|
||||
|
||||
function startDelayedUpdate() {
|
||||
stopAutoUpdate();
|
||||
playTimeout = setTimeout(() => {
|
||||
updateWorkpad();
|
||||
}, displayInterval);
|
||||
}
|
||||
|
||||
return action => {
|
||||
next(action);
|
||||
|
||||
const isFullscreen = getFullscreen(getState());
|
||||
const autoplay = getAutoplay(getState());
|
||||
const shouldPlay = isFullscreen && autoplay.enabled && autoplay.interval > 0;
|
||||
displayInterval = autoplay.interval;
|
||||
|
||||
// when in-flight requests are finished, update the workpad after a given delay
|
||||
if (action.type === inFlightComplete.toString() && shouldPlay) {
|
||||
startDelayedUpdate();
|
||||
} // create new update request
|
||||
|
||||
// This middleware creates or destroys an interval that will cause workpad elements to update
|
||||
// clear any pending timeout
|
||||
stopAutoUpdate();
|
||||
|
||||
// if interval is larger than 0, start the delayed update
|
||||
if (shouldPlay) {
|
||||
startDelayedUpdate();
|
||||
}
|
||||
};
|
||||
};
|
|
@ -10,7 +10,7 @@ import { restoreHistory } from '../actions/history';
|
|||
import * as pageActions from '../actions/pages';
|
||||
import * as transientActions from '../actions/transient';
|
||||
import { removeElements } from '../actions/elements';
|
||||
import { setRefreshInterval } from '../actions/workpad';
|
||||
import { setRefreshInterval, enableAutoplay, setAutoplayInterval } from '../actions/workpad';
|
||||
|
||||
export const transientReducer = handleActions(
|
||||
{
|
||||
|
@ -63,6 +63,14 @@ export const transientReducer = handleActions(
|
|||
[setRefreshInterval]: (transientState, { payload }) => {
|
||||
return { ...transientState, refresh: { interval: Number(payload) || 0 } };
|
||||
},
|
||||
|
||||
[enableAutoplay]: (transientState, { payload }) => {
|
||||
return set(transientState, 'autoplay.enabled', Boolean(payload) || false);
|
||||
},
|
||||
|
||||
[setAutoplayInterval]: (transientState, { payload }) => {
|
||||
return set(transientState, 'autoplay.interval', Number(payload) || 0);
|
||||
},
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
|
|
@ -319,3 +319,7 @@ export function getContextForIndex(state, index) {
|
|||
export function getRefreshInterval(state) {
|
||||
return get(state, 'transient.refresh.interval', 0);
|
||||
}
|
||||
|
||||
export function getAutoplay(state) {
|
||||
return get(state, 'transient.autoplay');
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue