Add update check

Closes #338
This commit is contained in:
Ildar Kamalov 2018-09-21 15:20:41 +03:00
parent 68422b8399
commit 43fcf4117d
10 changed files with 104 additions and 5 deletions

View File

@ -14978,6 +14978,11 @@
"setimmediate": "^1.0.4"
}
},
"tiny-version-compare": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/tiny-version-compare/-/tiny-version-compare-0.9.1.tgz",
"integrity": "sha512-kYim94l7ptSmj9rqxUMkrcMCJ448CS+hwqjA7OFcRi0ISdi0zjgdSUklQ4velVVECCjCo5frU3tNZ3oSgIKzsA=="
},
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",

View File

@ -31,6 +31,7 @@
"redux-thunk": "^2.3.0",
"svg-url-loader": "^2.3.2",
"tabler-react": "^1.10.0",
"tiny-version-compare": "^0.9.1",
"whatwg-fetch": "2.0.3"
},
"devDependencies": {

View File

@ -164,6 +164,21 @@ export const getStats = () => async (dispatch) => {
}
};
export const getVersionRequest = createAction('GET_VERSION_REQUEST');
export const getVersionFailure = createAction('GET_VERSION_FAILURE');
export const getVersionSuccess = createAction('GET_VERSION_SUCCESS');
export const getVersion = () => async (dispatch) => {
dispatch(getVersionRequest());
try {
const newVersion = await apiClient.getGlobalVersion();
dispatch(getVersionSuccess(newVersion));
} catch (error) {
dispatch(addErrorToast({ error }));
dispatch(getVersionFailure());
}
};
export const getTopStatsRequest = createAction('GET_TOP_STATS_REQUEST');
export const getTopStatsFailure = createAction('GET_TOP_STATS_FAILURE');
export const getTopStatsSuccess = createAction('GET_TOP_STATS_SUCCESS');

View File

@ -31,6 +31,7 @@ export default class Api {
GLOBAL_QUERY_LOG_ENABLE = { path: 'querylog_enable', method: 'POST' };
GLOBAL_QUERY_LOG_DISABLE = { path: 'querylog_disable', method: 'POST' };
GLOBAL_SET_UPSTREAM_DNS = { path: 'set_upstream_dns', method: 'POST' };
GLOBAL_VERSION = { path: 'version.json', method: 'GET' };
restartGlobalFiltering() {
const { path, method } = this.GLOBAL_RESTART;
@ -107,6 +108,11 @@ export default class Api {
return this.makeRequest(path, method, config);
}
getGlobalVersion() {
const { path, method } = this.GLOBAL_VERSION;
return this.makeRequest(path, method);
}
// Filtering
FILTERING_STATUS = { path: 'filtering/status', method: 'GET' };
FILTERING_ENABLE = { path: 'filtering/enable', method: 'POST' };

View File

@ -15,12 +15,13 @@ import Filters from '../../containers/Filters';
import Logs from '../../containers/Logs';
import Footer from '../ui/Footer';
import Toasts from '../Toasts';
import Status from '../ui/Status';
import Update from '../ui/Update';
class App extends Component {
componentDidMount() {
this.props.getDnsStatus();
this.props.getVersion();
}
handleStatusChange = () => {
@ -29,9 +30,20 @@ class App extends Component {
render() {
const { dashboard } = this.props;
const updateAvailable =
!dashboard.processingVersions &&
dashboard.isCoreRunning &&
dashboard.isUpdateAvailable;
return (
<HashRouter hashType='noslash'>
<Fragment>
{updateAvailable &&
<Update
announcement={dashboard.announcement}
announcementUrl={dashboard.announcementUrl}
/>
}
<LoadingBar className="loading-bar" updateTime={1000} />
<Route component={Header} />
<div className="container container--wrap">
@ -65,6 +77,7 @@ App.propTypes = {
dashboard: PropTypes.object,
isCoreRunning: PropTypes.bool,
error: PropTypes.string,
getVersion: PropTypes.func,
};
export default App;

View File

@ -67,11 +67,15 @@
}
.nav-version {
padding: 16px 0;
font-size: 0.85rem;
padding: 7px 0;
font-size: 0.80rem;
text-align: right;
}
.nav-version__value {
font-weight: 600;
}
.header-brand-img {
height: 26px;
}
@ -103,7 +107,7 @@
.nav-version {
padding: 0;
font-size: 0.9rem;
font-size: 0.85rem;
}
}

View File

@ -5,7 +5,12 @@ export default function Version(props) {
const { dnsVersion, dnsAddress, dnsPort } = props;
return (
<div className="nav-version">
version {dnsVersion} / address: {dnsAddress}:{dnsPort}
<div className="nav-version__text">
version: <span className="nav-version__value">{dnsVersion}</span>
</div>
<div className="nav-version__text">
address: <span className="nav-version__value">{dnsAddress}:{dnsPort}</span>
</div>
</div>
);
}

View File

@ -0,0 +1,6 @@
.update {
position: relative;
z-index: 102;
margin-bottom: 0;
padding: 0.75rem 0;
}

View File

@ -0,0 +1,19 @@
import React from 'react';
import PropTypes from 'prop-types';
import './Update.css';
const Update = props => (
<div className="alert alert-info update">
<div className="container">
{props.announcement} <a href={props.announcementUrl} target="_blank" rel="noopener noreferrer">Click here</a> for more info.
</div>
</div>
);
Update.propTypes = {
announcement: PropTypes.string.isRequired,
announcementUrl: PropTypes.string.isRequired,
};
export default Update;

View File

@ -1,6 +1,7 @@
import { combineReducers } from 'redux';
import { handleActions } from 'redux-actions';
import { loadingBarReducer } from 'react-redux-loading-bar';
import versionCompare from 'tiny-version-compare';
import nanoid from 'nanoid';
import * as actions from '../actions';
@ -100,12 +101,36 @@ const dashboard = handleActions({
const { queryLogEnabled } = state;
return ({ ...state, queryLogEnabled: !queryLogEnabled, logStatusProcessing: false });
},
[actions.getVersionRequest]: state => ({ ...state, processingVersion: true }),
[actions.getVersionFailure]: state => ({ ...state, processingVersion: false }),
[actions.getVersionSuccess]: (state, { payload }) => {
const currentVersion = state.dnsVersion === 'undefined' ? 0 : state.dnsVersion;
if (versionCompare(currentVersion, payload.version) === -1) {
const {
announcement,
announcement_url: announcementUrl,
} = payload;
const newState = {
...state,
announcement,
announcementUrl,
isUpdateAvailable: true,
};
return newState;
}
return state;
},
}, {
processing: true,
isCoreRunning: false,
processingTopStats: true,
processingStats: true,
logStatusProcessing: false,
processingVersion: true,
});
const queryLogs = handleActions({