PLT-5589 Reload configuration when the server config changes (#301)
This commit is contained in:
parent
a36702f7d4
commit
c1318fe834
13 changed files with 88 additions and 18 deletions
|
|
@ -12,13 +12,14 @@ export function loadStorage() {
|
|||
try {
|
||||
const data = JSON.parse(await AsyncStorage.getItem('storage'));
|
||||
|
||||
const {token, url, currentTeamId, ...otherStorage} = data;
|
||||
const {token, url, serverVersion, currentTeamId, ...otherStorage} = data;
|
||||
const credentials = {token, url};
|
||||
|
||||
const currentChannelId = otherStorage[currentTeamId] ? otherStorage[currentTeamId].currentChannelId : '';
|
||||
|
||||
const actions = [
|
||||
{type: GeneralTypes.RECEIVED_APP_CREDENTIALS, data: credentials},
|
||||
{type: GeneralTypes.RECEIVED_SERVER_VERSION, data: serverVersion},
|
||||
{type: TeamsTypes.SELECT_TEAM, data: currentTeamId},
|
||||
{type: ChannelTypes.SELECT_CHANNEL, data: currentChannelId}
|
||||
];
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@
|
|||
|
||||
import {NavigationTypes} from 'app/constants';
|
||||
import Routes from 'app/navigation/routes';
|
||||
import {updateStorage} from 'app/actions/storage';
|
||||
|
||||
import Client from 'service/client';
|
||||
import {getClientConfig, getLicenseConfig, setServerVersion} from 'service/actions/general';
|
||||
import {loadMe} from 'service/actions/users';
|
||||
import {getClientConfig, getLicenseConfig} from 'service/actions/general';
|
||||
|
||||
export function goToSelectServer() {
|
||||
return async (dispatch, getState) => {
|
||||
|
|
@ -23,13 +24,21 @@ export function setStoreFromLocalData(data) {
|
|||
Client.setToken(data.token);
|
||||
Client.setUrl(data.url);
|
||||
|
||||
await getClientConfig()(dispatch, getState);
|
||||
await getLicenseConfig()(dispatch, getState);
|
||||
return loadMe()(dispatch, getState);
|
||||
};
|
||||
}
|
||||
|
||||
export function loadConfigAndLicense(serverVersion) {
|
||||
return async (dispatch, getState) => {
|
||||
getClientConfig()(dispatch, getState);
|
||||
getLicenseConfig()(dispatch, getState);
|
||||
setServerVersion(serverVersion)(dispatch, getState);
|
||||
await updateStorage(null, {serverVersion});
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
goToSelectServer,
|
||||
loadConfigAndLicense,
|
||||
setStoreFromLocalData
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,14 +3,17 @@
|
|||
|
||||
import React from 'react';
|
||||
import {AppState} from 'react-native';
|
||||
import {getTranslations} from 'service/i18n';
|
||||
import {IntlProvider} from 'react-intl';
|
||||
import {Constants} from 'service/constants';
|
||||
import {getTranslations} from 'service/i18n';
|
||||
import EventEmitter from 'service/utils/event_emitter';
|
||||
|
||||
export default class Root extends React.Component {
|
||||
static propTypes = {
|
||||
children: React.PropTypes.node,
|
||||
locale: React.PropTypes.string.isRequired,
|
||||
actions: React.PropTypes.shape({
|
||||
loadConfigAndLicense: React.PropTypes.func.isRequired,
|
||||
setAppState: React.PropTypes.func
|
||||
}).isRequired
|
||||
};
|
||||
|
|
@ -25,16 +28,22 @@ export default class Root extends React.Component {
|
|||
|
||||
componentDidMount() {
|
||||
AppState.addEventListener('change', this.handleAppStateChange);
|
||||
EventEmitter.on(Constants.CONFIG_CHANGED, this.handleConfigChanged);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
AppState.removeEventListener('change', this.handleAppStateChange);
|
||||
EventEmitter.off(Constants.CONFIG_CHANGED, this.handleConfigChanged);
|
||||
}
|
||||
|
||||
handleAppStateChange(appState) {
|
||||
this.props.actions.setAppState(appState === 'active');
|
||||
}
|
||||
|
||||
handleConfigChanged = (serverVersion) => {
|
||||
this.props.actions.loadConfigAndLicense(serverVersion);
|
||||
};
|
||||
|
||||
render() {
|
||||
const locale = this.props.locale;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import {connect} from 'react-redux';
|
|||
|
||||
import Config from 'assets/config.json';
|
||||
|
||||
import {loadConfigAndLicense} from 'app/actions/views/root';
|
||||
import {setAppState} from 'service/actions/general';
|
||||
|
||||
import Root from './root';
|
||||
|
|
@ -28,6 +29,7 @@ function mapStateToProps(state, ownProps) {
|
|||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
loadConfigAndLicense,
|
||||
setAppState
|
||||
}, dispatch)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ class Login extends Component {
|
|||
handleSuccessfulLogin: React.PropTypes.func.isRequired,
|
||||
checkMfa: React.PropTypes.func.isRequired,
|
||||
login: React.PropTypes.func.isRequired,
|
||||
getClientConfig: React.PropTypes.func.isRequired,
|
||||
getLicenseConfig: React.PropTypes.func.isRequired,
|
||||
goToMfa: React.PropTypes.func.isRequired,
|
||||
goToLoadTeam: React.PropTypes.func.isRequired
|
||||
}).isRequired,
|
||||
|
|
@ -55,11 +53,6 @@ class Login extends Component {
|
|||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.props.actions.getClientConfig();
|
||||
this.props.actions.getLicenseConfig();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.loginRequest.status === RequestStatus.STARTED && nextProps.loginRequest.status === RequestStatus.SUCCESS) {
|
||||
this.props.actions.handleSuccessfulLogin().then(this.props.actions.goToLoadTeam);
|
||||
|
|
@ -193,7 +186,7 @@ class Login extends Component {
|
|||
};
|
||||
}
|
||||
return error.message;
|
||||
}
|
||||
};
|
||||
|
||||
loginRef = (ref) => {
|
||||
this.loginId = ref;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import {bindActionCreators} from 'redux';
|
|||
|
||||
import navigationSceneConnect from '../navigationSceneConnect';
|
||||
|
||||
import {getClientConfig, getLicenseConfig} from 'service/actions/general';
|
||||
import LoginActions from 'app/actions/views/login';
|
||||
import {goToMfa, goToLoadTeam} from 'app/actions/navigation';
|
||||
import {checkMfa, login} from 'service/actions/users';
|
||||
|
|
@ -33,8 +32,6 @@ function mapDispatchToProps(dispatch) {
|
|||
...LoginActions,
|
||||
checkMfa,
|
||||
login,
|
||||
getClientConfig,
|
||||
getLicenseConfig,
|
||||
goToMfa,
|
||||
goToLoadTeam
|
||||
}, dispatch)
|
||||
|
|
|
|||
|
|
@ -73,10 +73,17 @@ export function setAppState(state) {
|
|||
};
|
||||
}
|
||||
|
||||
export function setServerVersion(serverVersion) {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch({type: GeneralTypes.RECEIVED_SERVER_VERSION, data: serverVersion}, getState);
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
getPing,
|
||||
getClientConfig,
|
||||
getLicenseConfig,
|
||||
logClientError,
|
||||
setAppState
|
||||
setAppState,
|
||||
setServerVersion
|
||||
};
|
||||
|
|
|
|||
|
|
@ -142,6 +142,9 @@ function handleEvent(msg, dispatch, getState) {
|
|||
case WebsocketEvents.TYPING:
|
||||
handleUserTypingEvent(msg, dispatch, getState);
|
||||
break;
|
||||
case WebsocketEvents.HELLO:
|
||||
handleHelloEvent(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -358,6 +361,14 @@ function handleStatusChangedEvent(msg, dispatch, getState) {
|
|||
}, getState);
|
||||
}
|
||||
|
||||
function handleHelloEvent(msg) {
|
||||
const serverVersion = msg.data.server_version;
|
||||
if (Client.serverVersion !== serverVersion) {
|
||||
Client.serverVersion = serverVersion;
|
||||
EventEmitter.emit(Constants.CONFIG_CHANGED, serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
const typingUsers = {};
|
||||
function handleUserTypingEvent(msg, dispatch, getState) {
|
||||
const state = getState();
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import EventEmitter from 'service/utils/event_emitter';
|
||||
import {Constants} from 'service/constants';
|
||||
|
||||
const HEADER_AUTH = 'Authorization';
|
||||
const HEADER_BEARER = 'BEARER';
|
||||
const HEADER_CONTENT_TYPE = 'Content-Type';
|
||||
const HEADER_REQUESTED_WITH = 'X-Requested-With';
|
||||
const HEADER_TOKEN = 'Token';
|
||||
const HEADER_X_VERSION_ID = 'X-Version-Id';
|
||||
|
||||
const CONTENT_TYPE_JSON = 'application/json';
|
||||
|
||||
|
|
@ -15,6 +19,7 @@ export default class Client {
|
|||
this.token = '';
|
||||
this.url = '';
|
||||
this.urlVersion = '/api/v3';
|
||||
this.serverVersion = '';
|
||||
|
||||
this.translations = {
|
||||
connectionError: 'There appears to be a problem with your internet connection.',
|
||||
|
|
@ -38,6 +43,10 @@ export default class Client {
|
|||
this.token = token;
|
||||
}
|
||||
|
||||
getServerVersion() {
|
||||
return this.serverVersion;
|
||||
}
|
||||
|
||||
getUrlVersion() {
|
||||
return this.urlVersion;
|
||||
}
|
||||
|
|
@ -708,6 +717,14 @@ export default class Client {
|
|||
data = await response.text();
|
||||
}
|
||||
|
||||
if (headers.has(HEADER_X_VERSION_ID)) {
|
||||
const serverVersion = headers.get(HEADER_X_VERSION_ID);
|
||||
if (this.serverVersion !== serverVersion) {
|
||||
this.serverVersion = serverVersion;
|
||||
EventEmitter.emit(Constants.CONFIG_CHANGED, serverVersion);
|
||||
}
|
||||
}
|
||||
|
||||
if (response.ok) {
|
||||
return {
|
||||
response,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
// See License.txt for license information.
|
||||
|
||||
const Constants = {
|
||||
CONFIG_CHANGED: 'config_changed',
|
||||
|
||||
POST_CHUNK_SIZE: 60,
|
||||
PROFILE_CHUNK_SIZE: 100,
|
||||
CHANNELS_CHUNK_SIZE: 50,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ const GeneralTypes = keyMirror({
|
|||
PING_SUCCESS: null,
|
||||
PING_FAILURE: null,
|
||||
|
||||
RECEIVED_SERVER_VERSION: null,
|
||||
|
||||
CLIENT_CONFIG_REQUEST: null,
|
||||
CLIENT_CONFIG_SUCCESS: null,
|
||||
CLIENT_CONFIG_FAILURE: null,
|
||||
|
|
|
|||
|
|
@ -48,9 +48,21 @@ function credentials(state = {}, action) {
|
|||
}
|
||||
}
|
||||
|
||||
function serverVersion(state = '', action) {
|
||||
switch (action.type) {
|
||||
case GeneralTypes.RECEIVED_SERVER_VERSION:
|
||||
return action.data;
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return '';
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
appState,
|
||||
credentials,
|
||||
config,
|
||||
license
|
||||
license,
|
||||
serverVersion
|
||||
});
|
||||
|
|
|
|||
|
|
@ -75,4 +75,12 @@ describe('Actions.General', () => {
|
|||
// Check a few basic fields since they may change over time
|
||||
assert.notStrictEqual(licenseConfig.IsLicensed, undefined);
|
||||
});
|
||||
|
||||
it('setServerVersion', async () => {
|
||||
const version = '3.7.0';
|
||||
await Actions.setServerVersion(version)(store.dispatch, store.getState);
|
||||
|
||||
const {serverVersion} = store.getState().entities.general;
|
||||
assert.deepEqual(serverVersion, version);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue