Initial Redux Store (#84)
* Moved SelectServer view state into store * Moved view state for Login to stores * Renamed RequestStatus values * Merged duplicated view state for login * initial redux store * Fix eslint * user store and force logout when necessary * channel store * address feedback * Revert naming the property of data
This commit is contained in:
parent
74c02789ee
commit
9125d0cac2
89 changed files with 3681 additions and 1653 deletions
|
|
@ -65,7 +65,6 @@
|
|||
"linebreak-style": 2,
|
||||
"lines-around-comment": [2, { "beforeBlockComment": true, "beforeLineComment": true, "allowBlockStart": true, "allowBlockEnd": true }],
|
||||
"max-lines": [1, {"max": 450, "skipBlankLines": true, "skipComments": false}],
|
||||
"max-nested-callbacks": [1, {"max":1}],
|
||||
"max-nested-callbacks": [2, {"max":2}],
|
||||
"max-statements-per-line": [2, {"max": 1}],
|
||||
"multiline-ternary": [1, "never"],
|
||||
|
|
@ -148,7 +147,7 @@
|
|||
"no-template-curly-in-string": 2,
|
||||
"no-ternary": 0,
|
||||
"no-this-before-super": 2,
|
||||
"no-throw-literal": 2,
|
||||
"no-throw-literal": 0,
|
||||
"no-trailing-spaces": [2, { "skipBlankLines": false }],
|
||||
"no-undef-init": 2,
|
||||
"no-undefined": 2,
|
||||
|
|
|
|||
|
|
@ -1,24 +1,7 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import {AppRegistry} from 'react-native';
|
||||
import configureStore from 'store/configureStore.js';
|
||||
|
||||
import {Provider} from 'react-redux';
|
||||
import RootContainer from 'containers/root_container.js';
|
||||
|
||||
const store = configureStore();
|
||||
|
||||
class Mattermost extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<RootContainer/>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
import Mattermost from 'mattermost';
|
||||
|
||||
AppRegistry.registerComponent('Mattermost', () => Mattermost);
|
||||
|
|
|
|||
19
index.ios.js
19
index.ios.js
|
|
@ -1,24 +1,7 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import {AppRegistry} from 'react-native';
|
||||
import configureStore from 'store/configureStore.js';
|
||||
|
||||
import {Provider} from 'react-redux';
|
||||
import RootContainer from 'containers/root_container.js';
|
||||
|
||||
const store = configureStore();
|
||||
|
||||
class Mattermost extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<RootContainer/>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
import Mattermost from 'mattermost';
|
||||
|
||||
AppRegistry.registerComponent('Mattermost', () => Mattermost);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
"babel-preset-es2015": "6.18.0",
|
||||
"intl": "1.2.5",
|
||||
"isomorphic-fetch": "2.2.1",
|
||||
"keymirror": "0.1.1",
|
||||
"lodash": "4.16.4",
|
||||
"react": "15.3.2",
|
||||
"react-addons-pure-render-mixin": "15.3.2",
|
||||
|
|
|
|||
|
|
@ -1,30 +1,479 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {ChannelTypes} from 'constants';
|
||||
import {Constants, ChannelTypes, UsersTypes} from 'constants';
|
||||
import {forceLogoutIfNecessary} from './helpers';
|
||||
import {batchActions} from 'redux-batched-actions';
|
||||
import Client from 'client/client_instance.js';
|
||||
import Client from 'client';
|
||||
|
||||
export function createChannel(channel, userId) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.CREATE_CHANNEL_REQUEST
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CHANNEL_MEMBERS_REQUEST
|
||||
}
|
||||
]), getState);
|
||||
|
||||
const created = await Client.createChannel(channel);
|
||||
const member = {
|
||||
channel_id: created.id,
|
||||
user_id: userId,
|
||||
roles: `${Constants.CHANNEL_USER_ROLE} ${Constants.CHANNEL_ADMIN_ROLE}`,
|
||||
last_viewed_at: 0,
|
||||
msg_count: 0,
|
||||
mention_count: 0,
|
||||
notify_props: {desktop: 'default', mark_unread: 'all'},
|
||||
last_update_at: created.create_at
|
||||
};
|
||||
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_CHANNEL,
|
||||
data: created
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CREATE_CHANNEL_SUCCESS
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_MY_CHANNEL_MEMBER,
|
||||
data: member
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CHANNEL_MEMBERS_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.CREATE_CHANNEL_FAILURE,
|
||||
error
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CHANNEL_MEMBERS_FAILURE,
|
||||
error
|
||||
}
|
||||
]), getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function createDirectChannel(userId, otherUserId) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.CREATE_CHANNEL_REQUEST
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CHANNEL_MEMBERS_REQUEST
|
||||
},
|
||||
{
|
||||
type: UsersTypes.PROFILES_REQUEST
|
||||
}
|
||||
]), getState);
|
||||
|
||||
const created = await Client.createDirectChannel(otherUserId);
|
||||
const profile = await Client.getUser(otherUserId);
|
||||
const member = {
|
||||
channel_id: created.id,
|
||||
user_id: userId,
|
||||
roles: `${Constants.CHANNEL_USER_ROLE} ${Constants.CHANNEL_ADMIN_ROLE}`,
|
||||
last_viewed_at: 0,
|
||||
msg_count: 0,
|
||||
mention_count: 0,
|
||||
notify_props: {desktop: 'default', mark_unread: 'all'},
|
||||
last_update_at: created.create_at
|
||||
};
|
||||
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_CHANNEL,
|
||||
data: created
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CREATE_CHANNEL_SUCCESS
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_MY_CHANNEL_MEMBER,
|
||||
data: member
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CHANNEL_MEMBERS_SUCCESS
|
||||
},
|
||||
{
|
||||
type: UsersTypes.RECEIVED_PROFILES,
|
||||
data: {[profile.id]: profile}
|
||||
},
|
||||
{
|
||||
type: UsersTypes.PROFILES_SUCCESS
|
||||
},
|
||||
{
|
||||
type: UsersTypes.RECEIVED_PREFERENCE,
|
||||
data: {category: Constants.CATEGORY_DIRECT_CHANNEL_SHOW, name: otherUserId, value: 'true'}
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.CREATE_CHANNEL_FAILURE,
|
||||
error
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CHANNEL_MEMBERS_FAILURE,
|
||||
error
|
||||
},
|
||||
{
|
||||
type: UsersTypes.PROFILES_FAILURE
|
||||
}
|
||||
]), getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function updateChannel(channel) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: ChannelTypes.UPDATE_CHANNEL_REQUEST}, getState);
|
||||
|
||||
const updated = await Client.updateChannel(channel);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_CHANNEL,
|
||||
data: updated
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.UPDATE_CHANNEL_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: ChannelTypes.UPDATE_CHANNEL_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function updateChannelNotifyProps(userId, teamId, channelId, props) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: ChannelTypes.NOTIFY_PROPS_REQUEST}, getState);
|
||||
|
||||
const data = {
|
||||
user_id: userId,
|
||||
channel_id: channelId,
|
||||
...props
|
||||
};
|
||||
|
||||
const notifyProps = await Client.updateChannelNotifyProps(teamId, data);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_CHANNEL_PROPS,
|
||||
data: notifyProps,
|
||||
channel_id: channelId
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.NOTIFY_PROPS_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: ChannelTypes.NOTIFY_PROPS_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function getChannel(teamId, channelId) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: ChannelTypes.CHANNEL_REQUEST}, getState);
|
||||
|
||||
const data = await Client.getChannel(teamId, channelId);
|
||||
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_CHANNEL,
|
||||
data: data.channel
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CHANNEL_SUCCESS
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_MY_CHANNEL_MEMBER,
|
||||
data: data.member
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: ChannelTypes.CHANNELS_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchMyChannelsAndMembers(teamId) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.CHANNELS_REQUEST
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CHANNEL_MEMBERS_REQUEST
|
||||
}
|
||||
]), getState);
|
||||
|
||||
const channels = Client.getChannels(teamId);
|
||||
const channelMembers = Client.getMyChannelMembers(teamId);
|
||||
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.CHANNELS_RECEIVED,
|
||||
teamId,
|
||||
channels: await channels
|
||||
type: ChannelTypes.RECEIVED_CHANNELS,
|
||||
data: await channels
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CHANNEL_MEMBERS_RECEIVED,
|
||||
teamId,
|
||||
channelMembers: await channelMembers
|
||||
type: ChannelTypes.CHANNELS_SUCCESS
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_MY_CHANNEL_MEMBERS,
|
||||
data: await channelMembers
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CHANNEL_MEMBERS_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.CHANNELS_FAILURE,
|
||||
error
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CHANNEL_MEMBERS_FAILURE,
|
||||
error
|
||||
}
|
||||
]), getState);
|
||||
} catch (err) {
|
||||
console.error(err); // eslint-disable-line no-console
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function leaveChannel(teamId, channelId) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: ChannelTypes.LEAVE_CHANNEL_REQUEST}, getState);
|
||||
|
||||
await Client.leaveChannel(teamId, channelId);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.LEAVE_CHANNEL,
|
||||
channel_id: channelId
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.LEAVE_CHANNEL_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: ChannelTypes.LEAVE_CHANNEL_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function joinChannel(userId, teamId, channelId, channelName) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: ChannelTypes.JOIN_CHANNEL_REQUEST}, getState);
|
||||
|
||||
let channel;
|
||||
if (channelId) {
|
||||
channel = await Client.joinChannel(teamId, channelId);
|
||||
} else if (channelName) {
|
||||
channel = await Client.joinChannelByName(teamId, channelName);
|
||||
}
|
||||
|
||||
const channelMember = {
|
||||
channel_id: channel.id,
|
||||
user_id: userId,
|
||||
roles: `${Constants.CHANNEL_USER_ROLE}`,
|
||||
last_viewed_at: 0,
|
||||
msg_count: 0,
|
||||
mention_count: 0,
|
||||
notify_props: {desktop: 'default', mark_unread: 'all'},
|
||||
last_update_at: new Date().getTime()
|
||||
};
|
||||
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_CHANNEL,
|
||||
data: channel
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_MY_CHANNEL_MEMBER,
|
||||
data: channelMember
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.JOIN_CHANNEL_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: ChannelTypes.JOIN_CHANNEL_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function deleteChannel(teamId, channelId) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: ChannelTypes.DELETE_CHANNEL_REQUEST}, getState);
|
||||
|
||||
await Client.deleteChannel(teamId, channelId);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_CHANNEL_DELETED,
|
||||
channel_id: channelId
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.DELETE_CHANNEL_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: ChannelTypes.DELETE_CHANNEL_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function updateLastViewedAt(teamId, channelId, active) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: ChannelTypes.UPDATE_LAST_VIEWED_REQUEST}, getState);
|
||||
|
||||
// this API should return the timestamp that was set
|
||||
await Client.updateLastViewedAt(teamId, channelId, active);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_LAST_VIEWED,
|
||||
channel_id: channelId,
|
||||
last_viewed_at: new Date().getTime()
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.UPDATE_LAST_VIEWED_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: ChannelTypes.UPDATE_LAST_VIEWED_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function getMoreChannels(teamId, offset, limit = Constants.CHANNELS_CHUNK_SIZE) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: ChannelTypes.MORE_CHANNELS_REQUEST}, getState);
|
||||
|
||||
const channels = Client.getMoreChannels(teamId, offset, limit);
|
||||
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_MORE_CHANNELS,
|
||||
data: await channels
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.MORE_CHANNELS_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: ChannelTypes.MORE_CHANNELS_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function getChannelStats(teamId, channelId) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: ChannelTypes.CHANNEL_STATS_REQUEST}, getState);
|
||||
|
||||
const stat = await Client.getChannelStats(teamId, channelId);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: ChannelTypes.RECEIVED_CHANNEL_STATS,
|
||||
data: stat
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.CHANNEL_STATS_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: ChannelTypes.CHANNEL_STATS_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function addChannelMember(teamId, channelId, userId) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: ChannelTypes.ADD_CHANNEL_MEMBER_REQUEST}, getState);
|
||||
|
||||
await Client.addChannelMember(teamId, channelId, userId);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: UsersTypes.RECEIVED_PROFILE_IN_CHANNEL,
|
||||
user_id: userId
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.ADD_CHANNEL_MEMBER_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: ChannelTypes.ADD_CHANNEL_MEMBER_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function removeChannelMember(teamId, channelId, userId) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: ChannelTypes.REMOVE_CHANNEL_MEMBER_REQUEST}, getState);
|
||||
|
||||
await Client.addChannelMember(teamId, channelId, userId);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: UsersTypes.RECEIVED_PROFILE_NOT_IN_CHANNEL,
|
||||
user_id: userId
|
||||
},
|
||||
{
|
||||
type: ChannelTypes.REMOVE_CHANNEL_MEMBER_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: ChannelTypes.REMOVE_CHANNEL_MEMBER_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
createChannel,
|
||||
createDirectChannel,
|
||||
updateChannel,
|
||||
updateChannelNotifyProps,
|
||||
getChannel,
|
||||
fetchMyChannelsAndMembers,
|
||||
leaveChannel,
|
||||
joinChannel,
|
||||
deleteChannel,
|
||||
updateLastViewedAt,
|
||||
getMoreChannels,
|
||||
getChannelStats,
|
||||
addChannelMember,
|
||||
removeChannelMember
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import Client from 'client/client_instance.js';
|
||||
import Client from 'client';
|
||||
import {bindClientFunc} from './helpers.js';
|
||||
import {GeneralTypes} from 'constants';
|
||||
|
||||
|
|
@ -18,11 +18,20 @@ export function getClientConfig() {
|
|||
return bindClientFunc(
|
||||
Client.getClientConfig,
|
||||
GeneralTypes.CLIENT_CONFIG_REQUEST,
|
||||
GeneralTypes.CLIENT_CONFIG_SUCCESS,
|
||||
[GeneralTypes.CLIENT_CONFIG_RECEIVED, GeneralTypes.CLIENT_CONFIG_SUCCESS],
|
||||
GeneralTypes.CLIENT_CONFIG_FAILURE
|
||||
);
|
||||
}
|
||||
|
||||
export function getLicenseConfig() {
|
||||
return bindClientFunc(
|
||||
Client.getLicenseConfig,
|
||||
GeneralTypes.CLIENT_LICENSE_REQUEST,
|
||||
[GeneralTypes.CLIENT_LICENSE_RECEIVED, GeneralTypes.CLIENT_LICENSE_SUCCESS],
|
||||
GeneralTypes.CLIENT_LICENSE_FAILURE
|
||||
);
|
||||
}
|
||||
|
||||
export function logClientError(message, level = 'ERROR') {
|
||||
return bindClientFunc(
|
||||
Client.logClientError,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import Client from 'client';
|
||||
import {UsersTypes} from 'constants';
|
||||
const HTTP_UNAUTHORIZED = 401;
|
||||
|
||||
export async function forceLogoutIfNecessary(err, dispatch) {
|
||||
if (err.status_code === HTTP_UNAUTHORIZED && err.url.indexOf('/login') === -1) {
|
||||
await Client.logout();
|
||||
dispatch({type: UsersTypes.LOGOUT_SUCCESS});
|
||||
}
|
||||
}
|
||||
|
||||
function dispatcher(type, data, dispatch, getState) {
|
||||
if (type.indexOf('SUCCESS') === -1) { // we don't want to pass the data for the request types
|
||||
dispatch(requestSuccess(type, data), getState);
|
||||
} else {
|
||||
dispatch(requestData(type), getState);
|
||||
}
|
||||
}
|
||||
|
||||
export function requestData(type) {
|
||||
return {
|
||||
type
|
||||
|
|
@ -21,24 +40,22 @@ export function requestFailure(type, error) {
|
|||
};
|
||||
}
|
||||
|
||||
export function emptyError() {
|
||||
return {
|
||||
id: '',
|
||||
message: '',
|
||||
detailed_error: '',
|
||||
status_code: ''
|
||||
};
|
||||
}
|
||||
|
||||
export function bindClientFunc(clientFunc, request, success, failure, ...args) {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch(requestData(request), getState);
|
||||
|
||||
try {
|
||||
const data = await clientFunc(...args);
|
||||
dispatch(requestSuccess(success, data), getState);
|
||||
if (Array.isArray(success)) {
|
||||
success.forEach((s) => {
|
||||
dispatcher(s, data, dispatch, getState);
|
||||
});
|
||||
} else {
|
||||
dispatcher(success, data, dispatch, getState);
|
||||
}
|
||||
} catch (err) {
|
||||
dispatch(requestFailure(failure, err));
|
||||
forceLogoutIfNecessary(err, dispatch);
|
||||
dispatch(requestFailure(failure, err), getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {LoginTypes} from 'constants';
|
||||
import Client from 'client/client_instance';
|
||||
import {bindClientFunc} from 'actions/helpers.js';
|
||||
|
||||
export function login(loginId, password, mfaToken = '') {
|
||||
return bindClientFunc(
|
||||
Client.login,
|
||||
LoginTypes.LOGIN_REQUEST,
|
||||
LoginTypes.LOGIN_SUCCESS,
|
||||
LoginTypes.LOGIN_FAILURE,
|
||||
loginId,
|
||||
password,
|
||||
mfaToken
|
||||
);
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {LogoutTypes} from 'constants';
|
||||
import Client from 'client/client_instance';
|
||||
import {bindClientFunc} from 'actions/helpers.js';
|
||||
|
||||
export function logout() {
|
||||
return bindClientFunc(
|
||||
Client.logout,
|
||||
LogoutTypes.LOGOUT_REQUEST,
|
||||
LogoutTypes.LOGOUT_SUCCESS,
|
||||
LogoutTypes.LOGOUT_FAILURE
|
||||
);
|
||||
}
|
||||
|
|
@ -2,15 +2,15 @@
|
|||
// See License.txt for license information.
|
||||
|
||||
import {bindClientFunc} from './helpers.js';
|
||||
import Client from 'client/client_instance';
|
||||
import {PostsTypes as types} from 'constants';
|
||||
import Client from 'client';
|
||||
import {PostsTypes} from 'constants';
|
||||
|
||||
export function fetchPosts(teamId, channelId) {
|
||||
return bindClientFunc(
|
||||
Client.fetchPosts,
|
||||
types.FETCH_POSTS_REQUEST,
|
||||
types.FETCH_POSTS_SUCCESS,
|
||||
types.FETCH_POSTS_FAILURE,
|
||||
PostsTypes.FETCH_POSTS_REQUEST,
|
||||
PostsTypes.FETCH_POSTS_SUCCESS,
|
||||
PostsTypes.FETCH_POSTS_FAILURE,
|
||||
teamId,
|
||||
channelId
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@
|
|||
// See License.txt for license information.
|
||||
|
||||
import {bindClientFunc} from './helpers.js';
|
||||
import Client from 'client/client_instance';
|
||||
import Client from 'client';
|
||||
import {TeamsTypes} from 'constants';
|
||||
|
||||
export function selectTeam(team) {
|
||||
Client.setTeamId(team.id);
|
||||
return {
|
||||
type: TeamsTypes.SELECT_TEAM,
|
||||
teamId: team.id
|
||||
return async (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: TeamsTypes.SELECT_TEAM,
|
||||
teamId: team.id
|
||||
}, getState);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -17,7 +18,7 @@ export function fetchTeams() {
|
|||
return bindClientFunc(
|
||||
Client.getAllTeams,
|
||||
TeamsTypes.FETCH_TEAMS_REQUEST,
|
||||
TeamsTypes.FETCH_TEAMS_SUCCESS,
|
||||
[TeamsTypes.RECEIVED_ALL_TEAMS, TeamsTypes.FETCH_TEAMS_SUCCESS],
|
||||
TeamsTypes.FETCH_TEAMS_FAILURE
|
||||
);
|
||||
}
|
||||
|
|
|
|||
215
src/actions/users.js
Normal file
215
src/actions/users.js
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {batchActions} from 'redux-batched-actions';
|
||||
import Client from 'client';
|
||||
|
||||
// TODO: uncomment when PLT-4167 is merged
|
||||
// import {Constants, UsersTypes, TeamsTypes} from 'constants';
|
||||
import {Constants, UsersTypes} from 'constants';
|
||||
import {bindClientFunc} from 'actions/helpers';
|
||||
import {forceLogoutIfNecessary} from './helpers';
|
||||
|
||||
export function login(loginId, password, mfaToken = '') {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch({type: UsersTypes.LOGIN_REQUEST}, getState);
|
||||
Client.login(loginId, password, mfaToken).
|
||||
then(async (data) => {
|
||||
try {
|
||||
const preferences = Client.getMyPreferences();
|
||||
|
||||
// TODO: uncomment when PLT-4167 is merged
|
||||
// const teamMembers = Client.getMyTeamMembers();
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: UsersTypes.RECEIVED_ME,
|
||||
data
|
||||
},
|
||||
{
|
||||
type: UsersTypes.RECEIVED_PREFERENCES,
|
||||
data: await preferences
|
||||
},
|
||||
|
||||
// TODO: uncomment when PLT-4167 is merged
|
||||
// {
|
||||
// type: TeamsTypes.RECEIVED_MY_TEAM_MEMBERS,
|
||||
// data: await teamMembers
|
||||
// },
|
||||
{
|
||||
type: UsersTypes.LOGIN_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (err) {
|
||||
dispatch({type: UsersTypes.LOGIN_FAILURE, error: err}, getState);
|
||||
}
|
||||
}).
|
||||
catch((err) => {
|
||||
dispatch({type: UsersTypes.LOGIN_FAILURE, error: err}, getState);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
return bindClientFunc(
|
||||
Client.logout,
|
||||
UsersTypes.LOGOUT_REQUEST,
|
||||
UsersTypes.LOGOUT_SUCCESS,
|
||||
UsersTypes.LOGOUT_FAILURE,
|
||||
);
|
||||
}
|
||||
|
||||
export function getProfiles(offset, limit = Constants.PROFILE_CHUNK_SIZE) {
|
||||
return bindClientFunc(
|
||||
Client.getProfiles,
|
||||
UsersTypes.PROFILES_REQUEST,
|
||||
[UsersTypes.RECEIVED_PROFILES, UsersTypes.PROFILES_SUCCESS],
|
||||
UsersTypes.PROFILES_FAILURE,
|
||||
offset,
|
||||
limit
|
||||
);
|
||||
}
|
||||
|
||||
export function getProfilesByIds(userIds) {
|
||||
return bindClientFunc(
|
||||
Client.getProfilesByIds,
|
||||
UsersTypes.PROFILES_REQUEST,
|
||||
[UsersTypes.RECEIVED_PROFILES, UsersTypes.PROFILES_SUCCESS],
|
||||
UsersTypes.PROFILES_FAILURE,
|
||||
userIds
|
||||
);
|
||||
}
|
||||
|
||||
export function getProfilesInTeam(teamId, offset, limit = Constants.PROFILE_CHUNK_SIZE) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: UsersTypes.PROFILES_IN_TEAM_REQUEST}, getState);
|
||||
const profiles = await Client.getProfilesInTeam(teamId, offset, limit);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: UsersTypes.RECEIVED_PROFILES_IN_TEAM,
|
||||
data: profiles,
|
||||
offset,
|
||||
count: Object.keys(profiles).length
|
||||
},
|
||||
{
|
||||
type: UsersTypes.RECEIVED_PROFILES,
|
||||
data: profiles
|
||||
},
|
||||
{
|
||||
type: UsersTypes.PROFILES_IN_TEAM_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: UsersTypes.PROFILES_IN_TEAM_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function getProfilesInChannel(teamId, channelId, offset, limit = Constants.PROFILE_CHUNK_SIZE) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: UsersTypes.PROFILES_IN_CHANNEL_REQUEST}, getState);
|
||||
const profiles = await Client.getProfilesInChannel(teamId, channelId, offset, limit);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: UsersTypes.RECEIVED_PROFILES_IN_CHANNEL,
|
||||
data: profiles,
|
||||
offset,
|
||||
count: Object.keys(profiles).length
|
||||
},
|
||||
{
|
||||
type: UsersTypes.RECEIVED_PROFILES,
|
||||
data: profiles
|
||||
},
|
||||
{
|
||||
type: UsersTypes.PROFILES_IN_CHANNEL_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: UsersTypes.PROFILES_IN_CHANNEL_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function getProfilesNotInChannel(teamId, channelId, offset, limit = Constants.PROFILE_CHUNK_SIZE) {
|
||||
return async (dispatch, getState) => {
|
||||
try {
|
||||
dispatch({type: UsersTypes.PROFILES_NOT_IN_CHANNEL_REQUEST}, getState);
|
||||
const profiles = await Client.getProfilesInChannel(teamId, channelId, offset, limit);
|
||||
dispatch(batchActions([
|
||||
{
|
||||
type: UsersTypes.RECEIVED_PROFILES_NOT_IN_CHANNEL,
|
||||
data: profiles,
|
||||
offset,
|
||||
count: Object.keys(profiles).length
|
||||
},
|
||||
{
|
||||
type: UsersTypes.RECEIVED_PROFILES,
|
||||
data: profiles
|
||||
},
|
||||
{
|
||||
type: UsersTypes.PROFILES_NOT_IN_CHANNEL_SUCCESS
|
||||
}
|
||||
]), getState);
|
||||
} catch (error) {
|
||||
forceLogoutIfNecessary(error, dispatch);
|
||||
dispatch({type: UsersTypes.PROFILES_NOT_IN_CHANNEL_FAILURE, error}, getState);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function getStatusesByIds(userIds) {
|
||||
return bindClientFunc(
|
||||
Client.getStatusesByIds,
|
||||
UsersTypes.PROFILES_STATUSES_REQUEST,
|
||||
[UsersTypes.RECEIVED_STATUSES, UsersTypes.PROFILES_STATUSES_SUCCESS],
|
||||
UsersTypes.PROFILES_STATUSES_FAILURE,
|
||||
userIds
|
||||
);
|
||||
}
|
||||
|
||||
export function getSessions(userId) {
|
||||
return bindClientFunc(
|
||||
Client.getSessions,
|
||||
UsersTypes.SESSIONS_REQUEST,
|
||||
[UsersTypes.RECEIVED_SESSIONS, UsersTypes.SESSIONS_SUCCESS],
|
||||
UsersTypes.SESSIONS_FAILURE,
|
||||
userId
|
||||
);
|
||||
}
|
||||
|
||||
export function revokeSession(id) {
|
||||
return bindClientFunc(
|
||||
Client.revokeSession,
|
||||
UsersTypes.REVOKE_SESSION_REQUEST,
|
||||
[UsersTypes.RECEIVED_REVOKED_SESSION, UsersTypes.REVOKE_SESSION_SUCCESS],
|
||||
UsersTypes.REVOKE_SESSION_FAILURE,
|
||||
id
|
||||
);
|
||||
}
|
||||
|
||||
export function getAudits(userId) {
|
||||
return bindClientFunc(
|
||||
Client.getAudits,
|
||||
UsersTypes.AUDITS_REQUEST,
|
||||
[UsersTypes.RECEIVED_AUDITS, UsersTypes.AUDITS_SUCCESS],
|
||||
UsersTypes.AUDITS_FAILURE,
|
||||
userId
|
||||
);
|
||||
}
|
||||
|
||||
export default {
|
||||
login,
|
||||
logout,
|
||||
getProfiles,
|
||||
getProfilesByIds,
|
||||
getProfilesInTeam,
|
||||
getProfilesInChannel,
|
||||
getProfilesNotInChannel,
|
||||
getStatusesByIds,
|
||||
getSessions,
|
||||
revokeSession,
|
||||
getAudits
|
||||
};
|
||||
27
src/actions/views/login.js
Normal file
27
src/actions/views/login.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {UsersTypes} from 'constants';
|
||||
|
||||
export function handleLoginIdChanged(loginId) {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: UsersTypes.LOGIN_ID_CHANGED,
|
||||
loginId
|
||||
}, getState);
|
||||
};
|
||||
}
|
||||
|
||||
export function handlePasswordChanged(password) {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: UsersTypes.PASSWORD_CHANGED,
|
||||
password
|
||||
}, getState);
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
handleLoginIdChanged,
|
||||
handlePasswordChanged
|
||||
};
|
||||
17
src/actions/views/select_server.js
Normal file
17
src/actions/views/select_server.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {GeneralTypes} from 'constants';
|
||||
|
||||
export function handleServerUrlChanged(serverUrl) {
|
||||
return async (dispatch, getState) => {
|
||||
dispatch({
|
||||
type: GeneralTypes.SERVER_URL_CHANGED,
|
||||
serverUrl
|
||||
}, getState);
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
handleServerUrlChanged
|
||||
};
|
||||
|
|
@ -46,6 +46,10 @@ export default class Client {
|
|||
return `${this.url}${this.urlVersion}/teams`;
|
||||
}
|
||||
|
||||
getPreferencesRoute() {
|
||||
return `${this.url}${this.urlVersion}/preferences`;
|
||||
}
|
||||
|
||||
getTeamNeededRoute(teamId) {
|
||||
return `${this.url}${this.urlVersion}/teams/${teamId}`;
|
||||
}
|
||||
|
|
@ -120,14 +124,21 @@ export default class Client {
|
|||
`${this.getGeneralRoute()}/client_props`,
|
||||
{method: 'get'}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
getLicenseConfig = async () => {
|
||||
return this.doFetch(
|
||||
`${this.getLicenseRoute()}/client_config`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
getPing = async () => {
|
||||
return this.doFetch(
|
||||
`${this.getGeneralRoute()}/ping`,
|
||||
{method: 'get'}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
logClientError = async (message, level = 'ERROR') => {
|
||||
const body = {
|
||||
|
|
@ -139,16 +150,33 @@ export default class Client {
|
|||
`${this.getGeneralRoute()}/log_client`,
|
||||
{method: 'post', body}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// User routes
|
||||
|
||||
createUser = async (user) => {
|
||||
return this.createUserWithInvite(user);
|
||||
};
|
||||
|
||||
// TODO: add deep linking to emails so we can create accounts from within
|
||||
// the mobile app
|
||||
createUserWithInvite = async(user, data, emailHash, inviteId) => {
|
||||
let url = `${this.getUsersRoute()}/create`;
|
||||
|
||||
url += '?d=' + encodeURIComponent(data);
|
||||
|
||||
if (emailHash) {
|
||||
url += '&h=' + encodeURIComponent(emailHash);
|
||||
}
|
||||
|
||||
if (inviteId) {
|
||||
url += '&iid=' + encodeURIComponent(inviteId);
|
||||
}
|
||||
|
||||
return this.doFetch(
|
||||
`${this.getUsersRoute()}/create`,
|
||||
url,
|
||||
{method: 'post', body: JSON.stringify(user)}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
login = async (loginId, password, token = '') => {
|
||||
const body = {
|
||||
|
|
@ -167,7 +195,7 @@ export default class Client {
|
|||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
logout = async () => {
|
||||
const {response} = await this.doFetchWithResponse(
|
||||
|
|
@ -178,14 +206,125 @@ export default class Client {
|
|||
this.token = '';
|
||||
}
|
||||
return response;
|
||||
}
|
||||
};
|
||||
|
||||
updateUser = async (user) => {
|
||||
return this.doFetch(
|
||||
`${this.getUsersRoute()}/update`,
|
||||
{method: 'post', body: JSON.stringify(user)}
|
||||
);
|
||||
};
|
||||
|
||||
updatePassword = async (userId, currentPassword, newPassword) => {
|
||||
const data = {
|
||||
user_id: userId,
|
||||
current_password: currentPassword,
|
||||
new_password: newPassword
|
||||
};
|
||||
|
||||
return this.doFetch(
|
||||
`${this.getUsersRoute()}/newpassword`,
|
||||
{method: 'post', body: JSON.stringify(data)}
|
||||
);
|
||||
};
|
||||
|
||||
updateUserNotifyProps = async (notifyProps) => {
|
||||
return this.doFetch(
|
||||
`${this.getUsersRoute()}/update_notify`,
|
||||
{method: 'post', body: JSON.stringify(notifyProps)}
|
||||
);
|
||||
};
|
||||
|
||||
updateUserRoles = async (userId, newRoles) => {
|
||||
return this.doFetch(
|
||||
`${this.getUserNeededRoute(userId)}/update_roles`,
|
||||
{method: 'post', body: JSON.stringify({new_roles: newRoles})}
|
||||
);
|
||||
};
|
||||
|
||||
getMyPreferences = async () => {
|
||||
return this.doFetch(
|
||||
`${this.getPreferencesRoute()}/`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
getProfiles = async (offset, limit) => {
|
||||
return this.doFetch(
|
||||
`${this.getUsersRoute()}/${offset}/${limit}`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
getProfilesByIds = async (userIds) => {
|
||||
return this.doFetch(
|
||||
`${this.getUsersRoute()}/ids`,
|
||||
{method: 'post', body: JSON.stringify(userIds)}
|
||||
);
|
||||
};
|
||||
|
||||
getProfilesInTeam = async (teamId, offset, limit) => {
|
||||
return this.doFetch(
|
||||
`${this.getTeamNeededRoute(teamId)}/users/${offset}/${limit}`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
getProfilesInChannel = async (teamId, channelId, offset, limit) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelNeededRoute(teamId, channelId)}/users/${offset}/${limit}`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
getProfilesNotInChannel = async (teamId, channelId, offset, limit) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelNeededRoute(teamId, channelId)}/users/not_in_channel/${offset}/${limit}`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
getUser = async (userId) => {
|
||||
return this.doFetch(
|
||||
`${this.getUserNeededRoute(userId)}/get`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
getStatusesByIds = async (userIds) => {
|
||||
return this.doFetch(
|
||||
`${this.getUsersRoute()}/status/ids`,
|
||||
{method: 'post', body: JSON.stringify(userIds)}
|
||||
);
|
||||
};
|
||||
|
||||
getSessions = async (userId) => {
|
||||
return this.doFetch(
|
||||
`${this.getUserNeededRoute(userId)}/sessions`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
revokeSession = async (id) => {
|
||||
return this.doFetch(
|
||||
`${this.getUsersRoute()}/revoke_session`,
|
||||
{method: 'post', body: JSON.stringify({id})}
|
||||
);
|
||||
};
|
||||
|
||||
getAudits = async (userId) => {
|
||||
return this.doFetch(
|
||||
`${this.getUserNeededRoute(userId)}/audits`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
getInitialLoad = async () => {
|
||||
return this.doFetch(
|
||||
`${this.getUsersRoute()}/initial_load`,
|
||||
{method: 'get'}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Team routes
|
||||
|
||||
|
|
@ -194,21 +333,49 @@ export default class Client {
|
|||
`${this.getTeamsRoute()}/create`,
|
||||
{method: 'post', body: JSON.stringify(team)}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
getAllTeams = async() => {
|
||||
return this.doFetch(
|
||||
`${this.getTeamsRoute()}/all`,
|
||||
{method: 'get'}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
getMyTeamMembers = async() => {
|
||||
return this.doFetch(
|
||||
`${this.getTeamsRoute()}/members`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
getAllTeamListings = async () => {
|
||||
return this.doFetch(
|
||||
`${this.getTeamsRoute()}/all_team_listings`,
|
||||
{method: 'get'}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
addUserToTeamFromInvite = async (inviteId, data, hash) => {
|
||||
return this.doFetch(
|
||||
`${this.getTeamsRoute()}/add_user_to_team_from_invite`,
|
||||
{method: 'post', body: JSON.stringify({hash, data, invite_id: inviteId})}
|
||||
);
|
||||
};
|
||||
|
||||
addChannelMember = async (teamId, channelId, userId) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelNeededRoute(teamId, channelId)}/add`,
|
||||
{method: 'post', body: JSON.stringify({user_id: userId})}
|
||||
);
|
||||
};
|
||||
|
||||
removeChannelMember = async (teamId, channelId, userId) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelNeededRoute(teamId, channelId)}/remove`,
|
||||
{method: 'post', body: JSON.stringify({user_id: userId})}
|
||||
);
|
||||
};
|
||||
|
||||
// Channel routes
|
||||
|
||||
|
|
@ -217,21 +384,98 @@ export default class Client {
|
|||
`${this.getChannelsRoute(channel.team_id)}/create`,
|
||||
{method: 'post', body: JSON.stringify(channel)}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
createDirectChannel = async (userId) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelsRoute('fake')}/create_direct`,
|
||||
{method: 'post', body: JSON.stringify({user_id: userId})}
|
||||
);
|
||||
};
|
||||
|
||||
getChannel = async(teamId, channelId) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelNeededRoute(teamId, channelId)}/`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
getChannels = async (teamId) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelsRoute(teamId)}/`,
|
||||
{method: 'get'}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
getMyChannelMembers = async (teamId) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelsRoute(teamId)}/members`,
|
||||
{method: 'get'}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
updateChannel = async (channel) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelsRoute(channel.team_id)}/update`,
|
||||
{method: 'post', body: JSON.stringify(channel)}
|
||||
);
|
||||
};
|
||||
|
||||
updateChannelNotifyProps = async (teamId, data) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelsRoute(teamId)}/update_notify_props`,
|
||||
{method: 'post', body: JSON.stringify(data)}
|
||||
);
|
||||
};
|
||||
|
||||
leaveChannel = async(teamId, channelId) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelNeededRoute(teamId, channelId)}/leave`,
|
||||
{method: 'post'}
|
||||
);
|
||||
};
|
||||
|
||||
joinChannel = async(teamId, channelId) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelNeededRoute(teamId, channelId)}/join`,
|
||||
{method: 'post'}
|
||||
);
|
||||
};
|
||||
|
||||
joinChannelByName = async(teamId, channelName) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelNameRoute(teamId, channelName)}/join`,
|
||||
{method: 'post'}
|
||||
);
|
||||
};
|
||||
|
||||
deleteChannel = async(teamId, channelId) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelNeededRoute(teamId, channelId)}/delete`,
|
||||
{method: 'post'}
|
||||
);
|
||||
};
|
||||
|
||||
updateLastViewedAt = async(teamId, channelId, active) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelNeededRoute(teamId, channelId)}/update_last_viewed_at`,
|
||||
{method: 'post', body: JSON.stringify({active})}
|
||||
);
|
||||
};
|
||||
|
||||
getMoreChannels = async(teamId, offset, limit) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelsRoute(teamId)}/more/${offset}/${limit}`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
getChannelStats = async(teamId, channelId) => {
|
||||
return this.doFetch(
|
||||
`${this.getChannelNeededRoute(teamId, channelId)}/stats`,
|
||||
{method: 'get'}
|
||||
);
|
||||
};
|
||||
|
||||
// Post routes
|
||||
fetchPosts = (teamId, channelId, onRequest, onSuccess, onFailure) => {
|
||||
|
|
@ -242,20 +486,20 @@ export default class Client {
|
|||
onSuccess,
|
||||
onFailure
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
createPost = async (teamId, post) => {
|
||||
return this.doFetch(
|
||||
`${this.getPostsRoute(teamId, post.channel_id)}/create`,
|
||||
{method: 'post', body: JSON.stringify(post)}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
doFetch = async (url, options) => {
|
||||
const {data} = await this.doFetchWithResponse(url, options);
|
||||
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
doFetchWithResponse = async (url, options) => {
|
||||
const response = await fetch(url, this.getOptions(options));
|
||||
|
|
@ -288,6 +532,6 @@ export default class Client {
|
|||
console.error(msg); // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
throw new Error(msg);
|
||||
}
|
||||
throw {message: msg, status_code: data.status_code, url};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
|
||||
import React, {Component, PropTypes} from 'react';
|
||||
import {TouchableHighlight, Text} from 'react-native';
|
||||
import * as logoutActions from 'actions/logout';
|
||||
import {logout} from 'actions/users';
|
||||
import {RequestStatus} from 'constants';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
import {Actions as Routes} from 'react-native-router-flux';
|
||||
|
|
@ -17,8 +18,8 @@ class Logout extends Component {
|
|||
static propTypes = propTypes;
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.logout.status === 'fetching' &&
|
||||
nextProps.logout.status === 'fetched') {
|
||||
if (this.props.logout.status === RequestStatus.STARTED &&
|
||||
nextProps.logout.status === RequestStatus.SUCCESS) {
|
||||
Routes.popTo('goToSelectServer');
|
||||
}
|
||||
}
|
||||
|
|
@ -36,13 +37,13 @@ class Logout extends Component {
|
|||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
logout: state.views.logout
|
||||
logout: state.requests.users.logout
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(logoutActions, dispatch)
|
||||
actions: bindActionCreators({logout}, dispatch)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
export const CHANNEL_RECEIVED = 'mattermost/channels/channel_received';
|
||||
export const CHANNELS_RECEIVED = 'mattermost/channels/channels_received';
|
||||
|
||||
export const CHANNEL_MEMBER_RECEIVED = 'mattermost/channels/channel_member_received';
|
||||
export const CHANNEL_MEMBERS_RECEVED = 'mattermost/channels/channel_members_received';
|
||||
76
src/constants/channels.js
Normal file
76
src/constants/channels.js
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import keymirror from 'keymirror';
|
||||
|
||||
const ChannelTypes = keymirror({
|
||||
CHANNEL_REQUEST: null,
|
||||
CHANNEL_SUCCESS: null,
|
||||
CHANNEL_FAILURE: null,
|
||||
|
||||
CHANNELS_REQUEST: null,
|
||||
CHANNELS_SUCCESS: null,
|
||||
CHANNELS_FAILURE: null,
|
||||
|
||||
CHANNEL_MEMBERS_REQUEST: null,
|
||||
CHANNEL_MEMBERS_SUCCESS: null,
|
||||
CHANNEL_MEMBERS_FAILURE: null,
|
||||
|
||||
CREATE_CHANNEL_REQUEST: null,
|
||||
CREATE_CHANNEL_SUCCESS: null,
|
||||
CREATE_CHANNEL_FAILURE: null,
|
||||
|
||||
UPDATE_CHANNEL_REQUEST: null,
|
||||
UPDATE_CHANNEL_SUCCESS: null,
|
||||
UPDATE_CHANNEL_FAILURE: null,
|
||||
|
||||
NOTIFY_PROPS_REQUEST: null,
|
||||
NOTIFY_PROPS_SUCCESS: null,
|
||||
NOTIFY_PROPS_FAILURE: null,
|
||||
|
||||
LEAVE_CHANNEL_REQUEST: null,
|
||||
LEAVE_CHANNEL_SUCCESS: null,
|
||||
LEAVE_CHANNEL_FAILURE: null,
|
||||
|
||||
JOIN_CHANNEL_REQUEST: null,
|
||||
JOIN_CHANNEL_SUCCESS: null,
|
||||
JOIN_CHANNEL_FAILURE: null,
|
||||
|
||||
DELETE_CHANNEL_REQUEST: null,
|
||||
DELETE_CHANNEL_SUCCESS: null,
|
||||
DELETE_CHANNEL_FAILURE: null,
|
||||
|
||||
UPDATE_LAST_VIEWED_REQUEST: null,
|
||||
UPDATE_LAST_VIEWED_SUCCESS: null,
|
||||
UPDATE_LAST_VIEWED_FAILURE: null,
|
||||
|
||||
MORE_CHANNELS_REQUEST: null,
|
||||
MORE_CHANNELS_SUCCESS: null,
|
||||
MORE_CHANNELS_FAILURE: null,
|
||||
|
||||
CHANNEL_STATS_REQUEST: null,
|
||||
CHANNEL_STATS_SUCCESS: null,
|
||||
CHANNEL_STATS_FAILURE: null,
|
||||
|
||||
ADD_CHANNEL_MEMBER_REQUEST: null,
|
||||
ADD_CHANNEL_MEMBER_SUCCESS: null,
|
||||
ADD_CHANNEL_MEMBER_FAILURE: null,
|
||||
|
||||
REMOVE_CHANNEL_MEMBER_REQUEST: null,
|
||||
REMOVE_CHANNEL_MEMBER_SUCCESS: null,
|
||||
REMOVE_CHANNEL_MEMBER_FAILURE: null,
|
||||
|
||||
SELECTED_CHANNEL: null,
|
||||
LEAVE_CHANNEL: null,
|
||||
RECEIVED_CHANNEL: null,
|
||||
RECEIVED_CHANNELS: null,
|
||||
RECEIVED_MY_CHANNEL_MEMBERS: null,
|
||||
RECEIVED_MY_CHANNEL_MEMBER: null,
|
||||
RECEIVED_MORE_CHANNELS: null,
|
||||
RECEIVED_CHANNEL_STATS: null,
|
||||
RECEIVED_CHANNEL_PROPS: null,
|
||||
RECEIVED_CHANNEL_DELETED: null,
|
||||
RECEIVED_LAST_VIEWED: null
|
||||
});
|
||||
|
||||
export default ChannelTypes;
|
||||
15
src/constants/constants.js
Normal file
15
src/constants/constants.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
const Constants = {
|
||||
POST_CHUNK_SIZE: 60,
|
||||
PROFILE_CHUNK_SIZE: 100,
|
||||
CHANNELS_CHUNK_SIZE: 50,
|
||||
|
||||
CHANNEL_USER_ROLE: 'channel_user',
|
||||
CHANNEL_ADMIN_ROLE: 'channel_admin',
|
||||
|
||||
CATEGORY_DIRECT_CHANNEL_SHOW: 'direct_channel_show'
|
||||
};
|
||||
|
||||
export default Constants;
|
||||
|
|
@ -1,6 +1,12 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
export const DEVICE_REQUEST = 'DEVICE_REQUEST';
|
||||
export const DEVICE_SUCCESS = 'DEVICE_SUCCESS';
|
||||
export const DEVICE_FAILURE = 'DEVICE_FAILURE';
|
||||
import keymirror from 'keymirror';
|
||||
|
||||
const DeviceTypes = keymirror({
|
||||
DEVICE_REQUEST: null,
|
||||
DEVICE_SUCCESS: null,
|
||||
DEVICE_FAILURE: null
|
||||
});
|
||||
|
||||
export default DeviceTypes;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,28 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
export const PING_REQUEST = 'PING_REQUEST';
|
||||
export const PING_SUCCESS = 'PING_SUCCESS';
|
||||
export const PING_FAILURE = 'PING_FAILURE';
|
||||
import keymirror from 'keymirror';
|
||||
|
||||
export const CLIENT_CONFIG_REQUEST = 'CLIENT_CONFIG_REQUEST';
|
||||
export const CLIENT_CONFIG_SUCCESS = 'CLIENT_CONFIG_SUCCESS';
|
||||
export const CLIENT_CONFIG_FAILURE = 'CLIENT_CONFIG_FAILURE';
|
||||
const GeneralTypes = keymirror({
|
||||
PING_REQUEST: null,
|
||||
PING_SUCCESS: null,
|
||||
PING_FAILURE: null,
|
||||
|
||||
export const LOG_CLIENT_ERROR_REQUEST = 'LOG_CLIENT_ERROR_REQUEST';
|
||||
export const LOG_CLIENT_ERROR_SUCCESS = 'LOG_CLIENT_ERROR_SUCCESS';
|
||||
export const LOG_CLIENT_ERROR_FAILURE = 'LOG_CLIENT_ERROR_FAILURE';
|
||||
CLIENT_CONFIG_REQUEST: null,
|
||||
CLIENT_CONFIG_SUCCESS: null,
|
||||
CLIENT_CONFIG_FAILURE: null,
|
||||
CLIENT_CONFIG_RECEIVED: null,
|
||||
|
||||
CLIENT_LICENSE_REQUEST: null,
|
||||
CLIENT_LICENSE_SUCCESS: null,
|
||||
CLIENT_LICENSE_FAILURE: null,
|
||||
CLIENT_LICENSE_RECEIVED: null,
|
||||
|
||||
LOG_CLIENT_ERROR_REQUEST: null,
|
||||
LOG_CLIENT_ERROR_SUCCESS: null,
|
||||
LOG_CLIENT_ERROR_FAILURE: null,
|
||||
|
||||
SERVER_URL_CHANGED: null
|
||||
});
|
||||
|
||||
export default GeneralTypes;
|
||||
|
|
|
|||
|
|
@ -1,20 +1,22 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import * as ChannelTypes from './channel';
|
||||
import * as DeviceTypes from './device';
|
||||
import * as GeneralTypes from './general';
|
||||
import * as LoginTypes from './login';
|
||||
import * as LogoutTypes from './logout';
|
||||
import * as TeamsTypes from './teams';
|
||||
import * as PostsTypes from './posts';
|
||||
import Constants from './constants';
|
||||
import ChannelTypes from './channels';
|
||||
import DeviceTypes from './device';
|
||||
import GeneralTypes from './general';
|
||||
import UsersTypes from './users';
|
||||
import TeamsTypes from './teams';
|
||||
import PostsTypes from './posts';
|
||||
import RequestStatus from './request_status';
|
||||
|
||||
export {
|
||||
Constants,
|
||||
DeviceTypes,
|
||||
GeneralTypes,
|
||||
LoginTypes,
|
||||
LogoutTypes,
|
||||
UsersTypes,
|
||||
TeamsTypes,
|
||||
ChannelTypes,
|
||||
PostsTypes
|
||||
PostsTypes,
|
||||
RequestStatus
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
export const LOGIN_REQUEST = 'LOGIN_REQUEST';
|
||||
export const LOGIN_SUCCESS = 'LOGIN_SUCCESS';
|
||||
export const LOGIN_FAILURE = 'LOGIN_FAILURE';
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
export const LOGOUT_REQUEST = 'LOGOUT_REQUEST';
|
||||
export const LOGOUT_SUCCESS = 'LOGOUT_SUCCESS';
|
||||
export const LOGOUT_FAILURE = 'LOGOUT_FAILURE';
|
||||
|
|
@ -1,6 +1,22 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
export const FETCH_POSTS_REQUEST = 'FETCH_POSTS_REQUEST';
|
||||
export const FETCH_POSTS_SUCCESS = 'FETCH_POSTS_SUCCESS';
|
||||
export const FETCH_POSTS_FAILURE = 'FETCH_POSTS_FAILURE';
|
||||
import keymirror from 'keymirror';
|
||||
|
||||
const PostsTypes = keymirror({
|
||||
FETCH_POSTS_REQUEST: null,
|
||||
FETCH_POSTS_SUCCESS: null,
|
||||
FETCH_POSTS_FAILURE: null,
|
||||
|
||||
RECEIVED_POST: null,
|
||||
RECEIVED_POSTS: null,
|
||||
RECEIVED_FOCUSED_POST: null,
|
||||
RECEIVED_POST_SELECTED: null,
|
||||
RECEIVED_EDIT_POST: null,
|
||||
CREATE_POST: null,
|
||||
CREATE_COMMENT: null,
|
||||
POST_DELETED: null,
|
||||
REMOVE_POST: null
|
||||
});
|
||||
|
||||
export default PostsTypes;
|
||||
|
|
|
|||
9
src/constants/request_status.js
Normal file
9
src/constants/request_status.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
export default {
|
||||
NOT_STARTED: 'not_started',
|
||||
STARTED: 'started',
|
||||
SUCCESS: 'success',
|
||||
FAILURE: 'failure'
|
||||
};
|
||||
|
|
@ -1,8 +1,22 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
export const SELECT_TEAM = 'SELECT_TEAM';
|
||||
import keymirror from 'keymirror';
|
||||
|
||||
export const FETCH_TEAMS_REQUEST = 'FETCH_TEAMS_REQUEST';
|
||||
export const FETCH_TEAMS_SUCCESS = 'FETCH_TEAMS_SUCCESS';
|
||||
export const FETCH_TEAMS_FAILURE = 'FETCH_TEAMS_FAILURE';
|
||||
const TeamTypes = keymirror({
|
||||
FETCH_TEAMS_REQUEST: null,
|
||||
FETCH_TEAMS_SUCCESS: null,
|
||||
FETCH_TEAMS_FAILURE: null,
|
||||
|
||||
CREATED_TEAM: null,
|
||||
SELECT_TEAM: null,
|
||||
UPDATED_TEAM: null,
|
||||
RECEIVED_ALL_TEAMS: null,
|
||||
RECEIVED_MY_TEAM_MEMBERS: null,
|
||||
RECEIVED_TEAM_LISTINGS: null,
|
||||
RECEIVED_MEMBERS_IN_TEAM: null,
|
||||
RECEIVED_TEAM_STATS: null,
|
||||
LEAVE_TEAM: null
|
||||
});
|
||||
|
||||
export default TeamTypes;
|
||||
|
|
|
|||
66
src/constants/users.js
Normal file
66
src/constants/users.js
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import keymirror from 'keymirror';
|
||||
|
||||
const UserTypes = keymirror({
|
||||
LOGIN_ID_CHANGED: null,
|
||||
PASSWORD_CHANGED: null,
|
||||
|
||||
LOGIN_REQUEST: null,
|
||||
LOGIN_SUCCESS: null,
|
||||
LOGIN_FAILURE: null,
|
||||
|
||||
LOGOUT_REQUEST: null,
|
||||
LOGOUT_SUCCESS: null,
|
||||
LOGOUT_FAILURE: null,
|
||||
|
||||
PROFILES_REQUEST: null,
|
||||
PROFILES_SUCCESS: null,
|
||||
PROFILES_FAILURE: null,
|
||||
|
||||
PROFILES_IN_TEAM_REQUEST: null,
|
||||
PROFILES_IN_TEAM_SUCCESS: null,
|
||||
PROFILES_IN_TEAM_FAILURE: null,
|
||||
|
||||
PROFILES_IN_CHANNEL_REQUEST: null,
|
||||
PROFILES_IN_CHANNEL_SUCCESS: null,
|
||||
PROFILES_IN_CHANNEL_FAILURE: null,
|
||||
|
||||
PROFILES_NOT_IN_CHANNEL_REQUEST: null,
|
||||
PROFILES_NOT_IN_CHANNEL_SUCCESS: null,
|
||||
PROFILES_NOT_IN_CHANNEL_FAILURE: null,
|
||||
|
||||
PROFILES_STATUSES_REQUEST: null,
|
||||
PROFILES_STATUSES_SUCCESS: null,
|
||||
PROFILES_STATUSES_FAILURE: null,
|
||||
|
||||
SESSIONS_REQUEST: null,
|
||||
SESSIONS_SUCCESS: null,
|
||||
SESSIONS_FAILURE: null,
|
||||
|
||||
REVOKE_SESSION_REQUEST: null,
|
||||
REVOKE_SESSION_SUCCESS: null,
|
||||
REVOKE_SESSION_FAILURE: null,
|
||||
|
||||
AUDITS_REQUEST: null,
|
||||
AUDITS_SUCCESS: null,
|
||||
AUDITS_FAILURE: null,
|
||||
|
||||
RECEIVED_ME: null,
|
||||
RECEIVED_PROFILES: null,
|
||||
RECEIVED_PROFILES_IN_TEAM: null,
|
||||
RECEIVED_PROFILES_IN_CHANNEL: null,
|
||||
RECEIVED_PROFILE_IN_CHANNEL: null,
|
||||
RECEIVED_PROFILES_NOT_IN_CHANNEL: null,
|
||||
RECEIVED_PROFILE_NOT_IN_CHANNEL: null,
|
||||
RECEIVED_SESSIONS: null,
|
||||
RECEIVED_REVOKED_SESSION: null,
|
||||
RECEIVED_AUDITS: null,
|
||||
RECEIVED_STATUSES: null,
|
||||
RECEIVED_PREFERENCE: null,
|
||||
RECEIVED_PREFERENCES: null,
|
||||
DELETED_PREFERENCES: null
|
||||
});
|
||||
|
||||
export default UserTypes;
|
||||
|
|
@ -3,20 +3,20 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import Config from 'config/config.js';
|
||||
import Config from 'config';
|
||||
import {connect} from 'react-redux';
|
||||
import {loadDevice} from 'actions/device';
|
||||
import Loading from 'components/loading';
|
||||
import Routes from 'routes';
|
||||
|
||||
import {getTranslations} from 'i18n/i18n.js';
|
||||
import {getTranslations} from 'i18n';
|
||||
import {IntlProvider} from 'react-intl';
|
||||
|
||||
class RootContainer extends React.Component {
|
||||
static propTypes = {
|
||||
device: React.PropTypes.object.isRequired,
|
||||
loadDevice: React.PropTypes.func.isRequired
|
||||
}
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
|
|||
18
src/i18n/index.js
Normal file
18
src/i18n/index.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import 'intl';
|
||||
|
||||
import en from './en.json';
|
||||
import es from './es.json';
|
||||
|
||||
const DEFAULT_LOCALE = 'en';
|
||||
|
||||
const TRANSLATIONS = {
|
||||
en,
|
||||
es
|
||||
};
|
||||
|
||||
export function getTranslations(locale) {
|
||||
return TRANSLATIONS[locale] || TRANSLATIONS[DEFAULT_LOCALE];
|
||||
}
|
||||
18
src/mattermost.js
Normal file
18
src/mattermost.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {Provider} from 'react-redux';
|
||||
|
||||
import store from 'store';
|
||||
import RootContainer from 'containers/root_container.js';
|
||||
|
||||
export default class Mattermost extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<RootContainer/>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {ChannelTypes} from 'constants';
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
export function channels(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case ChannelTypes.CHANNEL_RECEIVED:
|
||||
return {
|
||||
...state,
|
||||
[action.channel.id]: action.channel
|
||||
};
|
||||
|
||||
case ChannelTypes.CHANNELS_RECEIVED: {
|
||||
const nextState = {...state};
|
||||
|
||||
for (const channel of action.channels) {
|
||||
nextState[channel.id] = channel;
|
||||
}
|
||||
|
||||
return nextState;
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export function channelIdsByTeamId(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case ChannelTypes.CHANNEL_RECEIVED: {
|
||||
const channel = action.channel;
|
||||
|
||||
return {
|
||||
...state,
|
||||
[channel.team_id]: {
|
||||
...state[channel.team_id],
|
||||
[channel.id]: channel.id
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
case ChannelTypes.CHANNELS_RECEIVED: {
|
||||
const nextState = {...state};
|
||||
|
||||
for (const channel of action.channels) {
|
||||
nextState[channel.team_id] = {
|
||||
...nextState[channel.team_id],
|
||||
[channel.id]: channel.id
|
||||
};
|
||||
}
|
||||
|
||||
return nextState;
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export function channelMembers(state = {}, action) {
|
||||
switch (action.type) {
|
||||
|
||||
case ChannelTypes.CHANNEL_MEMBER_RECEIVED: {
|
||||
const channelMember = action.channelMember;
|
||||
|
||||
return {
|
||||
...state,
|
||||
[`${channelMember.channel_id}-${channelMember.user_id}`]: channelMember
|
||||
};
|
||||
}
|
||||
|
||||
case ChannelTypes.CHANNEL_MEMBERS_RECEIVED: {
|
||||
const nextState = {...state};
|
||||
|
||||
for (const channelMember of action.channelMembers) {
|
||||
nextState[`${channelMember.channel_id}-${channelMember.user_id}`] = channelMember;
|
||||
}
|
||||
|
||||
return nextState;
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
|
||||
// A map of channel IDs to channels
|
||||
channels,
|
||||
|
||||
// A map of team IDs to pseudo-sets of channelIds
|
||||
channelIdsByTeamId,
|
||||
|
||||
// A map of "channelId-userId" to channel members
|
||||
channelMembers
|
||||
});
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {handle, initialState} from './helpers.js';
|
||||
import {DeviceTypes} from 'constants';
|
||||
export const initState = initialState();
|
||||
|
||||
export default function device(state = initState, action) {
|
||||
return handle(
|
||||
DeviceTypes.DEVICE_REQUEST,
|
||||
DeviceTypes.DEVICE_SUCCESS,
|
||||
DeviceTypes.DEVICE_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
146
src/reducers/entities/channels.js
Normal file
146
src/reducers/entities/channels.js
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {ChannelTypes, UsersTypes} from 'constants';
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
function currentId(state = '', action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return '';
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function channels(state = {}, action) {
|
||||
const nextState = {...state};
|
||||
|
||||
switch (action.type) {
|
||||
case ChannelTypes.RECEIVED_CHANNEL:
|
||||
return {
|
||||
...state,
|
||||
[action.data.id]: action.data
|
||||
};
|
||||
|
||||
case ChannelTypes.RECEIVED_CHANNELS: {
|
||||
for (const channel of action.data) {
|
||||
nextState[channel.id] = channel;
|
||||
}
|
||||
return nextState;
|
||||
}
|
||||
case ChannelTypes.LEAVE_CHANNEL:
|
||||
case ChannelTypes.RECEIVED_CHANNEL_DELETED: {
|
||||
Reflect.deleteProperty(nextState, action.channel_id);
|
||||
return nextState;
|
||||
}
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function myMembers(state = {}, action) {
|
||||
const nextState = {...state};
|
||||
|
||||
switch (action.type) {
|
||||
case ChannelTypes.RECEIVED_MY_CHANNEL_MEMBER: {
|
||||
const channelMember = action.data;
|
||||
return {
|
||||
...state,
|
||||
[channelMember.channel_id]: channelMember
|
||||
};
|
||||
}
|
||||
case ChannelTypes.RECEIVED_MY_CHANNEL_MEMBERS: {
|
||||
for (const cm of action.data) {
|
||||
nextState[cm.channel_id] = cm;
|
||||
}
|
||||
return nextState;
|
||||
}
|
||||
case ChannelTypes.RECEIVED_CHANNEL_PROPS: {
|
||||
const member = {...state[action.channel_id]};
|
||||
member.notify_props = action.data;
|
||||
|
||||
return {
|
||||
...state,
|
||||
[action.channel_id]: member
|
||||
};
|
||||
}
|
||||
case ChannelTypes.RECEIVED_LAST_VIEWED: {
|
||||
const member = {...state[action.channel_id]};
|
||||
member.last_viewed_at = action.last_viewed_at;
|
||||
|
||||
return {
|
||||
...state,
|
||||
[action.channel_id]: member
|
||||
};
|
||||
}
|
||||
case ChannelTypes.LEAVE_CHANNEL:
|
||||
case ChannelTypes.RECEIVED_CHANNEL_DELETED:
|
||||
Reflect.deleteProperty(nextState, action.channel_id);
|
||||
return nextState;
|
||||
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function moreChannels(state = {}, action) {
|
||||
const nextState = {...state};
|
||||
|
||||
switch (action.type) {
|
||||
case ChannelTypes.RECEIVED_MORE_CHANNELS: {
|
||||
for (const channel of action.data) {
|
||||
nextState[channel.id] = channel;
|
||||
}
|
||||
return nextState;
|
||||
}
|
||||
case ChannelTypes.RECEIVED_MY_CHANNEL_MEMBER: {
|
||||
const channelMember = action.data;
|
||||
Reflect.deleteProperty(nextState, channelMember.channel_id);
|
||||
return nextState;
|
||||
}
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function stats(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case ChannelTypes.RECEIVED_CHANNEL_STATS: {
|
||||
const nextState = {...state};
|
||||
const stat = action.data;
|
||||
nextState[stat.channel_id] = stat;
|
||||
|
||||
return nextState;
|
||||
}
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
|
||||
// the current selected channel
|
||||
currentId,
|
||||
|
||||
// object where every key is the channel id and has and object with the channel detail
|
||||
channels,
|
||||
|
||||
//object where every key is the channel id and has and object with the channel members detail
|
||||
myMembers,
|
||||
|
||||
// object where every key is the channel id and has a object with the channel detail where the user is not a current member
|
||||
moreChannels,
|
||||
|
||||
// object where every key is the team id and has an object with the team stats
|
||||
stats
|
||||
});
|
||||
32
src/reducers/entities/general.js
Normal file
32
src/reducers/entities/general.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
import {GeneralTypes, UsersTypes} from 'constants';
|
||||
|
||||
function config(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case GeneralTypes.CLIENT_CONFIG_RECEIVED:
|
||||
return Object.assign({}, state, action.data);
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function license(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case GeneralTypes.CLIENT_LICENSE_RECEIVED:
|
||||
return Object.assign({}, state, action.data);
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
config,
|
||||
license
|
||||
});
|
||||
136
src/reducers/entities/helpers.js
Normal file
136
src/reducers/entities/helpers.js
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
export function initialPagingState() {
|
||||
return {
|
||||
items: new Set(),
|
||||
offset: 0,
|
||||
count: 0
|
||||
};
|
||||
}
|
||||
|
||||
function isPostListNull(pl) {
|
||||
if (!pl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!pl.posts) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !pl.order;
|
||||
}
|
||||
|
||||
function makePostListNonNull(pl) {
|
||||
let postList = {...pl};
|
||||
if (!postList) {
|
||||
postList = {order: [], posts: {}};
|
||||
}
|
||||
|
||||
if (!postList.order) {
|
||||
postList.order = [];
|
||||
}
|
||||
|
||||
if (!postList.posts) {
|
||||
postList.posts = {};
|
||||
}
|
||||
|
||||
return postList;
|
||||
}
|
||||
|
||||
export function addPosts(state, action) {
|
||||
const newState = {...state};
|
||||
const newPosts = action.data;
|
||||
const id = action.channel_id;
|
||||
|
||||
if (isPostListNull(newPosts)) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (action.checkLatest) {
|
||||
const currentLatest = newState.latestPageTime[id] || 0;
|
||||
if (newPosts.order.length >= 1) {
|
||||
const newLatest = newPosts.posts[newPosts.order[0]].create_at || 0;
|
||||
if (newLatest > currentLatest) {
|
||||
newState.latestPageTime = {
|
||||
...newState.latestPageTime,
|
||||
[id]: newLatest
|
||||
};
|
||||
}
|
||||
} else if (currentLatest === 0) {
|
||||
// Mark that an empty page was received
|
||||
newState.latestPageTime = {
|
||||
...newState.latestPageTime,
|
||||
[id]: 1
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const combinedPosts = {...makePostListNonNull(newState.postsInfo[id].postList)};
|
||||
|
||||
for (const pid in newPosts.posts) {
|
||||
if (newPosts.posts.hasOwnProperty(pid)) {
|
||||
const np = newPosts.posts[pid];
|
||||
if (np.delete_at === 0) {
|
||||
combinedPosts.posts[pid] = np;
|
||||
if (combinedPosts.order.indexOf(pid) === -1 && newPosts.order.indexOf(pid) !== -1) {
|
||||
combinedPosts.order.push(pid);
|
||||
}
|
||||
} else if (combinedPosts.posts.hasOwnProperty(pid)) {
|
||||
combinedPosts.posts[pid] = {...np, state: 'DELETED', fileIds: []};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
combinedPosts.order.sort((a, b) => {
|
||||
if (combinedPosts.posts[a].create_at > combinedPosts.posts[b].create_at) {
|
||||
return -1;
|
||||
}
|
||||
if (combinedPosts.posts[a].create_at < combinedPosts.posts[b].create_at) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
newState.postsInfo = {
|
||||
...newState.postsInfo,
|
||||
[id]: {
|
||||
...newState.postsInfo[id],
|
||||
postList: combinedPosts
|
||||
}
|
||||
};
|
||||
|
||||
return newState;
|
||||
}
|
||||
|
||||
export function profilesToSet(state, action) {
|
||||
const nextState = {...state};
|
||||
if (action.offset != null && action.count != null) {
|
||||
nextState.offset = action.offset + action.count;
|
||||
nextState.count += action.count;
|
||||
}
|
||||
|
||||
nextState.items = new Set(state.items);
|
||||
Object.keys(action.data).forEach((key) => {
|
||||
nextState.items.add(key);
|
||||
});
|
||||
|
||||
return nextState;
|
||||
}
|
||||
|
||||
export function addProfileToSet(state, profileId) {
|
||||
const nextState = {...state};
|
||||
nextState.items = new Set(state.items);
|
||||
nextState.items.add(profileId);
|
||||
|
||||
return nextState;
|
||||
}
|
||||
|
||||
export function removeProfileFromSet(state, profileId) {
|
||||
const nextState = {...state};
|
||||
nextState.items = new Set(state.items);
|
||||
nextState.items.delete(profileId);
|
||||
|
||||
return nextState;
|
||||
}
|
||||
18
src/reducers/entities/index.js
Normal file
18
src/reducers/entities/index.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
import channels from './channels';
|
||||
import general from './general';
|
||||
import users from './users';
|
||||
import teams from './teams';
|
||||
import posts from './posts';
|
||||
|
||||
export default combineReducers({
|
||||
general,
|
||||
users,
|
||||
teams,
|
||||
channels,
|
||||
posts
|
||||
});
|
||||
59
src/reducers/entities/posts.js
Normal file
59
src/reducers/entities/posts.js
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {PostsTypes, UsersTypes} from 'constants';
|
||||
import {combineReducers} from 'redux';
|
||||
import {addPosts} from './helpers';
|
||||
|
||||
function selectedPostId(state = '', action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return '';
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function currentFocusedPostId(state = '', action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return '';
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function postsInfo(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case PostsTypes.FETCH_POSTS_SUCCESS:
|
||||
return addPosts(state, action);
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function latestPageTime(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
|
||||
// the current selected post
|
||||
selectedPostId,
|
||||
|
||||
// the current selected focused post (permalink view)
|
||||
currentFocusedPostId,
|
||||
|
||||
// object where every key is the channel id and has and object with the postList
|
||||
postsInfo,
|
||||
|
||||
// object where the every key is the channel id and has the timestamp of the latest post created in that channel
|
||||
latestPageTime
|
||||
});
|
||||
100
src/reducers/entities/teams.js
Normal file
100
src/reducers/entities/teams.js
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
import {TeamsTypes, UsersTypes} from 'constants';
|
||||
|
||||
function currentId(state = '', action) {
|
||||
switch (action.type) {
|
||||
case TeamsTypes.SELECT_TEAM:
|
||||
return action.teamId;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function teams(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case TeamsTypes.RECEIVED_ALL_TEAMS:
|
||||
return Object.assign({}, state, action.data);
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function myMembers(state = {}, action) {
|
||||
const nextState = {...state};
|
||||
|
||||
switch (action.type) {
|
||||
case TeamsTypes.RECEIVED_MY_TEAM_MEMBERS: {
|
||||
const members = action.data;
|
||||
for (const m of members) {
|
||||
nextState[m.team_id] = m;
|
||||
}
|
||||
return nextState;
|
||||
}
|
||||
case TeamsTypes.LEAVE_TEAM: {
|
||||
const data = action.team;
|
||||
Reflect.deleteProperty(nextState, data.team_id);
|
||||
return nextState;
|
||||
}
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function membersInTeam(state = {}, action) {
|
||||
switch (action.type) {
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function membersNotInTeam(state = {}, action) {
|
||||
switch (action.type) {
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function stats(state = {}, action) {
|
||||
switch (action.type) {
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function openTeamIds(state = new Set(), action) {
|
||||
switch (action.type) {
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
|
||||
// the current selected team
|
||||
currentId,
|
||||
|
||||
// object where every key is the team id and has and object with the team detail
|
||||
teams,
|
||||
|
||||
//object where every key is the team id and has and object with the team members detail
|
||||
myMembers,
|
||||
|
||||
// object where every key is the team id and has a Set of user ids that are members in the team
|
||||
membersInTeam,
|
||||
|
||||
// object where every key is the team id and has a Set of user ids that aren't members in the team
|
||||
membersNotInTeam,
|
||||
|
||||
// object where every key is the team id and has an object with the team stats
|
||||
stats,
|
||||
|
||||
// Set with the team ids the user is not a member of
|
||||
openTeamIds
|
||||
});
|
||||
216
src/reducers/entities/users.js
Normal file
216
src/reducers/entities/users.js
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
import {UsersTypes} from 'constants';
|
||||
import {initialPagingState, profilesToSet, addProfileToSet, removeProfileFromSet} from './helpers';
|
||||
|
||||
function currentId(state = '', action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.RECEIVED_ME:
|
||||
return action.data.id;
|
||||
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return '';
|
||||
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
function myPreferences(state = {}, action) {
|
||||
const nextState = {...state};
|
||||
|
||||
switch (action.type) {
|
||||
case UsersTypes.RECEIVED_PREFERENCES: {
|
||||
const preferences = action.data;
|
||||
for (const p of preferences) {
|
||||
nextState[`${p.category}--${p.name}`] = p.value;
|
||||
}
|
||||
return nextState;
|
||||
}
|
||||
case UsersTypes.RECEIVED_PREFERENCE: {
|
||||
const p = action.data;
|
||||
nextState[`${p.category}--${p.name}`] = p.value;
|
||||
return nextState;
|
||||
}
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function mySessions(state = [], action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.RECEIVED_SESSIONS:
|
||||
return [...action.data];
|
||||
|
||||
case UsersTypes.RECEIVED_REVOKED_SESSION: {
|
||||
let index = -1;
|
||||
const length = state.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (state[i].id === action.data.id) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index > -1) {
|
||||
return state.slice(0, index).concat(state.slice(index + 1));
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return [];
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function myAudits(state = [], action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.RECEIVED_AUDITS:
|
||||
return [...action.data];
|
||||
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return [];
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function profiles(state = {items: {}, offset: 0, count: 0}, action) {
|
||||
const nextState = {...state};
|
||||
|
||||
switch (action.type) {
|
||||
case UsersTypes.RECEIVED_ME: {
|
||||
const id = action.data.id;
|
||||
nextState.items = {
|
||||
...nextState.items,
|
||||
[id]: {
|
||||
...nextState.items[id],
|
||||
...action.data
|
||||
}
|
||||
};
|
||||
|
||||
return nextState;
|
||||
}
|
||||
case UsersTypes.RECEIVED_PROFILES:
|
||||
if (action.offset != null && action.count != null) {
|
||||
nextState.offset = action.offset + action.count;
|
||||
nextState.count += action.count;
|
||||
}
|
||||
nextState.items = Object.assign({}, nextState.items, action.data);
|
||||
|
||||
return nextState;
|
||||
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {items: {}, offset: 0, count: 0};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function profilesInTeam(state = initialPagingState(), action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.RECEIVED_PROFILES_IN_TEAM:
|
||||
return profilesToSet(state, action);
|
||||
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return initialPagingState();
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function profilesInChannel(state = initialPagingState(), action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.RECEIVED_PROFILE_IN_CHANNEL:
|
||||
return addProfileToSet(state, action.user_id);
|
||||
|
||||
case UsersTypes.RECEIVED_PROFILES_IN_CHANNEL:
|
||||
return profilesToSet(state, action);
|
||||
|
||||
case UsersTypes.RECEIVED_PROFILE_NOT_IN_CHANNEL:
|
||||
return removeProfileFromSet(state, action.user_id);
|
||||
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return initialPagingState();
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function profilesNotInChannel(state = initialPagingState(), action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.RECEIVED_PROFILE_NOT_IN_CHANNEL:
|
||||
return addProfileToSet(state, action.user_id);
|
||||
|
||||
case UsersTypes.RECEIVED_PROFILES_NOT_IN_CHANNEL:
|
||||
return profilesToSet(state, action);
|
||||
|
||||
case UsersTypes.RECEIVED_PROFILE_IN_CHANNEL:
|
||||
return removeProfileFromSet(state, action.user_id);
|
||||
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return initialPagingState();
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function statuses(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.RECEIVED_STATUSES: {
|
||||
const nextState = {...state};
|
||||
return Object.assign({}, nextState, action.data);
|
||||
}
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
|
||||
// the current selected user
|
||||
currentId,
|
||||
|
||||
// object where the key is the category-name and has the corresponding value
|
||||
myPreferences,
|
||||
|
||||
// array with the user's sessions
|
||||
mySessions,
|
||||
|
||||
// array with the user's audits
|
||||
myAudits,
|
||||
|
||||
// object containing items, count and offset where items is an object where every key is a user id
|
||||
// and has an object with the users details
|
||||
profiles,
|
||||
|
||||
// object containing items, count and offset where items is an object where every key is a user id
|
||||
// and has a Set with the users id that are members of the team
|
||||
profilesInTeam,
|
||||
|
||||
// object containing items, count and offset where items is an object where every key is a user id
|
||||
// and has a Set with the users id that are members of the channel
|
||||
profilesInChannel,
|
||||
|
||||
// object containing items, count and offset where items is an object where every key is a user id
|
||||
// and has a Set with the users id that are members of the channel
|
||||
profilesNotInChannel,
|
||||
|
||||
// object where every key is the user id and has a value with the current status of each user
|
||||
statuses
|
||||
});
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
import {GeneralTypes} from 'constants';
|
||||
|
||||
function ping(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case GeneralTypes.PING_REQUEST:
|
||||
return {
|
||||
...action.data,
|
||||
loading: true
|
||||
};
|
||||
case GeneralTypes.PING_SUCCESS:
|
||||
return {
|
||||
...action.data,
|
||||
loading: false,
|
||||
error: null
|
||||
};
|
||||
case GeneralTypes.PING_FAILURE:
|
||||
return {
|
||||
...action.data,
|
||||
loading: false,
|
||||
error: action.error
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function clientConfig(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case GeneralTypes.CLIENT_CONFIG_REQUEST:
|
||||
return {
|
||||
...action.data,
|
||||
loading: true
|
||||
};
|
||||
case GeneralTypes.CLIENT_CONFIG_SUCCESS:
|
||||
return {
|
||||
...action.data,
|
||||
loading: false,
|
||||
error: null
|
||||
};
|
||||
case GeneralTypes.CLIENT_CONFIG_FAILURE:
|
||||
return {
|
||||
...action.data,
|
||||
loading: false,
|
||||
error: action.error
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
ping,
|
||||
clientConfig
|
||||
});
|
||||
|
|
@ -3,28 +3,12 @@
|
|||
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
import channel from './channel.js';
|
||||
import device from './device.js';
|
||||
import general from './general.js';
|
||||
import login from './login';
|
||||
import logout from './logout';
|
||||
import teams from './teams';
|
||||
import posts from './posts';
|
||||
|
||||
const entities = combineReducers({
|
||||
channel,
|
||||
general,
|
||||
teams,
|
||||
posts
|
||||
});
|
||||
|
||||
const views = combineReducers({
|
||||
device,
|
||||
login,
|
||||
logout
|
||||
});
|
||||
import entities from './entities';
|
||||
import requests from './requests';
|
||||
import views from './views';
|
||||
|
||||
export default combineReducers({
|
||||
entities,
|
||||
requests,
|
||||
views
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {LoginTypes, LogoutTypes} from 'constants';
|
||||
|
||||
export const initState = {
|
||||
status: 'not fetched',
|
||||
error: null
|
||||
};
|
||||
|
||||
export default function reduceLogin(state = initState, action) {
|
||||
switch (action.type) {
|
||||
|
||||
case LoginTypes.LOGIN_REQUEST:
|
||||
return {
|
||||
...state,
|
||||
status: 'fetching',
|
||||
error: null
|
||||
};
|
||||
case LoginTypes.LOGIN_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
status: 'fetched'
|
||||
};
|
||||
case LoginTypes.LOGIN_FAILURE:
|
||||
return {
|
||||
...state,
|
||||
status: 'failed',
|
||||
error: action.error
|
||||
};
|
||||
|
||||
case LogoutTypes.LOGOUT_SUCCESS:
|
||||
return initState;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {LogoutTypes} from 'constants';
|
||||
|
||||
export const initState = {
|
||||
status: 'not fetched',
|
||||
error: null
|
||||
};
|
||||
|
||||
export default function reduceLogout(state = initState, action) {
|
||||
switch (action.type) {
|
||||
case LogoutTypes.LOGOUT_REQUEST:
|
||||
return {...state,
|
||||
status: 'fetching',
|
||||
error: null
|
||||
};
|
||||
case LogoutTypes.LOGOUT_SUCCESS:
|
||||
return {...state,
|
||||
status: 'fetched'
|
||||
};
|
||||
case LogoutTypes.LOGOUT_FAILURE:
|
||||
return {...state,
|
||||
status: 'failed',
|
||||
error: action.error
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {PostsTypes, LogoutTypes} from 'constants';
|
||||
|
||||
export const initState = {
|
||||
status: 'not fetched',
|
||||
error: null,
|
||||
data: {}
|
||||
};
|
||||
|
||||
export default function reducePosts(state = initState, action) {
|
||||
switch (action.type) {
|
||||
|
||||
case PostsTypes.FETCH_POSTS_REQUEST:
|
||||
return {...state,
|
||||
status: 'fetching',
|
||||
error: null
|
||||
};
|
||||
case PostsTypes.FETCH_POSTS_SUCCESS:
|
||||
return {...state,
|
||||
status: 'fetched',
|
||||
data: action.data.posts
|
||||
};
|
||||
case PostsTypes.FETCH_POSTS_FAILURE:
|
||||
return {...state,
|
||||
status: 'failed',
|
||||
error: action.error
|
||||
};
|
||||
|
||||
case LogoutTypes.LOGOUT_SUCCESS:
|
||||
return initState;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
164
src/reducers/requests/channels.js
Normal file
164
src/reducers/requests/channels.js
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {handleRequest, initialRequestState} from './helpers';
|
||||
import {ChannelTypes} from 'constants';
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
function getChannel(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.CHANNEL_REQUEST,
|
||||
ChannelTypes.CHANNEL_SUCCESS,
|
||||
ChannelTypes.CHANNEL_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function getChannels(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.CHANNELS_REQUEST,
|
||||
ChannelTypes.CHANNELS_SUCCESS,
|
||||
ChannelTypes.CHANNELS_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function myMembers(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.CHANNEL_MEMBERS_REQUEST,
|
||||
ChannelTypes.CHANNEL_MEMBERS_SUCCESS,
|
||||
ChannelTypes.CHANNEL_MEMBERS_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function createChannel(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.CREATE_CHANNEL_REQUEST,
|
||||
ChannelTypes.CREATE_CHANNEL_SUCCESS,
|
||||
ChannelTypes.CREATE_CHANNEL_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function updateChannel(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.UPDATE_CHANNEL_REQUEST,
|
||||
ChannelTypes.UPDATE_CHANNEL_SUCCESS,
|
||||
ChannelTypes.UPDATE_CHANNEL_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function updateChannelNotifyProps(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.NOTIFY_PROPS_REQUEST,
|
||||
ChannelTypes.NOTIFY_PROPS_SUCCESS,
|
||||
ChannelTypes.NOTIFY_PROPS_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function leaveChannel(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.LEAVE_CHANNEL_REQUEST,
|
||||
ChannelTypes.LEAVE_CHANNEL_SUCCESS,
|
||||
ChannelTypes.LEAVE_CHANNEL_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function joinChannel(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.JOIN_CHANNEL_REQUEST,
|
||||
ChannelTypes.JOIN_CHANNEL_SUCCESS,
|
||||
ChannelTypes.JOIN_CHANNEL_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function deleteChannel(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.DELETE_CHANNEL_REQUEST,
|
||||
ChannelTypes.DELETE_CHANNEL_SUCCESS,
|
||||
ChannelTypes.DELETE_CHANNEL_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function updateLastViewedAt(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.UPDATE_LAST_VIEWED_REQUEST,
|
||||
ChannelTypes.UPDATE_LAST_VIEWED_SUCCESS,
|
||||
ChannelTypes.UPDATE_LAST_VIEWED_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function getMoreChannels(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.MORE_CHANNELS_REQUEST,
|
||||
ChannelTypes.MORE_CHANNELS_SUCCESS,
|
||||
ChannelTypes.MORE_CHANNELS_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function getChannelStats(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.CHANNEL_STATS_REQUEST,
|
||||
ChannelTypes.CHANNEL_STATS_SUCCESS,
|
||||
ChannelTypes.CHANNEL_STATS_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function addChannelMember(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.ADD_CHANNEL_MEMBER_REQUEST,
|
||||
ChannelTypes.ADD_CHANNEL_MEMBER_SUCCESS,
|
||||
ChannelTypes.ADD_CHANNEL_MEMBER_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function removeChannelMember(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
ChannelTypes.REMOVE_CHANNEL_MEMBER_REQUEST,
|
||||
ChannelTypes.REMOVE_CHANNEL_MEMBER_SUCCESS,
|
||||
ChannelTypes.REMOVE_CHANNEL_MEMBER_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
getChannel,
|
||||
getChannels,
|
||||
myMembers,
|
||||
createChannel,
|
||||
updateChannel,
|
||||
updateChannelNotifyProps,
|
||||
leaveChannel,
|
||||
joinChannel,
|
||||
deleteChannel,
|
||||
updateLastViewedAt,
|
||||
getMoreChannels,
|
||||
getChannelStats,
|
||||
addChannelMember,
|
||||
removeChannelMember
|
||||
});
|
||||
42
src/reducers/requests/general.js
Normal file
42
src/reducers/requests/general.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
import {GeneralTypes} from 'constants';
|
||||
import {handleRequest, initialRequestState} from './helpers';
|
||||
|
||||
function server(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
GeneralTypes.PING_REQUEST,
|
||||
GeneralTypes.PING_SUCCESS,
|
||||
GeneralTypes.PING_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function config(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
GeneralTypes.CLIENT_CONFIG_REQUEST,
|
||||
GeneralTypes.CLIENT_CONFIG_SUCCESS,
|
||||
GeneralTypes.CLIENT_CONFIG_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function license(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
GeneralTypes.CLIENT_LICENSE_REQUEST,
|
||||
GeneralTypes.CLIENT_LICENSE_SUCCESS,
|
||||
GeneralTypes.CLIENT_LICENSE_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
server,
|
||||
config,
|
||||
license
|
||||
});
|
||||
|
|
@ -1,38 +1,37 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
export function initialState() {
|
||||
import {RequestStatus} from 'constants';
|
||||
|
||||
export function initialRequestState() {
|
||||
return {
|
||||
data: {},
|
||||
loading: false,
|
||||
status: RequestStatus.NOT_STARTED,
|
||||
error: null
|
||||
};
|
||||
}
|
||||
|
||||
export function handle(REQUEST, SUCCESS, FAILURE, state, action) {
|
||||
export function handleRequest(REQUEST, SUCCESS, FAILURE, state, action) {
|
||||
switch (action.type) {
|
||||
|
||||
case REQUEST:
|
||||
return {
|
||||
...state,
|
||||
loading: true
|
||||
status: RequestStatus.STARTED
|
||||
};
|
||||
|
||||
case SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
status: RequestStatus.SUCCESS,
|
||||
data: action.data,
|
||||
loading: false,
|
||||
error: null
|
||||
};
|
||||
|
||||
case FAILURE:
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
status: RequestStatus.FAILURE,
|
||||
error: action.error
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/reducers/requests/index.js
Normal file
16
src/reducers/requests/index.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
import general from './general';
|
||||
import channels from './channels';
|
||||
import users from './users';
|
||||
import teams from './teams';
|
||||
|
||||
export default combineReducers({
|
||||
general,
|
||||
channels,
|
||||
users,
|
||||
teams
|
||||
});
|
||||
21
src/reducers/requests/teams.js
Normal file
21
src/reducers/requests/teams.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {handleRequest, initialRequestState} from './helpers';
|
||||
import {TeamsTypes} from 'constants';
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
function allTeams(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
TeamsTypes.FETCH_TEAMS_REQUEST,
|
||||
TeamsTypes.FETCH_TEAMS_SUCCESS,
|
||||
TeamsTypes.FETCH_TEAMS_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
allTeams
|
||||
});
|
||||
129
src/reducers/requests/users.js
Normal file
129
src/reducers/requests/users.js
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {handleRequest, initialRequestState} from './helpers';
|
||||
import {UsersTypes, RequestStatus} from 'constants';
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
function login(state = initialRequestState(), action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.LOGIN_REQUEST:
|
||||
return {...state, status: RequestStatus.STARTED};
|
||||
|
||||
case UsersTypes.LOGIN_SUCCESS:
|
||||
return {...state, status: RequestStatus.SUCCESS, error: null};
|
||||
|
||||
case UsersTypes.LOGIN_FAILURE:
|
||||
return {...state, status: RequestStatus.FAILURE, error: action.error};
|
||||
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return {...state, status: RequestStatus.NOT_STARTED, error: null};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function logout(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
UsersTypes.LOGOUT_REQUEST,
|
||||
UsersTypes.LOGOUT_SUCCESS,
|
||||
UsersTypes.LOGOUT_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function getProfiles(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
UsersTypes.PROFILES_REQUEST,
|
||||
UsersTypes.PROFILES_SUCCESS,
|
||||
UsersTypes.PROFILES_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function getProfilesInTeam(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
UsersTypes.PROFILES_IN_TEAM_REQUEST,
|
||||
UsersTypes.PROFILES_IN_TEAM_SUCCESS,
|
||||
UsersTypes.PROFILES_IN_TEAM_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function getProfilesInChannel(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
UsersTypes.PROFILES_IN_CHANNEL_REQUEST,
|
||||
UsersTypes.PROFILES_IN_CHANNEL_SUCCESS,
|
||||
UsersTypes.PROFILES_IN_CHANNEL_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function getProfilesNotInChannel(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
UsersTypes.PROFILES_NOT_IN_CHANNEL_REQUEST,
|
||||
UsersTypes.PROFILES_NOT_IN_CHANNEL_SUCCESS,
|
||||
UsersTypes.PROFILES_NOT_IN_CHANNEL_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function getStatusesByIds(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
UsersTypes.PROFILES_STATUSES_REQUEST,
|
||||
UsersTypes.PROFILES_STATUSES_SUCCESS,
|
||||
UsersTypes.PROFILES_STATUSES_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function getSessions(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
UsersTypes.SESSIONS_REQUEST,
|
||||
UsersTypes.SESSIONS_SUCCESS,
|
||||
UsersTypes.SESSIONS_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function revokeSession(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
UsersTypes.REVOKE_SESSION_REQUEST,
|
||||
UsersTypes.REVOKE_SESSION_SUCCESS,
|
||||
UsersTypes.REVOKE_SESSION_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
function getAudits(state = initialRequestState(), action) {
|
||||
return handleRequest(
|
||||
UsersTypes.AUDITS_REQUEST,
|
||||
UsersTypes.AUDITS_SUCCESS,
|
||||
UsersTypes.AUDITS_FAILURE,
|
||||
state,
|
||||
action
|
||||
);
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
login,
|
||||
logout,
|
||||
getProfiles,
|
||||
getProfilesInTeam,
|
||||
getProfilesInChannel,
|
||||
getProfilesNotInChannel,
|
||||
getStatusesByIds,
|
||||
getSessions,
|
||||
revokeSession,
|
||||
getAudits
|
||||
});
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {TeamsTypes, LogoutTypes} from 'constants';
|
||||
|
||||
export const initState = {
|
||||
status: 'not fetched',
|
||||
error: null,
|
||||
data: {},
|
||||
currentTeamId: null
|
||||
};
|
||||
|
||||
export default function reduceTeams(state = initState, action) {
|
||||
switch (action.type) {
|
||||
|
||||
case TeamsTypes.SELECT_TEAM:
|
||||
return {
|
||||
...state,
|
||||
currentTeamId: action.teamId
|
||||
};
|
||||
|
||||
case TeamsTypes.FETCH_TEAMS_REQUEST:
|
||||
return {
|
||||
...state,
|
||||
status: 'fetching',
|
||||
error: null
|
||||
};
|
||||
case TeamsTypes.FETCH_TEAMS_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
status: 'fetched',
|
||||
data: action.data
|
||||
};
|
||||
case TeamsTypes.FETCH_TEAMS_FAILURE:
|
||||
return {
|
||||
...state,
|
||||
status: 'failed',
|
||||
error: action.error
|
||||
};
|
||||
|
||||
case LogoutTypes.LOGOUT_SUCCESS:
|
||||
return initState;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
36
src/reducers/views/device.js
Normal file
36
src/reducers/views/device.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {DeviceTypes} from 'constants';
|
||||
import RequestStatus from 'constants/request_status';
|
||||
|
||||
export const initState = {
|
||||
status: RequestStatus.NOT_STARTED,
|
||||
error: null
|
||||
};
|
||||
|
||||
export default function device(state = initState, action) {
|
||||
switch (action.type) {
|
||||
case DeviceTypes.DEVICE_REQUEST:
|
||||
return {
|
||||
...state,
|
||||
status: RequestStatus.STARTED
|
||||
};
|
||||
case DeviceTypes.DEVICE_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
status: RequestStatus.SUCCESS,
|
||||
data: action.data,
|
||||
error: null
|
||||
};
|
||||
case DeviceTypes.DEVICE_FAILURE:
|
||||
return {
|
||||
...state,
|
||||
status: RequestStatus.FAILURE,
|
||||
error: action.error
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
23
src/reducers/views/i18n.js
Normal file
23
src/reducers/views/i18n.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
import Config from 'config/index';
|
||||
import {UsersTypes} from 'constants';
|
||||
|
||||
function locale(state = Config.DefaultLocale, action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.RECEIVED_ME:
|
||||
return action.data.locale;
|
||||
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return Config.DefaultLocale;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
locale
|
||||
});
|
||||
16
src/reducers/views/index.js
Normal file
16
src/reducers/views/index.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
import login from './login';
|
||||
import selectServer from './select_server';
|
||||
import device from './device';
|
||||
import i18n from './i18n';
|
||||
|
||||
export default combineReducers({
|
||||
device,
|
||||
i18n,
|
||||
login,
|
||||
selectServer
|
||||
});
|
||||
33
src/reducers/views/login.js
Normal file
33
src/reducers/views/login.js
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
import {UsersTypes} from 'constants';
|
||||
|
||||
function loginId(state = '', action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.LOGIN_ID_CHANGED:
|
||||
return action.loginId;
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return '';
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function password(state = '', action) {
|
||||
switch (action.type) {
|
||||
case UsersTypes.PASSWORD_CHANGED:
|
||||
return action.password;
|
||||
case UsersTypes.LOGOUT_SUCCESS:
|
||||
return '';
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
loginId,
|
||||
password
|
||||
});
|
||||
22
src/reducers/views/select_server.js
Normal file
22
src/reducers/views/select_server.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {combineReducers} from 'redux';
|
||||
|
||||
import Config from 'config/index';
|
||||
|
||||
import {GeneralTypes} from 'constants';
|
||||
|
||||
function serverUrl(state = Config.DefaultServerUrl, action) {
|
||||
switch (action.type) {
|
||||
case GeneralTypes.SERVER_URL_CHANGED:
|
||||
return action.serverUrl;
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
export default combineReducers({
|
||||
serverUrl
|
||||
});
|
||||
|
|
@ -17,7 +17,7 @@ export default class Channel extends React.Component {
|
|||
currentTeam: React.PropTypes.object.isRequired,
|
||||
currentChannel: React.PropTypes.object,
|
||||
channels: React.PropTypes.arrayOf(React.PropTypes.object).isRequired
|
||||
}
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
|
|
|||
|
|
@ -7,18 +7,17 @@ import {fetchMyChannelsAndMembers} from 'actions/channels.js';
|
|||
import Channel from './channel.js';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
const currentTeamId = ownProps.currentTeamId;
|
||||
const currentTeam = state.entities.teams.data[currentTeamId];
|
||||
const currentTeamId = state.entities.teams.currentId;
|
||||
const currentTeam = state.entities.teams.teams[currentTeamId];
|
||||
let channels = state.entities.channels.channels;
|
||||
|
||||
let currentChannel;
|
||||
if (ownProps.currentChannelId) {
|
||||
currentChannel = state.entities.channel.channels[ownProps.currentChannelId];
|
||||
currentChannel = state.entities.channels.channels[ownProps.currentChannelId];
|
||||
} else {
|
||||
// TODO figure out the town square id before this
|
||||
const channelIds = state.entities.channel.channelIdsByTeamId[currentTeamId] || {};
|
||||
|
||||
for (const channelId of Object.keys(channelIds)) {
|
||||
const channel = state.entities.channel.channels[channelId];
|
||||
for (const channelId of Object.keys(channels)) {
|
||||
const channel = channels[channelId];
|
||||
|
||||
if (channel.name === 'town-square') {
|
||||
currentChannel = channel;
|
||||
|
|
@ -27,8 +26,7 @@ function mapStateToProps(state, ownProps) {
|
|||
}
|
||||
}
|
||||
|
||||
const channelIdsForTeam = state.entities.channel.channelIdsByTeamId[currentTeamId] || {};
|
||||
const channels = Object.keys(channelIdsForTeam).map((channelId) => state.entities.channel.channels[channelId]);
|
||||
channels = Object.keys(channels).map((channelId) => channels[channelId]);
|
||||
|
||||
return {
|
||||
...ownProps,
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@ import SelectServerContainer from './select_server/select_server_container.js';
|
|||
import SelectTeamContainer from './select_team/select_team_container.js';
|
||||
import ChannelContainer from './channel/channel_container.js';
|
||||
import Logout from 'components/logout';
|
||||
import * as logout from 'actions/logout';
|
||||
import {logout} from 'actions/users';
|
||||
|
||||
import {injectIntl, intlShape} from 'react-intl';
|
||||
|
||||
class Routes extends Component {
|
||||
static propTypes = {
|
||||
intl: intlShape.isRequired
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {formatMessage} = this.props.intl;
|
||||
|
|
|
|||
|
|
@ -14,52 +14,55 @@ import logo from 'images/logo.png';
|
|||
|
||||
import {injectIntl, intlShape} from 'react-intl';
|
||||
|
||||
import {RequestStatus} from 'constants';
|
||||
|
||||
class Login extends Component {
|
||||
static propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
clientConfig: PropTypes.object.isRequired,
|
||||
login: PropTypes.object.isRequired,
|
||||
actions: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
state = {
|
||||
loginId: '',
|
||||
password: ''
|
||||
config: PropTypes.object.isRequired,
|
||||
license: PropTypes.object.isRequired,
|
||||
actions: PropTypes.object.isRequired,
|
||||
loginId: PropTypes.string.isRequired,
|
||||
password: PropTypes.string.isRequired,
|
||||
loginRequest: PropTypes.object.isRequired,
|
||||
configRequest: PropTypes.object.isRequired,
|
||||
licenseRequest: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
this.props.actions.getClientConfig();
|
||||
this.props.actions.getLicenseConfig();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.login.status === 'fetching' && nextProps.login.status === 'fetched') {
|
||||
if (this.props.loginRequest.status === RequestStatus.STARTED && nextProps.loginRequest.status === RequestStatus.SUCCESS) {
|
||||
Routes.goToSelectTeam();
|
||||
}
|
||||
}
|
||||
|
||||
signIn = () => {
|
||||
if (this.props.login.status !== 'fetching') {
|
||||
const {loginId, password} = this.state;
|
||||
this.props.actions.login(loginId, password);
|
||||
signIn() {
|
||||
if (this.props.loginRequest.status !== RequestStatus.STARTED) {
|
||||
this.props.actions.login(this.props.loginId, this.props.password);
|
||||
}
|
||||
}
|
||||
|
||||
createLoginPlaceholder() {
|
||||
const {formatMessage} = this.props.intl;
|
||||
const clientConfig = this.props.clientConfig;
|
||||
const license = this.props.license;
|
||||
const config = this.props.config;
|
||||
|
||||
const loginPlaceholders = [];
|
||||
if (clientConfig.EnableSignInWithEmail === 'true') {
|
||||
if (config.EnableSignInWithEmail === 'true') {
|
||||
loginPlaceholders.push(formatMessage({id: 'login.email', defaultMessage: 'Email'}));
|
||||
}
|
||||
|
||||
if (clientConfig.EnableSignInWithUsername === 'true') {
|
||||
if (config.EnableSignInWithUsername === 'true') {
|
||||
loginPlaceholders.push(formatMessage({id: 'login.username', defaultMessage: 'Username'}));
|
||||
}
|
||||
|
||||
if (clientConfig.EnableLdap === 'true') { // TODO check if we're licensed once we have that
|
||||
if (clientConfig.LdapLoginFieldName) {
|
||||
loginPlaceholders.push(clientConfig.LdapLoginFieldName);
|
||||
if (license.IsLicensed === 'true' && license.LDAP === 'true' && config.EnableLdap === 'true') {
|
||||
if (config.LdapLoginFieldName) {
|
||||
loginPlaceholders.push(config.LdapLoginFieldName);
|
||||
} else {
|
||||
loginPlaceholders.push(formatMessage({id: 'login.ldapUsername', defaultMessage: 'AD/LDAP Username'}));
|
||||
}
|
||||
|
|
@ -77,7 +80,7 @@ class Login extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
if (this.props.clientConfig.loading || this.props.clientConfig.error) {
|
||||
if (this.props.configRequest.status === RequestStatus.STARTED || this.props.licenseRequest.status === RequestStatus.STARTED) {
|
||||
return <Loading/>;
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +91,7 @@ class Login extends Component {
|
|||
source={logo}
|
||||
/>
|
||||
<Text style={GlobalStyles.header}>
|
||||
{this.props.clientConfig.SiteName}
|
||||
{this.props.config.SiteName}
|
||||
</Text>
|
||||
<FormattedText
|
||||
style={GlobalStyles.subheader}
|
||||
|
|
@ -97,8 +100,8 @@ class Login extends Component {
|
|||
/>
|
||||
<TextInput
|
||||
ref='loginId'
|
||||
value={this.state.loginId}
|
||||
onChangeText={(loginId) => this.setState({loginId})}
|
||||
value={this.props.loginId}
|
||||
onChangeText={this.props.actions.handleLoginIdChanged}
|
||||
style={GlobalStyles.inputBox}
|
||||
placeholder={this.createLoginPlaceholder()}
|
||||
autoCorrect={false}
|
||||
|
|
@ -106,8 +109,8 @@ class Login extends Component {
|
|||
underlineColorAndroid='transparent'
|
||||
/>
|
||||
<TextInput
|
||||
value={this.state.password}
|
||||
onChangeText={(password) => this.setState({password})}
|
||||
value={this.props.password}
|
||||
onChangeText={this.props.actions.handlePasswordChanged}
|
||||
style={GlobalStyles.inputBox}
|
||||
placeholder={this.props.intl.formatMessage({id: 'login.password', defaultMessage: 'Password'})}
|
||||
secureTextEntry={true}
|
||||
|
|
@ -115,15 +118,15 @@ class Login extends Component {
|
|||
autoCapitalize='none'
|
||||
underlineColorAndroid='transparent'
|
||||
returnKeyType='go'
|
||||
onSubmitEditing={this.signIn}
|
||||
onSubmitEditing={this.signIn.bind(this)}
|
||||
/>
|
||||
<Button onPress={this.signIn}>
|
||||
<Button onPress={this.signIn.bind(this)}>
|
||||
<FormattedText
|
||||
id='login.signIn'
|
||||
defaultMessage='Sign in'
|
||||
/>
|
||||
</Button>
|
||||
<ErrorText error={this.props.login.error}/>
|
||||
<ErrorText error={this.props.loginRequest.error}/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,22 +3,31 @@
|
|||
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
import * as loginActions from 'actions/login';
|
||||
import {getClientConfig} from 'actions/general';
|
||||
|
||||
import {getClientConfig, getLicenseConfig} from 'actions/general';
|
||||
import * as LoginActions from 'actions/views/login';
|
||||
import {login} from 'actions/users';
|
||||
|
||||
import Login from './login.js';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
clientConfig: state.entities.general.clientConfig,
|
||||
login: state.views.login
|
||||
...state.views.login,
|
||||
loginRequest: state.requests.users.login,
|
||||
configRequest: state.requests.general.config,
|
||||
licenseRequest: state.requests.general.license,
|
||||
config: state.entities.general.config,
|
||||
license: state.entities.general.license
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
...loginActions,
|
||||
getClientConfig
|
||||
...LoginActions,
|
||||
login,
|
||||
getClientConfig,
|
||||
getLicenseConfig
|
||||
}, dispatch)
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,8 @@ import React, {Component} from 'react';
|
|||
import {View, TextInput, Image} from 'react-native';
|
||||
import KeyboardSpacer from 'react-native-keyboard-spacer';
|
||||
import {Actions as Routes} from 'react-native-router-flux';
|
||||
import _ from 'lodash';
|
||||
|
||||
import Client from 'client/client_instance.js';
|
||||
import Config from 'config/config.js';
|
||||
import Client from 'client';
|
||||
import Button from 'components/button';
|
||||
import ErrorText from 'components/error_text';
|
||||
import FormattedText from 'components/formatted_text';
|
||||
|
|
@ -17,31 +15,25 @@ import logo from 'images/logo.png';
|
|||
|
||||
import {injectIntl, intlShape} from 'react-intl';
|
||||
|
||||
import RequestStatus from 'constants/request_status';
|
||||
|
||||
class SelectServer extends Component {
|
||||
static propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
ping: React.PropTypes.object.isRequired,
|
||||
device: React.PropTypes.object.isRequired,
|
||||
serverUrl: React.PropTypes.string.isRequired,
|
||||
server: React.PropTypes.object.isRequired,
|
||||
actions: React.PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
serverUrl: Config.DefaultServerUrl
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
onClick = () => {
|
||||
Client.setUrl(this.state.serverUrl);
|
||||
Client.setUrl(this.props.serverUrl);
|
||||
|
||||
this.props.actions.getPing().then(() => {
|
||||
if (!this.props.ping.loading && !this.props.ping.error) {
|
||||
if (this.props.server.status === RequestStatus.SUCCESS) {
|
||||
Routes.goToLogin();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {formatMessage} = this.props.intl;
|
||||
|
|
@ -53,13 +45,13 @@ class SelectServer extends Component {
|
|||
source={logo}
|
||||
/>
|
||||
<FormattedText
|
||||
style={_.at(GlobalStyles, ['header', 'label'])}
|
||||
style={[GlobalStyles.header, GlobalStyles.label]}
|
||||
id='mobile.components.select_server_view.enterServerUrl'
|
||||
defaultMessage='Enter Server URL'
|
||||
/>
|
||||
<TextInput
|
||||
value={this.state.serverUrl}
|
||||
onChangeText={(serverUrl) => this.setState({serverUrl})}
|
||||
value={this.props.serverUrl}
|
||||
onChangeText={this.props.actions.handleServerUrlChanged}
|
||||
onSubmitEditing={this.onClick}
|
||||
style={GlobalStyles.inputBox}
|
||||
autoCapitalize='none'
|
||||
|
|
@ -71,14 +63,14 @@ class SelectServer extends Component {
|
|||
/>
|
||||
<Button
|
||||
onPress={this.onClick}
|
||||
loading={this.props.ping.loading}
|
||||
loading={this.props.server.loading}
|
||||
>
|
||||
<FormattedText
|
||||
id='mobile.components.select_server_view.proceed'
|
||||
defaultMessage='Proceed'
|
||||
/>
|
||||
</Button>
|
||||
<ErrorText error={this.props.ping.error}/>
|
||||
<ErrorText error={this.props.server.error}/>
|
||||
<KeyboardSpacer/>
|
||||
</View>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,20 +3,26 @@
|
|||
|
||||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {getPing} from 'actions/general';
|
||||
import SelectServerView from './select_server.js';
|
||||
import * as SelectServerActions from 'actions/views/select_server';
|
||||
|
||||
import SelectServer from './select_server';
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
ping: state.entities.general.ping,
|
||||
device: state.views.device
|
||||
...state.views.selectServer,
|
||||
server: state.requests.general.server
|
||||
};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({getPing}, dispatch)
|
||||
actions: bindActionCreators({
|
||||
...SelectServerActions,
|
||||
getPing
|
||||
}, dispatch)
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SelectServerView);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SelectServer);
|
||||
|
|
|
|||
|
|
@ -6,18 +6,21 @@ import React, {Component, PropTypes} from 'react';
|
|||
import {View, Image, Text} from 'react-native';
|
||||
import {Actions as Routes} from 'react-native-router-flux';
|
||||
import Button from 'react-native-button';
|
||||
import Loading from 'components/loading.js';
|
||||
import Loading from 'components/loading';
|
||||
import Icon from 'react-native-vector-icons/MaterialIcons';
|
||||
|
||||
import ErrorText from 'components/error_text';
|
||||
import {GlobalStyles} from 'styles';
|
||||
import logo from 'images/logo.png';
|
||||
import FormattedText from 'components/formatted_text';
|
||||
import {RequestStatus} from 'constants';
|
||||
|
||||
export default class SelectTeam extends Component {
|
||||
static propTypes = {
|
||||
clientConfig: PropTypes.object.isRequired,
|
||||
config: PropTypes.object.isRequired,
|
||||
teams: PropTypes.object.isRequired,
|
||||
myMembers: PropTypes.object.isRequired,
|
||||
teamsRequest: PropTypes.object.isRequired,
|
||||
actions: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
|
|
@ -26,18 +29,21 @@ export default class SelectTeam extends Component {
|
|||
}
|
||||
|
||||
onSelectTeam(team) {
|
||||
this.props.actions.selectTeam(team);
|
||||
Routes.goToMain({currentTeamId: team.id});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.teams.status !== 'fetched') {
|
||||
if (this.props.teamsRequest.status === RequestStatus.STARTED) {
|
||||
return <Loading/>;
|
||||
}
|
||||
|
||||
const teams = [];
|
||||
for (const id of Object.keys(this.props.teams.data)) {
|
||||
const team = this.props.teams.data[id];
|
||||
for (const id of Object.keys(this.props.teams)) {
|
||||
const team = this.props.teams[id];
|
||||
|
||||
// TODO: uncomment when PLT-4167 is merged
|
||||
// if (this.props.myMembers.hasOwnProperty(id)) {
|
||||
teams.push(
|
||||
<Button
|
||||
key={id}
|
||||
|
|
@ -53,6 +59,8 @@ export default class SelectTeam extends Component {
|
|||
/>
|
||||
</Button>
|
||||
);
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -62,7 +70,7 @@ export default class SelectTeam extends Component {
|
|||
source={logo}
|
||||
/>
|
||||
<Text style={GlobalStyles.header}>
|
||||
{this.props.clientConfig.SiteName}
|
||||
{this.props.config.SiteName}
|
||||
</Text>
|
||||
<FormattedText
|
||||
style={GlobalStyles.subheader}
|
||||
|
|
@ -75,7 +83,7 @@ export default class SelectTeam extends Component {
|
|||
defaultMessage='Your teams:'
|
||||
/>
|
||||
{teams}
|
||||
<ErrorText error={this.props.teams.error}/>
|
||||
<ErrorText error={this.props.teamsRequest.error}/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@ import SelectTeamView from './select_team.js';
|
|||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
clientConfig: state.entities.general.clientConfig,
|
||||
teams: state.entities.teams
|
||||
config: state.entities.general.config,
|
||||
teamsRequest: state.requests.teams.allTeams,
|
||||
teams: state.entities.teams.teams,
|
||||
myMembers: state.entities.teams.myMembers
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
8
src/store/index.js
Normal file
8
src/store/index.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import configureStore from 'store/configureStore.js';
|
||||
|
||||
const store = configureStore();
|
||||
|
||||
export default store;
|
||||
496
test/actions/channels.test.js
Normal file
496
test/actions/channels.test.js
Normal file
|
|
@ -0,0 +1,496 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import * as Actions from 'actions/channels';
|
||||
import Client from 'client';
|
||||
import configureStore from 'store/configureStore';
|
||||
import {RequestStatus} from 'constants';
|
||||
import TestHelper from 'test_helper';
|
||||
|
||||
describe('Actions.Channels', () => {
|
||||
it('createChannel', (done) => {
|
||||
TestHelper.initBasic(Client).then(() => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const channels = store.getState().entities.channels.channels;
|
||||
const members = store.getState().entities.channels.myMembers;
|
||||
|
||||
const createRequest = store.getState().requests.channels.createChannel;
|
||||
const membersRequest = store.getState().requests.channels.myMembers;
|
||||
|
||||
if (createRequest.status === RequestStatus.SUCCESS && membersRequest.status === RequestStatus.SUCCESS) {
|
||||
const channelsCount = Object.keys(channels).length;
|
||||
const membersCount = Object.keys(members).length;
|
||||
assert.ok(channels);
|
||||
assert.ok(members);
|
||||
assert.ok(channels[Object.keys(members)[0]]);
|
||||
assert.ok(members[Object.keys(channels)[0]]);
|
||||
assert.equal(members[Object.keys(channels)[0]].user_id, TestHelper.basicUser.id);
|
||||
assert.equal(channelsCount, membersCount);
|
||||
assert.equal(channelsCount, 1);
|
||||
assert.equal(membersCount, 1);
|
||||
done();
|
||||
} else if (createRequest.status === RequestStatus.FAILURE && membersRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(createRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
const channel = {
|
||||
team_id: TestHelper.basicTeam.id,
|
||||
name: 'redux-test',
|
||||
display_name: 'Redux Test',
|
||||
purpose: 'This is to test redux',
|
||||
header: 'MM with Redux',
|
||||
type: 'O'
|
||||
};
|
||||
|
||||
Actions.createChannel(channel, TestHelper.basicUser.id)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('createDirectChannel', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
const user = await TestHelper.basicClient.createUser(TestHelper.fakeUser());
|
||||
|
||||
store.subscribe(() => {
|
||||
const channels = store.getState().entities.channels.channels;
|
||||
const members = store.getState().entities.channels.myMembers;
|
||||
const profiles = store.getState().entities.users.profiles;
|
||||
const preferences = store.getState().entities.users.myPreferences;
|
||||
|
||||
const createRequest = store.getState().requests.channels.createChannel;
|
||||
const membersRequest = store.getState().requests.channels.myMembers;
|
||||
|
||||
if (createRequest.status === RequestStatus.SUCCESS && membersRequest.status === RequestStatus.SUCCESS) {
|
||||
const channelsCount = Object.keys(channels).length;
|
||||
const membersCount = Object.keys(members).length;
|
||||
assert.ok(channels);
|
||||
assert.ok(members);
|
||||
assert.ok(profiles.items[user.id]);
|
||||
assert.ok(Object.keys(preferences).length);
|
||||
assert.ok(channels[Object.keys(members)[0]]);
|
||||
assert.ok(members[Object.keys(channels)[0]]);
|
||||
assert.equal(members[Object.keys(channels)[0]].user_id, TestHelper.basicUser.id);
|
||||
assert.equal(channelsCount, membersCount);
|
||||
assert.equal(channels[Object.keys(channels)[0]].type, 'D');
|
||||
assert.equal(channelsCount, 1);
|
||||
assert.equal(membersCount, 1);
|
||||
done();
|
||||
} else if (createRequest.status === RequestStatus.FAILURE && membersRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(createRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
Actions.createDirectChannel(TestHelper.basicUser.id, user.id)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('updateChannel', (done) => {
|
||||
TestHelper.initBasic(Client).then(() => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const channels = store.getState().entities.channels.channels;
|
||||
const updateRequest = store.getState().requests.channels.updateChannel;
|
||||
|
||||
if (updateRequest.status === RequestStatus.SUCCESS) {
|
||||
const channelId = Object.keys(channels)[0];
|
||||
const channel = channels[channelId];
|
||||
assert.ok(channelId);
|
||||
assert.ok(channel);
|
||||
assert.equal(channel.header, 'MM with Redux');
|
||||
done();
|
||||
} else if (updateRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(updateRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
const channel = {
|
||||
...TestHelper.basicChannel,
|
||||
purpose: 'This is to test redux',
|
||||
header: 'MM with Redux'
|
||||
};
|
||||
|
||||
Actions.updateChannel(channel)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('getChannel', (done) => {
|
||||
TestHelper.initBasic(Client).then(() => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const channels = store.getState().entities.channels.channels;
|
||||
const members = store.getState().entities.channels.myMembers;
|
||||
|
||||
const channelRequest = store.getState().requests.channels.getChannel;
|
||||
|
||||
if (channelRequest.status === RequestStatus.SUCCESS) {
|
||||
assert.ok(channels[TestHelper.basicChannel.id]);
|
||||
assert.ok(members[TestHelper.basicChannel.id]);
|
||||
done();
|
||||
} else if (channelRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(channelRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getChannel(TestHelper.basicTeam.id, TestHelper.basicChannel.id)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('fetchMyChannelsAndMembers', (done) => {
|
||||
TestHelper.initBasic(Client).then(() => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const channels = store.getState().entities.channels.channels;
|
||||
const members = store.getState().entities.channels.myMembers;
|
||||
|
||||
const channelsRequest = store.getState().requests.channels.getChannels;
|
||||
const membersRequest = store.getState().requests.channels.myMembers;
|
||||
|
||||
if (channelsRequest.status === RequestStatus.SUCCESS && membersRequest.status === RequestStatus.SUCCESS) {
|
||||
assert.ok(channels);
|
||||
assert.ok(members);
|
||||
assert.ok(channels[Object.keys(members)[0]]);
|
||||
assert.ok(members[Object.keys(channels)[0]]);
|
||||
assert.equal(Object.keys(channels).length, Object.keys(members).length);
|
||||
done();
|
||||
} else if (channelsRequest.status === RequestStatus.FAILURE && membersRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(channelsRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
Actions.fetchMyChannelsAndMembers(TestHelper.basicTeam.id)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('updateChannelNotifyProps', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const members = store.getState().entities.channels.myMembers;
|
||||
const updateRequest = store.getState().requests.channels.updateChannelNotifyProps;
|
||||
|
||||
if (updateRequest.status === RequestStatus.SUCCESS) {
|
||||
const member = members[TestHelper.basicChannel.id];
|
||||
assert.ok(member);
|
||||
assert.equal(member.notify_props.mark_unread, 'mention');
|
||||
assert.equal(member.notify_props.desktop, 'none');
|
||||
done();
|
||||
} else if (updateRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(updateRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
const notifyProps = {
|
||||
mark_unread: 'mention',
|
||||
desktop: 'none'
|
||||
};
|
||||
|
||||
await Actions.fetchMyChannelsAndMembers(TestHelper.basicTeam.id)(store.dispatch, store.getState);
|
||||
Actions.updateChannelNotifyProps(
|
||||
TestHelper.basicUser.id,
|
||||
TestHelper.basicTeam.id,
|
||||
TestHelper.basicChannel.id,
|
||||
notifyProps)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('leaveChannel', (done) => {
|
||||
TestHelper.initBasic(Client).then(() => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const channels = store.getState().entities.channels.channels;
|
||||
const members = store.getState().entities.channels.myMembers;
|
||||
const leaveRequest = store.getState().requests.channels.leaveChannel;
|
||||
|
||||
if (leaveRequest.status === RequestStatus.SUCCESS) {
|
||||
const channel = channels[TestHelper.basicChannel.id];
|
||||
const member = members[TestHelper.basicChannel.id];
|
||||
|
||||
assert.ifError(channel);
|
||||
assert.ifError(member);
|
||||
done();
|
||||
} else if (leaveRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(leaveRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
Actions.leaveChannel(
|
||||
TestHelper.basicTeam.id,
|
||||
TestHelper.basicChannel.id)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('joinChannel', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
const secondClient = TestHelper.createClient();
|
||||
const user = await TestHelper.basicClient.createUserWithInvite(
|
||||
TestHelper.fakeUser(),
|
||||
null,
|
||||
null,
|
||||
TestHelper.basicTeam.invite_id
|
||||
);
|
||||
await secondClient.login(user.email, 'password1');
|
||||
|
||||
const secondChannel = await secondClient.createChannel(
|
||||
TestHelper.fakeChannel(TestHelper.basicTeam.id));
|
||||
|
||||
store.subscribe(() => {
|
||||
const channels = store.getState().entities.channels.channels;
|
||||
const members = store.getState().entities.channels.myMembers;
|
||||
const joinRequest = store.getState().requests.channels.joinChannel;
|
||||
|
||||
if (joinRequest.status === RequestStatus.SUCCESS) {
|
||||
const channel = channels[secondChannel.id];
|
||||
const member = members[secondChannel.id];
|
||||
|
||||
assert.ok(channel);
|
||||
assert.ok(member);
|
||||
done();
|
||||
} else if (joinRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(joinRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
Actions.joinChannel(
|
||||
TestHelper.basicUser.id,
|
||||
TestHelper.basicTeam.id,
|
||||
secondChannel.id)(store.dispatch, store.getState);
|
||||
});
|
||||
}).timeout(3000);
|
||||
|
||||
it('joinChannelByName', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
const secondClient = TestHelper.createClient();
|
||||
const user = await TestHelper.basicClient.createUserWithInvite(
|
||||
TestHelper.fakeUser(),
|
||||
null,
|
||||
null,
|
||||
TestHelper.basicTeam.invite_id
|
||||
);
|
||||
await secondClient.login(user.email, 'password1');
|
||||
|
||||
const secondChannel = await secondClient.createChannel(
|
||||
TestHelper.fakeChannel(TestHelper.basicTeam.id));
|
||||
|
||||
store.subscribe(() => {
|
||||
const channels = store.getState().entities.channels.channels;
|
||||
const members = store.getState().entities.channels.myMembers;
|
||||
const joinRequest = store.getState().requests.channels.joinChannel;
|
||||
|
||||
if (joinRequest.status === RequestStatus.SUCCESS) {
|
||||
const channel = channels[secondChannel.id];
|
||||
const member = members[secondChannel.id];
|
||||
|
||||
assert.ok(channel);
|
||||
assert.ok(member);
|
||||
done();
|
||||
} else if (joinRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(joinRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
Actions.joinChannel(
|
||||
TestHelper.basicUser.id,
|
||||
TestHelper.basicTeam.id,
|
||||
null,
|
||||
secondChannel.name)(store.dispatch, store.getState);
|
||||
});
|
||||
}).timeout(3000);
|
||||
|
||||
it('deleteChannel', (done) => {
|
||||
TestHelper.initBasic(Client).then(() => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const channels = store.getState().entities.channels.channels;
|
||||
const members = store.getState().entities.channels.myMembers;
|
||||
const deleteRequest = store.getState().requests.channels.deleteChannel;
|
||||
|
||||
if (deleteRequest.status === RequestStatus.SUCCESS) {
|
||||
const channel = channels[TestHelper.basicChannel.id];
|
||||
const member = members[TestHelper.basicChannel.id];
|
||||
|
||||
assert.ifError(channel);
|
||||
assert.ifError(member);
|
||||
done();
|
||||
} else if (deleteRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(deleteRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
Actions.deleteChannel(
|
||||
TestHelper.basicTeam.id,
|
||||
TestHelper.basicChannel.id)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('updateLastViewedAt', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
let lastViewed;
|
||||
|
||||
store.subscribe(() => {
|
||||
const members = store.getState().entities.channels.myMembers;
|
||||
const updateRequest = store.getState().requests.channels.updateLastViewedAt;
|
||||
let member;
|
||||
|
||||
if (updateRequest.status === RequestStatus.STARTED) {
|
||||
member = members[TestHelper.basicChannel.id];
|
||||
assert.ok(member);
|
||||
lastViewed = member.last_viewed_at;
|
||||
} else if (updateRequest.status === RequestStatus.SUCCESS) {
|
||||
member = members[TestHelper.basicChannel.id];
|
||||
assert.ok(member.last_viewed_at > lastViewed);
|
||||
|
||||
done();
|
||||
} else if (updateRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(updateRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
await Actions.fetchMyChannelsAndMembers(TestHelper.basicTeam.id)(store.dispatch, store.getState);
|
||||
Actions.updateLastViewedAt(
|
||||
TestHelper.basicTeam.id,
|
||||
TestHelper.basicChannel.id, true)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('getMoreChannels', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
const secondClient = TestHelper.createClient();
|
||||
const user = await TestHelper.basicClient.createUserWithInvite(
|
||||
TestHelper.fakeUser(),
|
||||
null,
|
||||
null,
|
||||
TestHelper.basicTeam.invite_id
|
||||
);
|
||||
await secondClient.login(user.email, 'password1');
|
||||
|
||||
const secondChannel = await secondClient.createChannel(
|
||||
TestHelper.fakeChannel(TestHelper.basicTeam.id));
|
||||
|
||||
store.subscribe(() => {
|
||||
const channels = store.getState().entities.channels.moreChannels;
|
||||
const moreRequest = store.getState().requests.channels.getMoreChannels;
|
||||
|
||||
if (moreRequest.status === RequestStatus.SUCCESS) {
|
||||
const channel = channels[secondChannel.id];
|
||||
|
||||
assert.ok(channel);
|
||||
done();
|
||||
} else if (moreRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(moreRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getMoreChannels(TestHelper.basicTeam.id, 0)(store.dispatch, store.getState);
|
||||
});
|
||||
}).timeout(3000);
|
||||
|
||||
it('getChannelStats', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const stats = store.getState().entities.channels.stats;
|
||||
const statsRequest = store.getState().requests.channels.getChannelStats;
|
||||
|
||||
if (statsRequest.status === RequestStatus.SUCCESS) {
|
||||
const stat = stats[TestHelper.basicChannel.id];
|
||||
assert.ok(stat);
|
||||
assert.equal(stat.member_count, 1);
|
||||
done();
|
||||
} else if (statsRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(statsRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getChannelStats(
|
||||
TestHelper.basicTeam.id,
|
||||
TestHelper.basicChannel.id
|
||||
)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('addChannelMember', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
const user = await TestHelper.basicClient.createUserWithInvite(
|
||||
TestHelper.fakeUser(),
|
||||
null,
|
||||
null,
|
||||
TestHelper.basicTeam.invite_id
|
||||
);
|
||||
|
||||
store.subscribe(() => {
|
||||
const profilesInChannel = store.getState().entities.users.profilesInChannel;
|
||||
const profilesNotInChannel = store.getState().entities.users.profilesNotInChannel;
|
||||
const addRequest = store.getState().requests.channels.addChannelMember;
|
||||
|
||||
if (addRequest.status === RequestStatus.SUCCESS) {
|
||||
assert.ok(profilesInChannel.items.has(user.id));
|
||||
assert.ifError(profilesNotInChannel.items.has(user.id));
|
||||
done();
|
||||
} else if (addRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(addRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
Actions.addChannelMember(
|
||||
TestHelper.basicTeam.id,
|
||||
TestHelper.basicChannel.id,
|
||||
user.id
|
||||
)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('removeChannelMember', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
const user = await TestHelper.basicClient.createUserWithInvite(
|
||||
TestHelper.fakeUser(),
|
||||
null,
|
||||
null,
|
||||
TestHelper.basicTeam.invite_id
|
||||
);
|
||||
|
||||
store.subscribe(() => {
|
||||
const profilesInChannel = store.getState().entities.users.profilesInChannel;
|
||||
const profilesNotInChannel = store.getState().entities.users.profilesNotInChannel;
|
||||
const removeRequest = store.getState().requests.channels.removeChannelMember;
|
||||
|
||||
if (removeRequest.status === RequestStatus.SUCCESS) {
|
||||
assert.ok(profilesNotInChannel.items.has(user.id));
|
||||
assert.ifError(profilesInChannel.items.has(user.id));
|
||||
done();
|
||||
} else if (removeRequest.status === RequestStatus.FAILURE) {
|
||||
done(new Error(JSON.stringify(removeRequest.error)));
|
||||
}
|
||||
});
|
||||
|
||||
await Actions.addChannelMember(
|
||||
TestHelper.basicTeam.id,
|
||||
TestHelper.basicChannel.id,
|
||||
user.id
|
||||
)(store.dispatch, store.getState);
|
||||
|
||||
Actions.removeChannelMember(
|
||||
TestHelper.basicTeam.id,
|
||||
TestHelper.basicChannel.id,
|
||||
user.id
|
||||
)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -3,22 +3,41 @@
|
|||
|
||||
import assert from 'assert';
|
||||
|
||||
import * as Actions from 'actions/general.js';
|
||||
import Client from 'client/client_instance.js';
|
||||
import configureStore from 'store/configureStore.js';
|
||||
import TestHelper from 'test_helper.js';
|
||||
import * as Actions from 'actions/general';
|
||||
import Client from 'client';
|
||||
import configureStore from 'store/configureStore';
|
||||
import {RequestStatus} from 'constants';
|
||||
import TestHelper from 'test_helper';
|
||||
|
||||
describe('Actions.General', () => {
|
||||
it('getPing', (done) => {
|
||||
TestHelper.initBasic(Client).then(() => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const ping = store.getState().requests.general.server;
|
||||
|
||||
if (ping.error) {
|
||||
done(new Error(JSON.stringify(ping.error)));
|
||||
} else if (ping.status !== RequestStatus.STARTED) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getPing()(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('getClientConfig', (done) => {
|
||||
TestHelper.initBasic(Client).then(() => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const clientConfig = store.getState().entities.general.clientConfig;
|
||||
|
||||
if (!clientConfig.loading) {
|
||||
if (clientConfig.error) {
|
||||
done(new Error(clientConfig.error));
|
||||
const clientConfig = store.getState().entities.general.config;
|
||||
const configRequest = store.getState().requests.general.config;
|
||||
if (configRequest.status === RequestStatus.SUCCESS || configRequest.status === RequestStatus.FAILURE) {
|
||||
if (configRequest.error) {
|
||||
done(new Error(JSON.stringify(configRequest.error)));
|
||||
} else {
|
||||
// Check a few basic fields since they may change over time
|
||||
assert.ok(clientConfig.Version);
|
||||
|
|
@ -35,21 +54,26 @@ describe('Actions.General', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('getPing', (done) => {
|
||||
it('getLicenseConfig', (done) => {
|
||||
TestHelper.initBasic(Client).then(() => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const ping = store.getState().entities.general.ping;
|
||||
const licenseConfig = store.getState().entities.general.license;
|
||||
const licenseRequest = store.getState().requests.general.license;
|
||||
if (licenseRequest.status === RequestStatus.SUCCESS || licenseRequest.status === RequestStatus.FAILURE) {
|
||||
if (licenseRequest.error) {
|
||||
done(new Error(JSON.stringify(licenseRequest.error)));
|
||||
} else {
|
||||
// Check a few basic fields since they may change over time
|
||||
assert.notStrictEqual(licenseConfig.IsLicensed, undefined);
|
||||
|
||||
if (ping.error) {
|
||||
done(new Error(ping.error));
|
||||
} else if (!ping.loading) {
|
||||
done();
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getPing()(store.dispatch, store.getState);
|
||||
Actions.getLicenseConfig()(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -58,15 +82,15 @@ describe('Actions.General', () => {
|
|||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const ping = store.getState().entities.general.ping;
|
||||
const ping = store.getState().requests.general.server;
|
||||
|
||||
if (!ping.loading && ping.error) {
|
||||
if (ping.status === RequestStatus.FAILURE && ping.error) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
Client.setUrl('https://example.com/fake/url');
|
||||
Client.setUrl('https://google.com/fake/url');
|
||||
Actions.getPing()(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
}).timeout(5000);
|
||||
});
|
||||
|
|
|
|||
50
test/actions/teams.test.js
Normal file
50
test/actions/teams.test.js
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import * as Actions from 'actions/teams';
|
||||
import Client from 'client';
|
||||
import configureStore from 'store/configureStore';
|
||||
import {RequestStatus} from 'constants';
|
||||
import TestHelper from 'test_helper';
|
||||
|
||||
describe('Actions.Teams', () => {
|
||||
it('fetchTeams', (done) => {
|
||||
TestHelper.initBasic(Client).then(() => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const teamsRequest = store.getState().requests.teams.allTeams;
|
||||
const teams = store.getState().entities.teams.teams;
|
||||
|
||||
if (teamsRequest.status === RequestStatus.SUCCESS || teamsRequest.status === RequestStatus.FAILURE) {
|
||||
if (teamsRequest.error) {
|
||||
done(new Error(JSON.stringify(teamsRequest.error)));
|
||||
} else {
|
||||
assert.ok(teams);
|
||||
assert.ok(teams[TestHelper.basicTeam.id]);
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Actions.fetchTeams()(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('selectTeam', (done) => {
|
||||
TestHelper.initBasic(Client).then(() => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const currentTeamId = store.getState().entities.teams.currentId;
|
||||
assert.ok(currentTeamId);
|
||||
assert.equal(currentTeamId, TestHelper.basicTeam.id);
|
||||
done();
|
||||
});
|
||||
|
||||
Actions.selectTeam(TestHelper.basicTeam)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
});
|
||||
359
test/actions/users.test.js
Normal file
359
test/actions/users.test.js
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import * as Actions from 'actions/users';
|
||||
import Client from 'client';
|
||||
import configureStore from 'store/configureStore';
|
||||
import {RequestStatus} from 'constants';
|
||||
import TestHelper from 'test_helper';
|
||||
|
||||
describe('Actions.Users', () => {
|
||||
it('login', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const loginRequest = store.getState().requests.users.login;
|
||||
const currentUserId = store.getState().entities.users.currentId;
|
||||
const profiles = store.getState().entities.users.profiles;
|
||||
const preferences = store.getState().entities.users.myPreferences;
|
||||
|
||||
// TODO: uncomment when PLT-4167 is merged
|
||||
// const teamMembers = store.getState().entities.teams.myMembers;
|
||||
|
||||
if (loginRequest.status === RequestStatus.SUCCESS || loginRequest.status === RequestStatus.FAILURE) {
|
||||
if (loginRequest.error) {
|
||||
done(new Error(JSON.stringify(loginRequest.error)));
|
||||
} else {
|
||||
assert.ok(currentUserId);
|
||||
assert.ok(profiles);
|
||||
assert.ok(profiles.items[currentUserId]);
|
||||
assert.ok(Object.keys(preferences).length);
|
||||
|
||||
// TODO: uncomment when PLT-4167 is merged
|
||||
// Object.keys(teamMembers).forEach((id) => {
|
||||
// assert.ok(teamMembers[id].team_id);
|
||||
// assert.equal(teamMembers[id].user_id, currentUserId);
|
||||
// });
|
||||
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const user = TestHelper.basicUser;
|
||||
await TestHelper.basicClient.logout();
|
||||
Actions.login(user.email, 'password1')(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('logout', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const logoutRequest = store.getState().requests.users.logout;
|
||||
const general = store.getState().entities.general;
|
||||
const users = store.getState().entities.users;
|
||||
const loginView = store.getState().views.login;
|
||||
const teams = store.getState().entities.teams;
|
||||
const channels = store.getState().entities.channels;
|
||||
const posts = store.getState().entities.posts;
|
||||
|
||||
if (logoutRequest.status === RequestStatus.SUCCESS || logoutRequest.status === RequestStatus.FAILURE) {
|
||||
if (logoutRequest.error) {
|
||||
done(new Error(JSON.stringify(logoutRequest.error)));
|
||||
} else {
|
||||
assert.deepStrictEqual(general.config, {}, 'config not empty');
|
||||
assert.deepStrictEqual(general.license, {}, 'license not empty');
|
||||
assert.strictEqual(users.currentId, '', 'current user id not empty');
|
||||
assert.deepStrictEqual(users.myPreferences, {}, 'user preferences not empty');
|
||||
assert.deepStrictEqual(users.mySessions, [], 'user sessions not empty');
|
||||
assert.deepStrictEqual(users.myAudits, [], 'user audits not empty');
|
||||
assert.deepStrictEqual(users.profiles, {items: {}, offset: 0, count: 0}, 'user profiles not empty');
|
||||
assert.deepStrictEqual(users.profilesInTeam, {items: new Set(), offset: 0, count: 0}, 'users profiles in team not empty');
|
||||
assert.deepStrictEqual(users.profilesInChannel, {items: new Set(), offset: 0, count: 0}, 'users profiles in channel not empty');
|
||||
assert.deepStrictEqual(users.profilesNotInChannel, {items: new Set(), offset: 0, count: 0}, 'users profiles NOT in channel not empty');
|
||||
assert.deepStrictEqual(users.statuses, {}, 'users statuses not empty');
|
||||
assert.strictEqual(loginView.loginId, '', 'login id not empty');
|
||||
assert.strictEqual(loginView.password, '', 'password not empty');
|
||||
assert.strictEqual(teams.currentId, '', 'current team id is not empty');
|
||||
assert.deepStrictEqual(teams.teams, {}, 'teams is not empty');
|
||||
assert.deepStrictEqual(teams.myMembers, {}, 'team members is not empty');
|
||||
assert.deepStrictEqual(teams.membersInTeam, {}, 'members in team is not empty');
|
||||
assert.deepStrictEqual(teams.membersNotInTeam, {}, 'members NOT in team is not empty');
|
||||
assert.deepStrictEqual(teams.stats, {}, 'team stats is not empty');
|
||||
assert.deepStrictEqual(teams.openTeamIds, new Set(), 'team open ids is not empty');
|
||||
assert.strictEqual(channels.currentId, '', 'current channel id is not empty');
|
||||
assert.deepStrictEqual(channels.channels, {}, 'channels is not empty');
|
||||
assert.deepStrictEqual(channels.myMembers, {}, 'channel members is not empty');
|
||||
assert.deepStrictEqual(channels.moreChannels, {}, 'more channels is not empty');
|
||||
assert.deepStrictEqual(channels.stats, {}, 'channel stats is not empty');
|
||||
assert.strictEqual(posts.selectedPostId, '', 'selected post id is not empty');
|
||||
assert.strictEqual(posts.currentFocusedPostId, '', 'current focused post id is not empty');
|
||||
assert.deepStrictEqual(posts.postsInfo, {}, 'posts info is not empty');
|
||||
assert.deepStrictEqual(posts.latestPageTime, {}, 'posts latest page time is not empty');
|
||||
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Actions.logout()(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('getProfiles', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
const user = await TestHelper.basicClient.createUser(TestHelper.fakeUser());
|
||||
|
||||
store.subscribe(() => {
|
||||
const profilesRequest = store.getState().requests.users.getProfiles;
|
||||
const profiles = store.getState().entities.users.profiles;
|
||||
|
||||
if (profilesRequest.status === RequestStatus.SUCCESS || profilesRequest.status === RequestStatus.FAILURE) {
|
||||
if (profilesRequest.error) {
|
||||
done(new Error(JSON.stringify(profilesRequest.error)));
|
||||
} else {
|
||||
assert.strictEqual(profiles.offset, 0, 'offset should be 0');
|
||||
assert.strictEqual(profiles.count, 0, 'count should be 0');
|
||||
assert.ok(profiles.items[user.id]);
|
||||
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getProfiles(0)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('getProfilesInTeam', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const profilesRequest = store.getState().requests.users.getProfilesInTeam;
|
||||
const profilesInTeam = store.getState().entities.users.profilesInTeam;
|
||||
const profiles = store.getState().entities.users.profiles;
|
||||
|
||||
if (profilesRequest.status === RequestStatus.SUCCESS || profilesRequest.status === RequestStatus.FAILURE) {
|
||||
if (profilesRequest.error) {
|
||||
done(new Error(JSON.stringify(profilesRequest.error)));
|
||||
} else {
|
||||
assert.ok(profilesInTeam.offset > 0, 'offset should be > 0');
|
||||
assert.ok(profilesInTeam.count > 0, 'count should be > 0');
|
||||
assert.equal(profilesInTeam.count, profilesInTeam.items.size, 'count should be equal to the amount of profiles');
|
||||
assert.ok(profilesInTeam.items.has(TestHelper.basicUser.id));
|
||||
assert.equal(Object.keys(profiles.items).length, profilesInTeam.count, 'profiles != profiles in team');
|
||||
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getProfilesInTeam(TestHelper.basicTeam.id, 0)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('getProfilesInChannel', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const profilesRequest = store.getState().requests.users.getProfilesInChannel;
|
||||
const profilesInChannel = store.getState().entities.users.profilesInChannel;
|
||||
const profiles = store.getState().entities.users.profiles;
|
||||
|
||||
if (profilesRequest.status === RequestStatus.SUCCESS || profilesRequest.status === RequestStatus.FAILURE) {
|
||||
if (profilesRequest.error) {
|
||||
done(new Error(JSON.stringify(profilesRequest.error)));
|
||||
} else {
|
||||
assert.ok(profilesInChannel.offset > 0, 'offset should be > 0');
|
||||
assert.ok(profilesInChannel.count > 0, 'count should be > 0');
|
||||
assert.equal(profilesInChannel.count, profilesInChannel.items.size, 'count should be equal to the amount of profiles');
|
||||
assert.ok(profilesInChannel.items.has(TestHelper.basicUser.id));
|
||||
assert.equal(Object.keys(profiles.items).length, profilesInChannel.count, 'profiles != profiles in channel');
|
||||
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getProfilesInChannel(TestHelper.basicTeam.id, TestHelper.basicChannel.id, 0)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('getProfilesNotInChannel', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const profilesRequest = store.getState().requests.users.getProfilesNotInChannel;
|
||||
const profilesNotInChannel = store.getState().entities.users.profilesNotInChannel;
|
||||
const profiles = store.getState().entities.users.profiles;
|
||||
|
||||
if (profilesRequest.status === RequestStatus.SUCCESS || profilesRequest.status === RequestStatus.FAILURE) {
|
||||
if (profilesRequest.error) {
|
||||
done(new Error(JSON.stringify(profilesRequest.error)));
|
||||
} else {
|
||||
assert.ok(profilesNotInChannel.offset > 0, 'offset should be > 0');
|
||||
assert.ok(profilesNotInChannel.count > 0, 'count should be > 0');
|
||||
assert.equal(profilesNotInChannel.count, profilesNotInChannel.items.size, 'count should be equal to the amount of profiles');
|
||||
assert.ok(profilesNotInChannel.items.has(TestHelper.basicUser.id));
|
||||
assert.equal(Object.keys(profiles.items).length, profilesNotInChannel.count, 'profiles != profiles in channel');
|
||||
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getProfilesNotInChannel(TestHelper.basicTeam.id, TestHelper.basicChannel.id, 0)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('getStatusesByIds', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
const user = await TestHelper.basicClient.createUser(TestHelper.fakeUser());
|
||||
|
||||
store.subscribe(() => {
|
||||
const statusesRequest = store.getState().requests.users.getStatusesByIds;
|
||||
const statuses = store.getState().entities.users.statuses;
|
||||
|
||||
if (statusesRequest.status === RequestStatus.SUCCESS || statusesRequest.status === RequestStatus.FAILURE) {
|
||||
if (statusesRequest.error) {
|
||||
done(new Error(JSON.stringify(statusesRequest.error)));
|
||||
} else {
|
||||
assert.ok(statuses[TestHelper.basicUser.id]);
|
||||
assert.ok(statuses[user.id]);
|
||||
assert.equal(Object.keys(statuses).length, 2);
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getStatusesByIds([TestHelper.basicUser.id, user.id])(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('getSessions', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const sessionsRequest = store.getState().requests.users.getSessions;
|
||||
const sessions = store.getState().entities.users.mySessions;
|
||||
|
||||
if (sessionsRequest.status === RequestStatus.SUCCESS || sessionsRequest.status === RequestStatus.FAILURE) {
|
||||
if (sessionsRequest.error) {
|
||||
done(new Error(JSON.stringify(sessionsRequest.error)));
|
||||
} else {
|
||||
assert.ok(sessions.length);
|
||||
assert.equal(sessions[0].user_id, TestHelper.basicUser.id);
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getSessions(TestHelper.basicUser.id)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('revokeSession', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const sessionsRequest = store.getState().requests.users.getSessions;
|
||||
const revokeRequest = store.getState().requests.users.revokeSession;
|
||||
const sessions = store.getState().entities.users.mySessions;
|
||||
|
||||
if (revokeRequest.status === RequestStatus.SUCCESS || revokeRequest.status === RequestStatus.FAILURE) {
|
||||
if (revokeRequest.error) {
|
||||
done(new Error(JSON.stringify(revokeRequest.error)));
|
||||
} else {
|
||||
assert.ok(sessions.length === 0);
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
if (sessionsRequest.status === RequestStatus.SUCCESS || sessionsRequest.status === RequestStatus.FAILURE) {
|
||||
if (sessionsRequest.error) {
|
||||
done(new Error(JSON.stringify(sessionsRequest.error)));
|
||||
} else if (revokeRequest.status === RequestStatus.NOT_STARTED) {
|
||||
Actions.revokeSession(sessions[0].id)(store.dispatch, store.getState);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getSessions(TestHelper.basicUser.id)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('revokeSession and logout', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const sessionsRequest = store.getState().requests.users.getSessions;
|
||||
const revokeRequest = store.getState().requests.users.revokeSession;
|
||||
const logoutRequest = store.getState().requests.users.logout;
|
||||
const profilesRequest = store.getState().requests.users.getProfiles;
|
||||
const sessions = store.getState().entities.users.mySessions;
|
||||
|
||||
if (logoutRequest.status === RequestStatus.SUCCESS || logoutRequest.status === RequestStatus.FAILURE) {
|
||||
if (logoutRequest.error) {
|
||||
done(new Error(JSON.stringify(logoutRequest.error)));
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
if (revokeRequest.status === RequestStatus.SUCCESS || revokeRequest.status === RequestStatus.FAILURE) {
|
||||
if (revokeRequest.error) {
|
||||
done(new Error(JSON.stringify(revokeRequest.error)));
|
||||
} else if (logoutRequest.status === RequestStatus.NOT_STARTED && profilesRequest.status === RequestStatus.NOT_STARTED) {
|
||||
Actions.getProfiles(0)(store.dispatch, store.getState);
|
||||
}
|
||||
}
|
||||
|
||||
if (sessionsRequest.status === RequestStatus.SUCCESS || sessionsRequest.status === RequestStatus.FAILURE) {
|
||||
if (sessionsRequest.error) {
|
||||
done(new Error(JSON.stringify(sessionsRequest.error)));
|
||||
} else if (revokeRequest.status === RequestStatus.NOT_STARTED) {
|
||||
Actions.revokeSession(sessions[0].id)(store.dispatch, store.getState);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getSessions(TestHelper.basicUser.id)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
||||
it('getAudits', (done) => {
|
||||
TestHelper.initBasic(Client).then(async () => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const auditsRequest = store.getState().requests.users.getAudits;
|
||||
const audits = store.getState().entities.users.myAudits;
|
||||
|
||||
if (auditsRequest.status === RequestStatus.SUCCESS || auditsRequest.status === RequestStatus.FAILURE) {
|
||||
if (auditsRequest.error) {
|
||||
done(new Error(JSON.stringify(auditsRequest.error)));
|
||||
} else {
|
||||
assert.ok(audits.length);
|
||||
assert.equal(audits[0].user_id, TestHelper.basicUser.id);
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Actions.getAudits(TestHelper.basicUser.id)(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
});
|
||||
33
test/actions/views/login.test.js
Normal file
33
test/actions/views/login.test.js
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import * as Actions from 'actions/views/login';
|
||||
import configureStore from 'store/configureStore';
|
||||
|
||||
describe('Actions.Views.Login', () => {
|
||||
it('handleLoginIdChanged', (done) => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const loginId = store.getState().views.login.loginId;
|
||||
assert.equal('email@example.com', loginId);
|
||||
done();
|
||||
});
|
||||
|
||||
Actions.handleLoginIdChanged('email@example.com')(store.dispatch, store.getState);
|
||||
});
|
||||
|
||||
it('handlePasswordChanged', (done) => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const password = store.getState().views.login.password;
|
||||
assert.equal('password', password);
|
||||
done();
|
||||
});
|
||||
|
||||
Actions.handlePasswordChanged('password')(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
21
test/actions/views/select_server.test.js
Normal file
21
test/actions/views/select_server.test.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import * as Actions from 'actions/views/select_server';
|
||||
import configureStore from 'store/configureStore';
|
||||
|
||||
describe('Actions.Views.SelectServer', () => {
|
||||
it('handleServerUrlChanged', (done) => {
|
||||
const store = configureStore();
|
||||
|
||||
store.subscribe(() => {
|
||||
const serverUrl = store.getState().views.selectServer.serverUrl;
|
||||
assert.equal('https://mattermost.example.com', serverUrl);
|
||||
done();
|
||||
});
|
||||
|
||||
Actions.handleServerUrlChanged('https://mattermost.example.com')(store.dispatch, store.getState);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import TestHelper from 'test_helper.js';
|
||||
|
||||
describe('Client', () => {
|
||||
it('doFetch', async () => {
|
||||
const client = TestHelper.createClient();
|
||||
|
||||
return client.doFetch(`${client.getGeneralRoute()}/ping`, {});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import TestHelper from 'test_helper.js';
|
||||
|
||||
describe('Client.Channel', () => {
|
||||
it('createChannel', async () => {
|
||||
const {client, team} = await TestHelper.initBasic();
|
||||
const channel = TestHelper.fakeChannel(team.id);
|
||||
|
||||
const rchannel = await client.createChannel(channel);
|
||||
|
||||
assert.ok(rchannel.id, 'id is empty');
|
||||
assert.equal(rchannel.name, channel.name, 'name doesn\'t match');
|
||||
assert.equal(rchannel.team_id, channel.team_id, 'team id doesn\'t match');
|
||||
});
|
||||
});
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import TestHelper from 'test_helper.js';
|
||||
|
||||
describe('Client.General', function() {
|
||||
it('getClientConfig', async () => {
|
||||
const {client} = await TestHelper.initBasic();
|
||||
|
||||
const clientConfig = await client.getClientConfig('foo');
|
||||
|
||||
assert.ok(clientConfig.Version);
|
||||
assert.ok(clientConfig.BuildNumber);
|
||||
assert.ok(clientConfig.BuildDate);
|
||||
assert.ok(clientConfig.BuildHash);
|
||||
});
|
||||
|
||||
it('getPing', async () => {
|
||||
const {client} = await TestHelper.initBasic();
|
||||
|
||||
await client.getPing();
|
||||
});
|
||||
|
||||
it('getPing - Invalid URL', async () => {
|
||||
const {client} = await TestHelper.initBasic();
|
||||
client.setUrl('https://example.com/fake/url');
|
||||
|
||||
let errored;
|
||||
try {
|
||||
await client.getPing();
|
||||
|
||||
errored = false;
|
||||
} catch (err) {
|
||||
errored = true;
|
||||
}
|
||||
|
||||
assert.ok(errored, 'should have errored');
|
||||
});
|
||||
|
||||
it('logClientError', async () => {
|
||||
const {client} = await TestHelper.initBasic();
|
||||
|
||||
await client.logClientError('this is a test');
|
||||
});
|
||||
});
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import TestHelper from 'test_helper.js';
|
||||
|
||||
describe('Client.Post', () => {
|
||||
it('createPost', async () => {
|
||||
const {
|
||||
client,
|
||||
channel,
|
||||
team
|
||||
} = await TestHelper.initBasic();
|
||||
const post = TestHelper.fakePost(channel.id);
|
||||
|
||||
const rpost = await client.createPost(team.id, post);
|
||||
|
||||
assert.ok(rpost.id, 'id is empty');
|
||||
});
|
||||
});
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import TestHelper from 'test_helper.js';
|
||||
|
||||
describe('Client.Team', () => {
|
||||
it('createTeam', async () => {
|
||||
const client = TestHelper.createClient();
|
||||
const team = TestHelper.fakeTeam();
|
||||
|
||||
const rteam = await client.createTeam(team);
|
||||
|
||||
assert.equal(rteam.id.length > 0, true);
|
||||
assert.equal(rteam.name, team.name);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
|
||||
import TestHelper from 'test_helper.js';
|
||||
|
||||
describe('Client.User', () => {
|
||||
it('createUser', async () => {
|
||||
const client = TestHelper.createClient();
|
||||
const user = TestHelper.fakeUser();
|
||||
|
||||
const ruser = await client.createUser(user);
|
||||
|
||||
assert.ok(ruser.id, 'id is empty');
|
||||
assert.equal(ruser.email, user.email, 'email addresses aren\'t equal');
|
||||
});
|
||||
|
||||
it('login', async () => {
|
||||
const client = TestHelper.createClient();
|
||||
const user = TestHelper.fakeUser();
|
||||
|
||||
user.password = 'password';
|
||||
await client.createUser(user);
|
||||
|
||||
const ruser = await client.login(user.email, user.password);
|
||||
|
||||
assert.ok(ruser.id, 'id is empty');
|
||||
assert.equal(ruser.email, user.email, 'email addresses aren\'t equal');
|
||||
assert.ok(!ruser.password, 'returned password should be empty');
|
||||
assert.ok(client.token, 'token is empty');
|
||||
});
|
||||
|
||||
it('getInitialLoad', async () => {
|
||||
const {client, user} = await TestHelper.initBasic();
|
||||
|
||||
const data = await client.getInitialLoad();
|
||||
|
||||
assert.ok(data.user.id.length, 'id is empty');
|
||||
assert.equal(data.user.id, user.id, 'user ids don\'t match');
|
||||
});
|
||||
});
|
||||
|
|
@ -1,268 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
import deepFreeze from 'deep-freeze';
|
||||
import TestHelper from 'test_helper.js';
|
||||
|
||||
import reduceChannel from 'reducers/channel';
|
||||
|
||||
import {ChannelTypes} from 'constants';
|
||||
|
||||
describe('reducers/channel.js', () => {
|
||||
it('initial state', () => {
|
||||
const store = reduceChannel(undefined, {type: ''});
|
||||
|
||||
const expected = {
|
||||
channels: {},
|
||||
channelIdsByTeamId: {},
|
||||
channelMembers: {}
|
||||
};
|
||||
|
||||
assert.deepEqual(store, expected, 'initial state of store');
|
||||
});
|
||||
|
||||
describe('CHANNEL_RECEIVED', () => {
|
||||
let store = deepFreeze(reduceChannel(undefined, {type: ''}));
|
||||
|
||||
const teamId = TestHelper.generateId();
|
||||
const channel1 = {
|
||||
id: TestHelper.generateId(),
|
||||
...TestHelper.fakeChannel(teamId)
|
||||
};
|
||||
const channel2 = {
|
||||
id: TestHelper.generateId(),
|
||||
...TestHelper.fakeChannel(teamId)
|
||||
};
|
||||
|
||||
it('first channel received', () => {
|
||||
store = reduceChannel(store, {
|
||||
type: ChannelTypes.CHANNEL_RECEIVED,
|
||||
channel: channel1
|
||||
});
|
||||
|
||||
assert.deepEqual(store.channels, {
|
||||
[channel1.id]: channel1
|
||||
});
|
||||
assert.deepEqual(store.channelIdsByTeamId, {
|
||||
[teamId]: {
|
||||
[channel1.id]: channel1.id
|
||||
}
|
||||
});
|
||||
assert.deepEqual(store.channelMembers, {});
|
||||
});
|
||||
|
||||
store = deepFreeze(store);
|
||||
|
||||
it('second channel received', () => {
|
||||
store = reduceChannel(store, {
|
||||
type: ChannelTypes.CHANNEL_RECEIVED,
|
||||
channel: channel2
|
||||
});
|
||||
|
||||
assert.deepEqual(store.channels, {
|
||||
[channel1.id]: channel1,
|
||||
[channel2.id]: channel2
|
||||
});
|
||||
assert.deepEqual(store.channelIdsByTeamId, {
|
||||
[teamId]: {
|
||||
[channel1.id]: channel1.id,
|
||||
[channel2.id]: channel2.id
|
||||
}
|
||||
});
|
||||
assert.deepEqual(store.channelMembers, {});
|
||||
});
|
||||
|
||||
store = deepFreeze(store);
|
||||
|
||||
const channel1a = {
|
||||
...channel1,
|
||||
name: channel1.name + 'test'
|
||||
};
|
||||
|
||||
it('first channel received again', () => {
|
||||
store = reduceChannel(store, {
|
||||
type: ChannelTypes.CHANNEL_RECEIVED,
|
||||
channel: channel1a
|
||||
});
|
||||
|
||||
assert.deepEqual(store.channels, {
|
||||
[channel1.id]: channel1a,
|
||||
[channel2.id]: channel2
|
||||
});
|
||||
assert.deepEqual(store.channelIdsByTeamId, {
|
||||
[teamId]: {
|
||||
[channel1.id]: channel1.id,
|
||||
[channel2.id]: channel2.id
|
||||
}
|
||||
});
|
||||
assert.deepEqual(store.channelMembers, {});
|
||||
});
|
||||
});
|
||||
|
||||
describe('CHANNELS_RECEIVED', () => {
|
||||
let store = deepFreeze(reduceChannel(undefined, {type: ''}));
|
||||
|
||||
const teamId = TestHelper.generateId();
|
||||
const channel1 = {
|
||||
id: TestHelper.generateId(),
|
||||
...TestHelper.fakeChannel(teamId)
|
||||
};
|
||||
const channel2 = {
|
||||
id: TestHelper.generateId(),
|
||||
...TestHelper.fakeChannel(teamId)
|
||||
};
|
||||
|
||||
it('first set of channels received', () => {
|
||||
store = reduceChannel(store, {
|
||||
type: ChannelTypes.CHANNELS_RECEIVED,
|
||||
channels: [channel1, channel2]
|
||||
});
|
||||
|
||||
assert.deepEqual(store.channels, {
|
||||
[channel1.id]: channel1,
|
||||
[channel2.id]: channel2
|
||||
});
|
||||
assert.deepEqual(store.channelIdsByTeamId, {
|
||||
[teamId]: {
|
||||
[channel1.id]: channel1.id,
|
||||
[channel2.id]: channel2.id
|
||||
}
|
||||
});
|
||||
assert.deepEqual(store.channelMembers, {});
|
||||
});
|
||||
|
||||
store = deepFreeze(store);
|
||||
|
||||
const channel2a = {
|
||||
...channel2,
|
||||
name: channel2.name + 'test'
|
||||
};
|
||||
const channel3 = {
|
||||
id: TestHelper.generateId(),
|
||||
...TestHelper.fakeChannel(teamId)
|
||||
};
|
||||
|
||||
it('second set of channels received', () => {
|
||||
store = reduceChannel(store, {
|
||||
type: ChannelTypes.CHANNELS_RECEIVED,
|
||||
channels: [channel2a, channel3]
|
||||
});
|
||||
|
||||
assert.deepEqual(store.channels, {
|
||||
[channel1.id]: channel1,
|
||||
[channel2.id]: channel2a,
|
||||
[channel3.id]: channel3
|
||||
});
|
||||
assert.deepEqual(store.channelIdsByTeamId, {
|
||||
[teamId]: {
|
||||
[channel1.id]: channel1.id,
|
||||
[channel2.id]: channel2.id,
|
||||
[channel3.id]: channel3.id
|
||||
}
|
||||
});
|
||||
assert.deepEqual(store.channelMembers, {});
|
||||
});
|
||||
});
|
||||
|
||||
describe('CHANNEL_MEMBER_RECEIVED', () => {
|
||||
let store = deepFreeze(reduceChannel(undefined, {type: ''}));
|
||||
|
||||
const member1 = TestHelper.fakeChannelMember(TestHelper.generateId(), TestHelper.generateId());
|
||||
const member2 = TestHelper.fakeChannelMember(TestHelper.generateId(), TestHelper.generateId());
|
||||
|
||||
it('first channel member received', () => {
|
||||
store = reduceChannel(store, {
|
||||
type: ChannelTypes.CHANNEL_MEMBER_RECEIVED,
|
||||
channelMember: member1
|
||||
});
|
||||
|
||||
assert.deepEqual(store.channels, {});
|
||||
assert.deepEqual(store.channelIdsByTeamId, {});
|
||||
assert.deepEqual(store.channelMembers, {
|
||||
[`${member1.channel_id}-${member1.user_id}`]: member1
|
||||
});
|
||||
});
|
||||
|
||||
store = deepFreeze(store);
|
||||
|
||||
it('second channel member received', () => {
|
||||
store = reduceChannel(store, {
|
||||
type: ChannelTypes.CHANNEL_MEMBER_RECEIVED,
|
||||
channelMember: member2
|
||||
});
|
||||
|
||||
assert.deepEqual(store.channels, {});
|
||||
assert.deepEqual(store.channelIdsByTeamId, {});
|
||||
assert.deepEqual(store.channelMembers, {
|
||||
[`${member1.channel_id}-${member1.user_id}`]: member1,
|
||||
[`${member2.channel_id}-${member2.user_id}`]: member2
|
||||
});
|
||||
});
|
||||
|
||||
store = deepFreeze(store);
|
||||
|
||||
const member1a = {
|
||||
...member1,
|
||||
roles: 'system_admin system_user'
|
||||
};
|
||||
|
||||
it('first channel member received again', () => {
|
||||
store = reduceChannel(store, {
|
||||
type: ChannelTypes.CHANNEL_MEMBER_RECEIVED,
|
||||
channelMember: member1a
|
||||
});
|
||||
|
||||
assert.deepEqual(store.channels, {});
|
||||
assert.deepEqual(store.channelIdsByTeamId, {});
|
||||
assert.deepEqual(store.channelMembers, {
|
||||
[`${member1.channel_id}-${member1.user_id}`]: member1a,
|
||||
[`${member2.channel_id}-${member2.user_id}`]: member2
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('CHANNEL_MEMBERS_RECEIVED', () => {
|
||||
let store = deepFreeze(reduceChannel(undefined, {type: ''}));
|
||||
|
||||
const member1 = TestHelper.fakeChannelMember(TestHelper.generateId(), TestHelper.generateId());
|
||||
const member2 = TestHelper.fakeChannelMember(TestHelper.generateId(), TestHelper.generateId());
|
||||
|
||||
it('first set of channel members received', () => {
|
||||
store = reduceChannel(store, {
|
||||
type: ChannelTypes.CHANNEL_MEMBERS_RECEIVED,
|
||||
channelMembers: [member1, member2]
|
||||
});
|
||||
|
||||
assert.deepEqual(store.channels, {});
|
||||
assert.deepEqual(store.channelIdsByTeamId, {});
|
||||
assert.deepEqual(store.channelMembers, {
|
||||
[`${member1.channel_id}-${member1.user_id}`]: member1,
|
||||
[`${member2.channel_id}-${member2.user_id}`]: member2
|
||||
});
|
||||
});
|
||||
|
||||
store = deepFreeze(store);
|
||||
|
||||
const member2a = {
|
||||
...member2,
|
||||
roles: 'system_admin system_user'
|
||||
};
|
||||
const member3 = TestHelper.fakeChannelMember(TestHelper.generateId(), TestHelper.generateId());
|
||||
|
||||
it('second set of channel members received', () => {
|
||||
store = reduceChannel(store, {
|
||||
type: ChannelTypes.CHANNEL_MEMBERS_RECEIVED,
|
||||
channelMembers: [member2a, member3]
|
||||
});
|
||||
|
||||
assert.deepEqual(store.channels, {});
|
||||
assert.deepEqual(store.channelIdsByTeamId, {});
|
||||
assert.deepEqual(store.channelMembers, {
|
||||
[`${member1.channel_id}-${member1.user_id}`]: member1,
|
||||
[`${member2.channel_id}-${member2.user_id}`]: member2a,
|
||||
[`${member3.channel_id}-${member3.user_id}`]: member3
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
import reduceDevice, {initState} from 'reducers/device';
|
||||
import {DeviceTypes} from 'constants';
|
||||
|
||||
describe('device reducer', () => {
|
||||
describe('Init', () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reduceDevice(store, {type: ''});
|
||||
expectedStore = {...initState};
|
||||
});
|
||||
it('should be initial state', () => {
|
||||
assert.equal(typeof store, 'object');
|
||||
});
|
||||
it('have a specifc initial state', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${DeviceTypes.DEVICE_REQUEST}`, () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reduceDevice(store, {
|
||||
type: DeviceTypes.DEVICE_REQUEST
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
loading: true
|
||||
};
|
||||
});
|
||||
it('should set status to fetching', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${DeviceTypes.DEVICE_SUCCESS}`, () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
const data = {some: 'data'};
|
||||
before(() => {
|
||||
store = reduceDevice(store, {
|
||||
type: DeviceTypes.DEVICE_SUCCESS,
|
||||
data
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
loading: false,
|
||||
data
|
||||
};
|
||||
});
|
||||
it('should set status to fetched and data', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${DeviceTypes.DEVICE_FAILURE}`, () => {
|
||||
let store;
|
||||
let error;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
error = {id: 'the.error.id', message: 'Something went wrong'};
|
||||
store = reduceDevice(store, {
|
||||
type: DeviceTypes.DEVICE_FAILURE,
|
||||
error
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
loading: false,
|
||||
error
|
||||
};
|
||||
});
|
||||
it('should set status to failed and error', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
// import assert from 'assert';
|
||||
// import reduceGeneral, {initState} from 'reducers/general';
|
||||
// import {GeneralTypes} from 'constants';
|
||||
|
||||
// const combinedState = {
|
||||
// clientConfig: {...initState},
|
||||
// ping: {...initState}
|
||||
// };
|
||||
|
||||
// describe('general reducer', () => {
|
||||
// describe('PING', () => {
|
||||
// describe('Init', () => {
|
||||
// let store;
|
||||
// let expectedStore;
|
||||
// before(() => {
|
||||
// store = reduceGeneral(store, {type: ''});
|
||||
// expectedStore = {...combinedState};
|
||||
// });
|
||||
// it('should be initial state', () => {
|
||||
// assert.equal(typeof store, 'object');
|
||||
// });
|
||||
// it('have a specifc initial state', () => {
|
||||
// assert.deepEqual(store, expectedStore);
|
||||
// });
|
||||
// });
|
||||
// describe(`when ${GeneralTypes.PING_REQUEST}`, () => {
|
||||
// let store;
|
||||
// let expectedStore;
|
||||
// before(() => {
|
||||
// store = reduceGeneral(store, {
|
||||
// type: GeneralTypes.PING_REQUEST
|
||||
// });
|
||||
// expectedStore = {
|
||||
// ...combinedState,
|
||||
// ping: {
|
||||
// ...combinedState.ping,
|
||||
// loading: true
|
||||
// }
|
||||
// };
|
||||
// });
|
||||
// it('should set status to fetching', () => {
|
||||
// assert.deepEqual(store, expectedStore);
|
||||
// });
|
||||
// });
|
||||
// describe(`when ${GeneralTypes.PING_SUCCESS}`, () => {
|
||||
// let store;
|
||||
// let expectedStore;
|
||||
// const data = {some: 'data'};
|
||||
// before(() => {
|
||||
// store = reduceGeneral(store, {
|
||||
// type: GeneralTypes.PING_SUCCESS,
|
||||
// data
|
||||
// });
|
||||
// expectedStore = {
|
||||
// ...combinedState,
|
||||
// ping: {
|
||||
// ...combinedState.ping,
|
||||
// data
|
||||
// }
|
||||
// };
|
||||
// });
|
||||
// it('should set status to fetched and data', () => {
|
||||
// assert.deepEqual(store, expectedStore);
|
||||
// });
|
||||
// });
|
||||
// describe(`when ${GeneralTypes.PING_FAILURE}`, () => {
|
||||
// let store;
|
||||
// let error;
|
||||
// let expectedStore;
|
||||
// before(() => {
|
||||
// error = {id: 'the.error.id', message: 'Something went wrong'};
|
||||
// store = reduceGeneral(store, {
|
||||
// type: GeneralTypes.PING_FAILURE,
|
||||
// error
|
||||
// });
|
||||
// expectedStore = {
|
||||
// ...combinedState,
|
||||
// ping: {
|
||||
// ...combinedState.ping,
|
||||
// error
|
||||
// }
|
||||
// };
|
||||
// });
|
||||
// it('should set status to failed and error', () => {
|
||||
// assert.deepEqual(store, expectedStore);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// describe('CLIENT_CONFIG', () => {
|
||||
// describe('Init', () => {
|
||||
// let store;
|
||||
// let expectedStore;
|
||||
// before(() => {
|
||||
// store = reduceGeneral(store, {type: ''});
|
||||
// expectedStore = {...combinedState};
|
||||
// });
|
||||
// it('should be initial state', () => {
|
||||
// assert.equal(typeof store, 'object');
|
||||
// });
|
||||
// it('have a specifc initial state', () => {
|
||||
// assert.deepEqual(store, expectedStore);
|
||||
// });
|
||||
// });
|
||||
// describe(`when ${GeneralTypes.CLIENT_CONFIG_REQUEST}`, () => {
|
||||
// let store;
|
||||
// let expectedStore;
|
||||
// before(() => {
|
||||
// store = reduceGeneral(store, {
|
||||
// type: GeneralTypes.CLIENT_CONFIG_REQUEST
|
||||
// });
|
||||
// expectedStore = {
|
||||
// ...combinedState,
|
||||
// clientConfig: {
|
||||
// ...combinedState.clientConfig,
|
||||
// loading: true
|
||||
// }
|
||||
// };
|
||||
// });
|
||||
// it('should set status to fetching', () => {
|
||||
// assert.deepEqual(store, expectedStore);
|
||||
// });
|
||||
// });
|
||||
// describe(`when ${GeneralTypes.CLIENT_CONFIG_SUCCESS}`, () => {
|
||||
// let store;
|
||||
// let expectedStore;
|
||||
// const data = {some: 'data'};
|
||||
// before(() => {
|
||||
// store = reduceGeneral(store, {
|
||||
// type: GeneralTypes.CLIENT_CONFIG_SUCCESS,
|
||||
// data
|
||||
// });
|
||||
// expectedStore = {
|
||||
// ...combinedState,
|
||||
// clientConfig: {
|
||||
// ...combinedState.clientConfig,
|
||||
// data
|
||||
// }
|
||||
// };
|
||||
// });
|
||||
// it('should set status to fetched and data', () => {
|
||||
// assert.deepEqual(store, expectedStore);
|
||||
// });
|
||||
// });
|
||||
// describe(`when ${GeneralTypes.CLIENT_CONFIG_FAILURE}`, () => {
|
||||
// let store;
|
||||
// let error;
|
||||
// let expectedStore;
|
||||
// before(() => {
|
||||
// error = {id: 'the.error.id', message: 'Something went wrong'};
|
||||
// store = reduceGeneral(store, {
|
||||
// type: GeneralTypes.CLIENT_CONFIG_FAILURE,
|
||||
// error
|
||||
// });
|
||||
// expectedStore = {
|
||||
// ...combinedState,
|
||||
// clientConfig: {
|
||||
// ...combinedState.clientConfig,
|
||||
// error
|
||||
// }
|
||||
// };
|
||||
// });
|
||||
// it('should set status to failed and error', () => {
|
||||
// assert.deepEqual(store, expectedStore);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
import reduceLogin, {initState} from 'reducers/login';
|
||||
import {LoginTypes} from 'constants';
|
||||
|
||||
describe('login reducer', () => {
|
||||
describe('Init', () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reduceLogin(store, {type: ''});
|
||||
expectedStore = {...initState};
|
||||
});
|
||||
it('should be initial state', () => {
|
||||
assert.equal(typeof store, 'object');
|
||||
});
|
||||
it('have a specifc initial state', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${LoginTypes.LOGIN_REQUEST}`, () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reduceLogin(store, {
|
||||
type: LoginTypes.LOGIN_REQUEST
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
status: 'fetching'
|
||||
};
|
||||
});
|
||||
it('should set status to fetching', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${LoginTypes.LOGIN_SUCCESS}`, () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reduceLogin(store, {
|
||||
type: LoginTypes.LOGIN_SUCCESS
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
status: 'fetched'
|
||||
};
|
||||
});
|
||||
it('should set status to fetched and data', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${LoginTypes.LOGIN_FAILURE}`, () => {
|
||||
let store;
|
||||
let error;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
error = {id: 'the.error.id', message: 'Something went wrong'};
|
||||
store = reduceLogin(store, {
|
||||
type: LoginTypes.LOGIN_FAILURE,
|
||||
error
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
status: 'failed',
|
||||
error
|
||||
};
|
||||
});
|
||||
it('should set status to failed and error', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
import reduceLogout, {initState} from 'reducers/logout';
|
||||
import {LogoutTypes} from 'constants';
|
||||
|
||||
describe('logout reducer', () => {
|
||||
describe('Init', () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reduceLogout(store, {type: ''});
|
||||
expectedStore = {...initState};
|
||||
});
|
||||
it('should be initial state', () => {
|
||||
assert.equal(typeof store, 'object');
|
||||
});
|
||||
it('have a specifc initial state', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${LogoutTypes.LOGOUT_REQUEST}`, () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reduceLogout(store, {
|
||||
type: LogoutTypes.LOGOUT_REQUEST
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
status: 'fetching'
|
||||
};
|
||||
});
|
||||
it('should set status to fetching', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${LogoutTypes.LOGOUT_SUCCESS}`, () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reduceLogout(store, {
|
||||
type: LogoutTypes.LOGOUT_SUCCESS
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
status: 'fetched'
|
||||
};
|
||||
});
|
||||
it('should set status to fetched and data', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${LogoutTypes.LOGOUT_FAILURE}`, () => {
|
||||
let store;
|
||||
let error;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
error = {id: 'the.error.id', message: 'Something went wrong'};
|
||||
store = reduceLogout(store, {
|
||||
type: LogoutTypes.LOGOUT_FAILURE,
|
||||
error
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
status: 'failed',
|
||||
error
|
||||
};
|
||||
});
|
||||
it('should set status to failed and error', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
import reducePosts, {initState} from 'reducers/posts';
|
||||
import {PostsTypes} from 'constants';
|
||||
|
||||
describe('posts reducer', () => {
|
||||
describe('Init', () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reducePosts(store, {type: ''});
|
||||
expectedStore = {...initState};
|
||||
});
|
||||
it('should be initial state', () => {
|
||||
assert.equal(typeof store, 'object');
|
||||
});
|
||||
it('have a specifc initial state', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${PostsTypes.FETCH_POSTS_REQUEST}`, () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reducePosts(store, {
|
||||
type: PostsTypes.FETCH_POSTS_REQUEST
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
status: 'fetching'
|
||||
};
|
||||
});
|
||||
it('should set status to fetching', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${PostsTypes.FETCH_POSTS_SUCCESS}`, () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
const data = {id: '1', attrs: 'attrs'};
|
||||
before(() => {
|
||||
store = reducePosts(store, {
|
||||
type: PostsTypes.FETCH_POSTS_SUCCESS,
|
||||
data: {
|
||||
posts: data
|
||||
}
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
status: 'fetched',
|
||||
data
|
||||
};
|
||||
});
|
||||
it('should set status to fetched and data', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${PostsTypes.FETCH_POSTS_FAILURE}`, () => {
|
||||
let store;
|
||||
let error;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
error = {id: 'the.error.id', message: 'Something went wrong'};
|
||||
store = reducePosts(store, {
|
||||
type: PostsTypes.FETCH_POSTS_FAILURE,
|
||||
error
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
status: 'failed',
|
||||
error
|
||||
};
|
||||
});
|
||||
it('should set status to failed and error', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
import reduceTeams, {initState} from 'reducers/teams';
|
||||
import {TeamsTypes} from 'constants';
|
||||
|
||||
describe('teams reducer', () => {
|
||||
describe('Init', () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reduceTeams(store, {type: ''});
|
||||
expectedStore = {...initState};
|
||||
});
|
||||
it('should be initial state', () => {
|
||||
assert.equal(typeof store, 'object');
|
||||
});
|
||||
it('have a specifc initial state', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${TeamsTypes.SELECT_TEAM}`, () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reduceTeams(store, {
|
||||
type: TeamsTypes.SELECT_TEAM,
|
||||
teamId: '1'
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
currentTeamId: '1'
|
||||
};
|
||||
});
|
||||
it('should set status to fetching', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${TeamsTypes.FETCH_TEAMS_REQUEST}`, () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reduceTeams(store, {
|
||||
type: TeamsTypes.FETCH_TEAMS_REQUEST
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
status: 'fetching'
|
||||
};
|
||||
});
|
||||
it('should set status to fetching', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${TeamsTypes.FETCH_TEAMS_SUCCESS}`, () => {
|
||||
let store;
|
||||
const data = {some: 'thing'};
|
||||
let expectedStore;
|
||||
before(() => {
|
||||
store = reduceTeams(store, {
|
||||
type: TeamsTypes.FETCH_TEAMS_SUCCESS,
|
||||
data
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
status: 'fetched',
|
||||
data
|
||||
};
|
||||
});
|
||||
it('should set status to fetched and data', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
describe(`when ${TeamsTypes.FETCH_TEAMS_FAILURE}`, () => {
|
||||
let store;
|
||||
let expectedStore;
|
||||
let error;
|
||||
before(() => {
|
||||
error = {id: 'the.error.id', message: 'Something went wrong'};
|
||||
store = reduceTeams(store, {
|
||||
type: TeamsTypes.FETCH_TEAMS_FAILURE,
|
||||
error
|
||||
});
|
||||
expectedStore = {
|
||||
...initState,
|
||||
status: 'failed',
|
||||
error
|
||||
};
|
||||
});
|
||||
it('should set status to failed and error', () => {
|
||||
assert.deepEqual(store, expectedStore);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
// See License.txt for license information.
|
||||
|
||||
import assert from 'assert';
|
||||
import Client from 'client/client.js';
|
||||
import Config from 'config/config.js';
|
||||
import Client from 'client/client';
|
||||
import Config from 'config';
|
||||
|
||||
const PASSWORD = 'password1';
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ class TestHelper {
|
|||
assertStatusOkay = (data) => {
|
||||
assert(data);
|
||||
assert(data.status === 'OK');
|
||||
}
|
||||
};
|
||||
|
||||
generateId = () => {
|
||||
// Implementation taken from http://stackoverflow.com/a/2117523
|
||||
|
|
@ -40,7 +40,7 @@ class TestHelper {
|
|||
});
|
||||
|
||||
return 'uid' + id;
|
||||
}
|
||||
};
|
||||
|
||||
createClient = () => {
|
||||
const client = new Client();
|
||||
|
|
@ -48,11 +48,11 @@ class TestHelper {
|
|||
client.setUrl(Config.DefaultServerUrl);
|
||||
|
||||
return client;
|
||||
}
|
||||
};
|
||||
|
||||
fakeEmail = () => {
|
||||
return 'success' + this.generateId() + '@simulator.amazonses.com';
|
||||
}
|
||||
};
|
||||
|
||||
fakeUser = () => {
|
||||
return {
|
||||
|
|
@ -61,19 +61,24 @@ class TestHelper {
|
|||
password: PASSWORD,
|
||||
username: this.generateId()
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
fakeTeam = () => {
|
||||
const name = this.generateId();
|
||||
let inviteId = this.generateId();
|
||||
if (inviteId.length > 32) {
|
||||
inviteId = inviteId.substring(0, 32);
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
display_name: `Unit Test ${name}`,
|
||||
type: 'O',
|
||||
email: this.fakeEmail(),
|
||||
allowed_domains: ''
|
||||
allowed_domains: '',
|
||||
invite_id: inviteId
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
fakeChannel = (teamId) => {
|
||||
const name = this.generateId();
|
||||
|
|
@ -84,7 +89,7 @@ class TestHelper {
|
|||
display_name: `Unit Test ${name}`,
|
||||
type: 'O'
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
fakeChannelMember = (userId, channelId) => {
|
||||
return {
|
||||
|
|
@ -93,14 +98,14 @@ class TestHelper {
|
|||
notify_props: {},
|
||||
roles: 'system_user'
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
fakePost = (channelId) => {
|
||||
return {
|
||||
channel_id: channelId,
|
||||
message: `Unit Test ${this.generateId()}`
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
initBasic = async (client = this.createClient()) => {
|
||||
client.setUrl(Config.DefaultServerUrl);
|
||||
|
|
@ -121,7 +126,7 @@ class TestHelper {
|
|||
channel: this.basicChannel,
|
||||
post: this.basicPost
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default new TestHelper();
|
||||
|
|
|
|||
Loading…
Reference in a new issue