Chore: Migrate redux module createChannel to typescript (#3602)
* chore: migrate createChannel to ts and add tests * chore: fix naming * chore: add more types and remove mapDispatchToProps from components * remove todo * update tests * chore: migrate interface to reducer and fix errors on return * chore: insert IApplicationState to mapStateToProps state type * Remove spread * fix type * fix import and state type Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
parent
c442a8473d
commit
7ad900a515
|
@ -1,23 +0,0 @@
|
|||
import * as types from './actionsTypes';
|
||||
|
||||
export function createChannelRequest(data) {
|
||||
return {
|
||||
type: types.CREATE_CHANNEL.REQUEST,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
export function createChannelSuccess(data) {
|
||||
return {
|
||||
type: types.CREATE_CHANNEL.SUCCESS,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
export function createChannelFailure(err, isTeam) {
|
||||
return {
|
||||
type: types.CREATE_CHANNEL.FAILURE,
|
||||
err,
|
||||
isTeam
|
||||
};
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
import { Action } from 'redux';
|
||||
|
||||
import { TCreateChannelResult } from '../reducers/createChannel';
|
||||
import { CREATE_CHANNEL } from './actionsTypes';
|
||||
|
||||
interface ICreateChannelRequest extends Action {
|
||||
data: TCreateChannelResult;
|
||||
}
|
||||
|
||||
interface ICreateChannelSuccess extends Action {
|
||||
data: TCreateChannelResult;
|
||||
}
|
||||
|
||||
interface ICreateChannelFailure extends Action {
|
||||
err: any;
|
||||
isTeam: boolean;
|
||||
}
|
||||
|
||||
export type TActionCreateChannel = ICreateChannelRequest & ICreateChannelSuccess & ICreateChannelFailure;
|
||||
|
||||
export function createChannelRequest(data: TCreateChannelResult): ICreateChannelRequest {
|
||||
return {
|
||||
type: CREATE_CHANNEL.REQUEST,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
export function createChannelSuccess(data: TCreateChannelResult): ICreateChannelSuccess {
|
||||
return {
|
||||
type: CREATE_CHANNEL.SUCCESS,
|
||||
data
|
||||
};
|
||||
}
|
||||
|
||||
export function createChannelFailure(err: any, isTeam: boolean): ICreateChannelFailure {
|
||||
return {
|
||||
type: CREATE_CHANNEL.FAILURE,
|
||||
err,
|
||||
isTeam
|
||||
};
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
// ACTIONS
|
||||
import { TActionActiveUsers } from '../../actions/activeUsers';
|
||||
import { TActionCreateChannel } from '../../actions/createChannel';
|
||||
import { TActionCustomEmojis } from '../../actions/customEmojis';
|
||||
import { TActionEncryption } from '../../actions/encryption';
|
||||
import { TActionInviteLinks } from '../../actions/inviteLinks';
|
||||
|
@ -13,6 +14,7 @@ import { TActionUserTyping } from '../../actions/usersTyping';
|
|||
// REDUCERS
|
||||
import { IActiveUsers } from '../../reducers/activeUsers';
|
||||
import { IConnect } from '../../reducers/connect';
|
||||
import { ICreateChannel } from '../../reducers/createChannel';
|
||||
import { IEncryption } from '../../reducers/encryption';
|
||||
import { IInviteLinks } from '../../reducers/inviteLinks';
|
||||
import { IRoles } from '../../reducers/roles';
|
||||
|
@ -27,7 +29,7 @@ export interface IApplicationState {
|
|||
meteor: IConnect;
|
||||
server: IServer;
|
||||
selectedUsers: ISelectedUsers;
|
||||
createChannel: any;
|
||||
createChannel: ICreateChannel;
|
||||
app: any;
|
||||
room: any;
|
||||
rooms: any;
|
||||
|
@ -54,5 +56,6 @@ export type TApplicationActions = TActionActiveUsers &
|
|||
TActionEncryption &
|
||||
TActionSortPreferences &
|
||||
TActionUserTyping &
|
||||
TActionCreateChannel &
|
||||
TActionsShare &
|
||||
TActionServer;
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
import { CREATE_CHANNEL } from '../actions/actionsTypes';
|
||||
|
||||
const initialState = {
|
||||
isFetching: false,
|
||||
failure: false,
|
||||
result: {},
|
||||
error: {}
|
||||
};
|
||||
|
||||
export default function (state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case CREATE_CHANNEL.REQUEST:
|
||||
return {
|
||||
...state,
|
||||
isFetching: true,
|
||||
failure: false,
|
||||
error: {}
|
||||
};
|
||||
case CREATE_CHANNEL.SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
isFetching: false,
|
||||
failure: false,
|
||||
result: action.data
|
||||
};
|
||||
case CREATE_CHANNEL.FAILURE:
|
||||
return {
|
||||
...state,
|
||||
isFetching: false,
|
||||
failure: true,
|
||||
error: action.err
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
import { createChannelRequest, createChannelSuccess, createChannelFailure } from '../actions/createChannel';
|
||||
import { initialState } from './createChannel';
|
||||
import { mockedStore } from './mockedStore';
|
||||
|
||||
describe('test reducer', () => {
|
||||
const data = {
|
||||
name: 'test',
|
||||
users: ['diego', 'karla'],
|
||||
type: true,
|
||||
readOnly: true,
|
||||
broadcast: true,
|
||||
encrypted: true,
|
||||
isTeam: true,
|
||||
teamId: 'xxx'
|
||||
};
|
||||
|
||||
it('should return initial state', () => {
|
||||
const { createChannel } = mockedStore.getState();
|
||||
expect(createChannel).toEqual(initialState);
|
||||
});
|
||||
|
||||
it('should return correct createChannel state after dispatch createChannelRequest action', () => {
|
||||
mockedStore.dispatch(createChannelRequest(data));
|
||||
const { createChannel } = mockedStore.getState();
|
||||
expect(createChannel).toEqual({ isFetching: true, failure: false, error: {}, result: {} });
|
||||
});
|
||||
|
||||
it('should return correct createChannel state after dispatch createChannelSuccess action', () => {
|
||||
mockedStore.dispatch(createChannelSuccess(data));
|
||||
const { createChannel } = mockedStore.getState();
|
||||
expect(createChannel).toEqual({ isFetching: false, failure: false, result: { ...data }, error: {} });
|
||||
});
|
||||
|
||||
it('should return correct createChannel state after dispatch createChannelFailure action', () => {
|
||||
mockedStore.dispatch(createChannelFailure({ err: true }, true));
|
||||
const { createChannel } = mockedStore.getState();
|
||||
expect(createChannel).toEqual({
|
||||
isFetching: false,
|
||||
failure: true,
|
||||
result: { ...data },
|
||||
error: { err: true }
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,61 @@
|
|||
import { TApplicationActions } from '../definitions';
|
||||
import { CREATE_CHANNEL } from '../actions/actionsTypes';
|
||||
|
||||
interface ICreateChannelResult {
|
||||
name: string;
|
||||
users: string[];
|
||||
teamId: string;
|
||||
type: boolean;
|
||||
readOnly: boolean;
|
||||
encrypted: boolean;
|
||||
broadcast: boolean;
|
||||
isTeam: boolean;
|
||||
}
|
||||
|
||||
interface ICreateChannelResultOnlyGroup {
|
||||
group: boolean;
|
||||
}
|
||||
|
||||
export type TCreateChannelResult = ICreateChannelResult | ICreateChannelResultOnlyGroup;
|
||||
|
||||
export interface ICreateChannel {
|
||||
isFetching: boolean;
|
||||
failure: boolean;
|
||||
result: TCreateChannelResult | {};
|
||||
error: any;
|
||||
}
|
||||
|
||||
export const initialState: ICreateChannel = {
|
||||
isFetching: false,
|
||||
failure: false,
|
||||
result: {},
|
||||
error: {}
|
||||
};
|
||||
|
||||
export default function (state = initialState, action: TApplicationActions): ICreateChannel {
|
||||
switch (action.type) {
|
||||
case CREATE_CHANNEL.REQUEST:
|
||||
return {
|
||||
...state,
|
||||
isFetching: true,
|
||||
failure: false,
|
||||
error: {}
|
||||
};
|
||||
case CREATE_CHANNEL.SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
isFetching: false,
|
||||
failure: false,
|
||||
result: action.data
|
||||
};
|
||||
case CREATE_CHANNEL.FAILURE:
|
||||
return {
|
||||
...state,
|
||||
isFetching: false,
|
||||
failure: true,
|
||||
error: action.err
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
|
@ -1,16 +1,13 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Dispatch } from 'redux';
|
||||
import { StackNavigationProp } from '@react-navigation/stack';
|
||||
import { RouteProp } from '@react-navigation/native';
|
||||
import { FlatList, ScrollView, StyleSheet, Switch, Text, View, SwitchProps } from 'react-native';
|
||||
import { dequal } from 'dequal';
|
||||
|
||||
import * as List from '../containers/List';
|
||||
import TextInput from '../presentation/TextInput';
|
||||
import Loading from '../containers/Loading';
|
||||
import { createChannelRequest as createChannelRequestAction } from '../actions/createChannel';
|
||||
import { removeUser as removeUserAction } from '../actions/selectedUsers';
|
||||
import { createChannelRequest } from '../actions/createChannel';
|
||||
import { removeUser } from '../actions/selectedUsers';
|
||||
import KeyboardView from '../presentation/KeyboardView';
|
||||
import scrollPersistTaps from '../utils/scrollPersistTaps';
|
||||
import I18n from '../i18n';
|
||||
|
@ -26,6 +23,7 @@ import SafeAreaView from '../containers/SafeAreaView';
|
|||
import RocketChat from '../lib/rocketchat';
|
||||
import sharedStyles from './Styles';
|
||||
import { ChatsStackParamList } from '../stacks/types';
|
||||
import { IApplicationState, IBaseScreen } from '../definitions';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
|
@ -75,12 +73,6 @@ interface IOtherUser {
|
|||
fname: string;
|
||||
}
|
||||
|
||||
interface ICreateFunction extends Omit<ICreateChannelViewState, 'channelName' | 'permissions'> {
|
||||
name: string;
|
||||
users: string[];
|
||||
teamId: string;
|
||||
}
|
||||
|
||||
interface ICreateChannelViewState {
|
||||
channelName: string;
|
||||
type: boolean;
|
||||
|
@ -91,12 +83,8 @@ interface ICreateChannelViewState {
|
|||
permissions: boolean[];
|
||||
}
|
||||
|
||||
interface ICreateChannelViewProps {
|
||||
navigation: StackNavigationProp<ChatsStackParamList, 'CreateChannelView'>;
|
||||
route: RouteProp<ChatsStackParamList, 'CreateChannelView'>;
|
||||
interface ICreateChannelViewProps extends IBaseScreen<ChatsStackParamList, 'CreateChannelView'> {
|
||||
baseUrl: string;
|
||||
create: (data: ICreateFunction) => void;
|
||||
removeUser: (user: IOtherUser) => void;
|
||||
error: object;
|
||||
failure: boolean;
|
||||
isFetching: boolean;
|
||||
|
@ -107,7 +95,6 @@ interface ICreateChannelViewProps {
|
|||
token: string;
|
||||
roles: string[];
|
||||
};
|
||||
theme: string;
|
||||
teamId: string;
|
||||
createPublicChannelPermission: string[];
|
||||
createPrivateChannelPermission: string[];
|
||||
|
@ -223,7 +210,7 @@ class CreateChannelView extends React.Component<ICreateChannelViewProps, ICreate
|
|||
|
||||
submit = () => {
|
||||
const { channelName, type, readOnly, broadcast, encrypted, isTeam } = this.state;
|
||||
const { users: usersProps, isFetching, create } = this.props;
|
||||
const { users: usersProps, isFetching, dispatch } = this.props;
|
||||
|
||||
if (!channelName.trim() || isFetching) {
|
||||
return;
|
||||
|
@ -233,7 +220,7 @@ class CreateChannelView extends React.Component<ICreateChannelViewProps, ICreate
|
|||
const users = usersProps.map(user => user.name);
|
||||
|
||||
// create channel or team
|
||||
create({
|
||||
const data = {
|
||||
name: channelName,
|
||||
users,
|
||||
type,
|
||||
|
@ -242,15 +229,15 @@ class CreateChannelView extends React.Component<ICreateChannelViewProps, ICreate
|
|||
encrypted,
|
||||
isTeam,
|
||||
teamId: this.teamId!
|
||||
});
|
||||
|
||||
};
|
||||
dispatch(createChannelRequest(data));
|
||||
Review.pushPositiveEvent();
|
||||
};
|
||||
|
||||
removeUser = (user: IOtherUser) => {
|
||||
logEvent(events.CR_REMOVE_USER);
|
||||
const { removeUser } = this.props;
|
||||
removeUser(user);
|
||||
const { dispatch } = this.props;
|
||||
dispatch(removeUser(user));
|
||||
};
|
||||
|
||||
renderSwitch = ({ id, value, label, onValueChange, disabled = false }: ISwitch) => {
|
||||
|
@ -434,7 +421,7 @@ class CreateChannelView extends React.Component<ICreateChannelViewProps, ICreate
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: any) => ({
|
||||
const mapStateToProps = (state: IApplicationState) => ({
|
||||
baseUrl: state.server.server,
|
||||
isFetching: state.createChannel.isFetching,
|
||||
encryptionEnabled: state.encryption.enabled,
|
||||
|
@ -444,9 +431,4 @@ const mapStateToProps = (state: any) => ({
|
|||
createPrivateChannelPermission: state.permissions['create-p']
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||
create: (data: ICreateFunction) => dispatch(createChannelRequestAction(data)),
|
||||
removeUser: (user: IOtherUser) => dispatch(removeUserAction(user))
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(CreateChannelView));
|
||||
export default connect(mapStateToProps)(withTheme(CreateChannelView));
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
import React from 'react';
|
||||
import { StackNavigationOptions, StackNavigationProp } from '@react-navigation/stack';
|
||||
import { FlatList, StyleSheet, Text, View } from 'react-native';
|
||||
import { Dispatch } from 'redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { Q } from '@nozbe/watermelondb';
|
||||
import { StackNavigationOptions } from '@react-navigation/stack';
|
||||
import { dequal } from 'dequal';
|
||||
import React from 'react';
|
||||
import { FlatList, StyleSheet, Text, View } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import * as List from '../containers/List';
|
||||
import Touch from '../utils/touch';
|
||||
import database from '../lib/database';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import UserItem from '../presentation/UserItem';
|
||||
import I18n from '../i18n';
|
||||
import log, { events, logEvent } from '../utils/log';
|
||||
import SearchBox from '../containers/SearchBox';
|
||||
import { CustomIcon } from '../lib/Icons';
|
||||
import * as HeaderButton from '../containers/HeaderButton';
|
||||
import StatusBar from '../containers/StatusBar';
|
||||
import { themes } from '../constants/colors';
|
||||
import { withTheme } from '../theme';
|
||||
import Navigation from '../lib/Navigation';
|
||||
import { createChannelRequest } from '../actions/createChannel';
|
||||
import { goRoom } from '../utils/goRoom';
|
||||
import { themes } from '../constants/colors';
|
||||
import * as HeaderButton from '../containers/HeaderButton';
|
||||
import * as List from '../containers/List';
|
||||
import SafeAreaView from '../containers/SafeAreaView';
|
||||
import SearchBox from '../containers/SearchBox';
|
||||
import StatusBar from '../containers/StatusBar';
|
||||
import { IApplicationState, IBaseScreen, TSubscriptionModel } from '../definitions';
|
||||
import I18n from '../i18n';
|
||||
import database from '../lib/database';
|
||||
import { CustomIcon } from '../lib/Icons';
|
||||
import Navigation from '../lib/Navigation';
|
||||
import RocketChat from '../lib/rocketchat';
|
||||
import { compareServerVersion, methods } from '../lib/utils';
|
||||
import { TSubscriptionModel } from '../definitions';
|
||||
import UserItem from '../presentation/UserItem';
|
||||
import { withTheme } from '../theme';
|
||||
import { goRoom } from '../utils/goRoom';
|
||||
import log, { events, logEvent } from '../utils/log';
|
||||
import Touch from '../utils/touch';
|
||||
import sharedStyles from './Styles';
|
||||
|
||||
const QUERY_SIZE = 50;
|
||||
|
@ -74,11 +73,8 @@ interface INewMessageViewState {
|
|||
permissions: boolean[];
|
||||
}
|
||||
|
||||
interface INewMessageViewProps {
|
||||
navigation: StackNavigationProp<any, 'NewMessageView'>;
|
||||
create: (params: { group: boolean }) => void;
|
||||
interface INewMessageViewProps extends IBaseScreen<any, 'NewMessageView'> {
|
||||
maxUsers: number;
|
||||
theme: string;
|
||||
isMasterDetail: boolean;
|
||||
serverVersion: string;
|
||||
createTeamPermission: string[];
|
||||
|
@ -175,9 +171,9 @@ class NewMessageView extends React.Component<INewMessageViewProps, INewMessageVi
|
|||
|
||||
createGroupChat = () => {
|
||||
logEvent(events.NEW_MSG_CREATE_GROUP_CHAT);
|
||||
const { create, maxUsers, navigation } = this.props;
|
||||
const { dispatch, maxUsers, navigation } = this.props;
|
||||
navigation.navigate('SelectedUsersViewCreateChannel', {
|
||||
nextAction: () => create({ group: true }),
|
||||
nextAction: () => dispatch(createChannelRequest({ group: true })),
|
||||
buttonText: I18n.t('Create'),
|
||||
maxUsers
|
||||
});
|
||||
|
@ -337,10 +333,10 @@ class NewMessageView extends React.Component<INewMessageViewProps, INewMessageVi
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: any) => ({
|
||||
serverVersion: state.server.version,
|
||||
const mapStateToProps = (state: IApplicationState) => ({
|
||||
serverVersion: state.server.version as string,
|
||||
isMasterDetail: state.app.isMasterDetail,
|
||||
maxUsers: state.settings.DirectMesssage_maxUsers || 1,
|
||||
maxUsers: (state.settings.DirectMesssage_maxUsers as number) || 1,
|
||||
createTeamPermission: state.permissions['create-team'],
|
||||
createDirectMessagePermission: state.permissions['create-d'],
|
||||
createPublicChannelPermission: state.permissions['create-c'],
|
||||
|
@ -348,8 +344,4 @@ const mapStateToProps = (state: any) => ({
|
|||
createDiscussionPermission: state.permissions['start-discussion']
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch) => ({
|
||||
create: (params: { group: boolean }) => dispatch(createChannelRequest(params))
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(NewMessageView));
|
||||
export default connect(mapStateToProps)(withTheme(NewMessageView));
|
||||
|
|
Loading…
Reference in New Issue