From f2e44f477cd089e663540119d8c3c6394f627da5 Mon Sep 17 00:00:00 2001 From: Jerko Steiner Date: Wed, 20 Mar 2019 16:57:41 +0500 Subject: [PATCH] Add better type checking when connecting components --- packages/client/src/actions/IAction.ts | 2 +- packages/client/src/login/LoginForm.tsx | 2 +- .../client/src/login/RegisterConnector.tsx | 6 +++-- packages/client/src/login/withForm.tsx | 7 ++++-- packages/client/src/redux/Connector.ts | 6 ++--- packages/client/src/team/TeamList.tsx | 15 ++++++------ packages/client/src/team/TeamManager.tsx | 18 +++++++-------- packages/client/src/team/TeamUserList.tsx | 23 ++++++++++++------- 8 files changed, 46 insertions(+), 33 deletions(-) diff --git a/packages/client/src/actions/IAction.ts b/packages/client/src/actions/IAction.ts index 0383d1f..15d05c5 100644 --- a/packages/client/src/actions/IAction.ts +++ b/packages/client/src/actions/IAction.ts @@ -1,7 +1,7 @@ // Maybe this won't be necessary after this is merged: // https://github.com/Microsoft/TypeScript/pull/29478 -export interface IAction { +export interface IAction { payload: Promise | T, type: ActionType } diff --git a/packages/client/src/login/LoginForm.tsx b/packages/client/src/login/LoginForm.tsx index 076c9b0..b06d300 100644 --- a/packages/client/src/login/LoginForm.tsx +++ b/packages/client/src/login/LoginForm.tsx @@ -7,7 +7,7 @@ import {Redirect} from '../components/Redirect' export interface ILoginFormProps { error?: string - onSubmit: () => Promise + onSubmit: () => void onChange: (name: string, value: string) => void data: ICredentials user?: IUser diff --git a/packages/client/src/login/RegisterConnector.tsx b/packages/client/src/login/RegisterConnector.tsx index 730b5d4..d781f2f 100644 --- a/packages/client/src/login/RegisterConnector.tsx +++ b/packages/client/src/login/RegisterConnector.tsx @@ -1,5 +1,5 @@ import {Connector} from '../redux/Connector' -import {ICredentials} from '@rondo/common' +import {INewUser} from '@rondo/common' import {ILoginState} from './LoginReducer' import {IStateSelector} from '../redux' import {LoginActions} from './LoginActions' @@ -7,9 +7,11 @@ import {RegisterForm} from './RegisterForm' import {bindActionCreators} from 'redux' import {withForm} from './withForm' -const defaultCredentials: ICredentials = { +const defaultCredentials: INewUser = { username: '', password: '', + firstName: '', + lastName: '', } export class RegisterConnector extends Connector { diff --git a/packages/client/src/login/withForm.tsx b/packages/client/src/login/withForm.tsx index 1ae8d44..badaeec 100644 --- a/packages/client/src/login/withForm.tsx +++ b/packages/client/src/login/withForm.tsx @@ -1,4 +1,5 @@ import React from 'react' +import {IAction} from '../actions' export interface IComponentProps { onSubmit: () => void @@ -9,7 +10,7 @@ export interface IComponentProps { } export interface IFormHOCProps { - onSubmit: (props: Data) => Promise + onSubmit: (props: Data) => IAction // TODO figure out what would happen if the underlying child component // would have the same required property as the HOC, like onSuccess? onSuccess?: () => void @@ -33,7 +34,9 @@ export function withForm>( handleSubmit = async (e: React.FormEvent) => { const {clearOnSuccess, onSuccess} = this.props e.preventDefault() - await this.props.onSubmit(this.state) + const promise = this.props.onSubmit(this.state) + console.log('aaaaaaaaa', promise) + await promise if (clearOnSuccess) { this.setState(initialState) } diff --git a/packages/client/src/redux/Connector.ts b/packages/client/src/redux/Connector.ts index 2775a77..ee27e1e 100644 --- a/packages/client/src/redux/Connector.ts +++ b/packages/client/src/redux/Connector.ts @@ -35,9 +35,9 @@ export abstract class Connector { protected wrap< State, - StateProps, - DispatchProps, - Props + Props, + StateProps extends Partial, + DispatchProps extends Partial, >( getLocalState: IStateSelector, mapStateToProps: (state: LocalState) => StateProps, diff --git a/packages/client/src/team/TeamList.tsx b/packages/client/src/team/TeamList.tsx index 8a0523d..bb9ea21 100644 --- a/packages/client/src/team/TeamList.tsx +++ b/packages/client/src/team/TeamList.tsx @@ -1,25 +1,26 @@ import React from 'react' +import {IAction} from '../actions' import {ITeam, ReadonlyRecord} from '@rondo/common' export interface ITeamListProps { teamsById: ReadonlyRecord, teamIds: ReadonlyArray, - onAddTeam: (params: {name: string}) => Promise - onRemoveTeam: (params: {id: number}) => Promise - onUpdateTeam: (params: {id: number, name: string}) => Promise + onAddTeam: (params: {name: string}) => IAction + onRemoveTeam: (params: {id: number}) => IAction + onUpdateTeam: (params: {id: number, name: string}) => IAction editTeamId: number } export interface ITeamProps { team: ITeam editTeamId: number // TODO handle edits via react-router params - onRemoveTeam: (params: {id: number}) => Promise - onUpdateTeam: (params: {id: number, name: string}) => Promise + onRemoveTeam: (params: {id: number}) => IAction + onUpdateTeam: (params: {id: number, name: string}) => IAction } export interface IAddTeamProps { - onAddTeam: (params: {name: string}) => Promise - onUpdateTeam: (params: {id: number, name: string}) => Promise + onAddTeam: (params: {name: string}) => IAction + onUpdateTeam: (params: {id: number, name: string}) => IAction team?: ITeam } diff --git a/packages/client/src/team/TeamManager.tsx b/packages/client/src/team/TeamManager.tsx index d325649..83d9a8d 100644 --- a/packages/client/src/team/TeamManager.tsx +++ b/packages/client/src/team/TeamManager.tsx @@ -1,19 +1,19 @@ import React from 'react' +import {IAction} from '../actions' import {ITeam, IUser, IUserInTeam, ReadonlyRecord} from '@rondo/common' import {TeamList} from './TeamList' import {TeamUserList} from './TeamUserList' -// import {Route} from 'react-router-dom' export interface ITeamManagerProps { - createTeam: (params: {name: string}) => Promise - updateTeam: (params: {id: number, name: string}) => Promise - removeTeam: (params: {id: number}) => Promise + createTeam: (params: {name: string}) => IAction + updateTeam: (params: {id: number, name: string}) => IAction + removeTeam: (params: {id: number}) => IAction - addUser: (params: {userId: number, teamId: number}) => Promise - removeUser: (params: {userId: number, teamId: number}) => Promise - fetchMyTeams: () => void - fetchUsersInTeam: () => void - findUserByEmail: (email: string) => Promise + addUser: (params: {userId: number, teamId: number, roleId: number}) => IAction + removeUser: (params: {userId: number, teamId: number}) => IAction + fetchMyTeams: () => IAction + fetchUsersInTeam: (params: {teamId: number}) => IAction + findUserByEmail: (email: string) => IAction teamsById: ReadonlyRecord teamIds: ReadonlyArray diff --git a/packages/client/src/team/TeamUserList.tsx b/packages/client/src/team/TeamUserList.tsx index 3b871fc..6bad0b5 100644 --- a/packages/client/src/team/TeamUserList.tsx +++ b/packages/client/src/team/TeamUserList.tsx @@ -1,15 +1,17 @@ import React from 'react' import {IUser, IUserInTeam, ReadonlyRecord} from '@rondo/common' +import {IAction} from '../actions' const EMPTY_ARRAY: ReadonlyArray = [] export interface ITeamUsersProps { // fetchMyTeams: () => void, - fetchUsersInTeam: (teamId: number) => void - findUserByEmail: (email: string) => Promise + fetchUsersInTeam: (params: {teamId: number}) => IAction + findUserByEmail: (email: string) => IAction - onAddUser: (params: {userId: number, teamId: number}) => Promise - onRemoveUser: (params: {userId: number, teamId: number}) => Promise + onAddUser: (params: {userId: number, teamId: number, roleId: number}) + => IAction + onRemoveUser: (params: {userId: number, teamId: number}) => IAction teamId: number userKeysByTeamId: ReadonlyRecord> @@ -22,8 +24,12 @@ export interface ITeamUserProps { } export interface IAddUserProps { - onAddUser: (params: {userId: number, teamId: number}) => Promise - onSearchUser: (email: string) => Promise + onAddUser: (params: { + userId: number, + teamId: number, + roleId: number, + }) => IAction + onSearchUser: (email: string) => IAction teamId: number } @@ -70,7 +76,7 @@ export class AddUser extends React.PureComponent { event.preventDefault() const {teamId} = this.props const {email} = this.state - const user = await this.props.onSearchUser(email) + const user = await this.props.onSearchUser(email).payload if (!user) { // TODO handle this better via 404 status code return @@ -78,6 +84,7 @@ export class AddUser extends React.PureComponent { await this.props.onAddUser({ teamId, userId: user.id, + roleId: 1, }) this.setState({email: '', user: undefined}) @@ -111,7 +118,7 @@ export class TeamUserList extends React.PureComponent { } async fetchUsersInTeam(teamId: number) { if (teamId) { - await this.props.fetchUsersInTeam(teamId) + await this.props.fetchUsersInTeam({teamId}) } } render() {