Commit bc92eb56 authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '86-check-for-updates' into 'master'

Resolve "Check for updates"

Closes #86

See merge request genesys-pgr/genesys-ui!83
parents 9b4a572b db458b69
......@@ -2,6 +2,9 @@ import * as Constants from 'constants/serverInfo';
import {log} from 'utilities/debug';
import ApiInfo from 'model/ApiInfo';
import ApiInfoService from 'service/genesys/ApiInfoService';
import AppVersionService from 'service/genesys/AppVersionService';
import {showSnackbar} from 'actions/snackbar';
import PageReloadButton from 'ui/common/buttons/PageReloadButton';
export const serverInfoRequest = () => (dispatch, getState): Promise<ApiInfo> => {
return ApiInfoService.apiInfo()
......@@ -13,3 +16,20 @@ const getServerInfo = (info: ApiInfo) => ({
type: Constants.GET_SERVER_INFO,
payload: { info },
});
const delay = 5 * 60 * 1000;
export const checkSoftwareVersion = () => (dispatch, getState) => {
return AppVersionService.getSoftwareVersion()
.then((softwareVersion) => {
// @ts-ignore
const currentSoftVersion = window.softwareCommit;
if (currentSoftVersion !== softwareVersion) {
dispatch(showSnackbar('New version is available', PageReloadButton));
}
setTimeout(() => dispatch(checkSoftwareVersion()), delay);
});
};
import { SHOW_SNACKBAR } from 'constants/snackbar';
export const showSnackbar = (content: string) => (dispatch) => {
dispatch({type: SHOW_SNACKBAR, payload: content});
export const showSnackbar = (content: string, button?: any) => (dispatch) => {
dispatch({type: SHOW_SNACKBAR, payload: {content, button}});
};
......@@ -3,19 +3,24 @@ import { SHOW_SNACKBAR } from 'constants/snackbar';
const INITIAL_STATE: {
content: any,
button: any,
} = {
content: null,
button: null,
};
export default function snackbar(state = INITIAL_STATE, action: { type?: string, payload?: string } = {type: '', payload: null}) {
export default function snackbar(state = INITIAL_STATE, action: { type?: string, payload?: any } = {type: '', payload: null}) {
switch (action.type) {
case SHOW_SNACKBAR: {
if (! action.payload) {
return state;
}
const {content, button} = action.payload;
return update(state, {
content: { $set: { message: action.payload, timestap: new Date().getTime() } },
content: { $set: { message: content, timestap: new Date().getTime() } },
button: {$set: button},
});
}
......
import axios from 'axios';
const SOFTWARE_VERSION_URL = '/COMMITHASH';
export default class AppVersionService {
public static getSoftwareVersion = () => {
const virtualPath = document.baseURI.replace(/^(https?:\/\/[^\/]+)?(.*)\/$/, '$2');
return axios.get(`${virtualPath}${SOFTWARE_VERSION_URL}`)
.then(({ data }) => data as string);
}
}
import * as React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import {updateHistory} from 'actions/history';
import {loadCrops} from 'crop/actions/public';
import {initMyList} from 'user/actions/public';
import { serverInfoRequest } from 'actions/serverInfo';
import { updateHistory } from 'actions/history';
import { loadCrops } from 'crop/actions/public';
import { initMyList } from 'user/actions/public';
import { checkSoftwareVersion, serverInfoRequest } from 'actions/serverInfo';
import { withRouter } from 'react-router-dom';
......@@ -29,6 +29,7 @@ interface IAppProps extends React.ClassAttributes<any> {
initMyList: () => void;
serverInfo: any;
serverInfoRequest: any;
checkSoftwareVersion: any;
}
class App extends React.Component<IAppProps, any> {
......@@ -54,9 +55,12 @@ class App extends React.Component<IAppProps, any> {
}
public componentDidMount() {
const { initMyList } = this.props;
const { initMyList, checkSoftwareVersion } = this.props;
initMyList();
console.log('Loading software version');
checkSoftwareVersion();
}
public componentWillReceiveProps(nextProps) {
const {updateHistory} = this.props;
if (this.props.location !== null && nextProps.location !== null) {
......@@ -87,6 +91,7 @@ const mapDispatchToProps = (dispatch) => bindActionCreators({
loadCrops,
initMyList,
serverInfoRequest,
checkSoftwareVersion,
}, dispatch);
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(App));
import * as React from 'react';
import Reload from '@material-ui/icons/Refresh';
const PageReloadButton = () => (
<Reload style={ {cursor: 'pointer'} } onClick={ () => location.reload() }/>
);
export default PageReloadButton;
......@@ -5,6 +5,7 @@ import Snackbar_ from '@material-ui/core/Snackbar';
interface ISnacks {
snack: string;
button?: any;
}
/// Based on example from https://material-ui.com/demos/snackbars/#consecutive-snackbars
......@@ -70,8 +71,25 @@ class Snackbar extends React.Component<ISnacks, any> {
this.processQueue();
}
private renderContent = () => {
const {messageInfo: {message} } = this.state;
const { button: renderButton } = this.props;
if (!renderButton) {
return (<span id="message-id">{ message }</span>);
}
return (
<span id="message-id" style={ {display: 'flex', alignItems: 'center', justifyContent: 'space-between', minWidth: '285px'} }>
{ message } { renderButton() }
</span>
);
}
public render() {
const { message, key } = this.state.messageInfo;
const { key } = this.state.messageInfo;
const snackContent = this.renderContent();
return (
<Snackbar_
......@@ -82,7 +100,7 @@ class Snackbar extends React.Component<ISnacks, any> {
onClose={ this.handleClose }
onExited={ this.handleExited }
ContentProps={ { 'aria-describedby': 'message-id' } }
message={ <span id="message-id">{ message }</span> }
message={ snackContent }
/>
);
}
......@@ -90,6 +108,7 @@ class Snackbar extends React.Component<ISnacks, any> {
const mapStateToProps = (state) => ({
snack: state.snackbar.content,
button: state.snackbar.button,
});
export default connect(mapStateToProps, null)(Snackbar);
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment