feat(client): migrate layout/default to ts (#43866)

* chore: rename Default.js to default.tsx

* chore: refactor default layout to typescript

* use TFunction for type

Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>
This commit is contained in:
Ahmed Ghoneim
2021-12-08 20:20:20 +02:00
committed by GitHub
parent c19bf504b8
commit 4bdfb6794f
6 changed files with 48 additions and 54 deletions

View File

@ -26,7 +26,7 @@ import {
userByNameSelector, userByNameSelector,
fetchProfileForUser fetchProfileForUser
} from '../redux'; } from '../redux';
import { User } from '../redux/prop-types'; import { UserFetchState, User } from '../redux/prop-types';
import { certMap } from '../resources/cert-and-project-map'; import { certMap } from '../resources/cert-and-project-map';
import certificateMissingMessage from '../utils/certificate-missing-message'; import certificateMissingMessage from '../utils/certificate-missing-message';
import reallyWeirdErrorMessage from '../utils/really-weird-error-message'; import reallyWeirdErrorMessage from '../utils/really-weird-error-message';
@ -71,9 +71,7 @@ interface ShowCertificationProps {
}) => void; }) => void;
signedInUserName: string; signedInUserName: string;
user: User; user: User;
userFetchState: { userFetchState: UserFetchState;
complete: boolean;
};
userFullName: string; userFullName: string;
username: string; username: string;
} }
@ -96,7 +94,7 @@ const mapStateToProps = (state: unknown, props: ShowCertificationProps) => {
cert: Cert, cert: Cert,
fetchState: ShowCertificationProps['fetchState'], fetchState: ShowCertificationProps['fetchState'],
signedInUserName: string, signedInUserName: string,
userFetchState: ShowCertificationProps['userFetchState'], userFetchState: UserFetchState,
isDonating: boolean, isDonating: boolean,
user user
) => ({ ) => ({

View File

@ -22,6 +22,7 @@ import {
userSelector, userSelector,
reportUser reportUser
} from '../redux'; } from '../redux';
import { UserFetchState } from '../redux/prop-types';
interface ShowUserProps { interface ShowUserProps {
email: string; email: string;
@ -31,11 +32,7 @@ interface ShowUserProps {
reportDescription: string; reportDescription: string;
}) => void; }) => void;
t: TFunction; t: TFunction;
userFetchState: { userFetchState: UserFetchState;
pending: boolean;
complete: boolean;
errored: boolean;
};
username: string; username: string;
} }
@ -45,7 +42,7 @@ const mapStateToProps = createSelector(
userSelector, userSelector,
( (
isSignedIn, isSignedIn,
userFetchState: ShowUserProps['userFetchState'], userFetchState: UserFetchState,
{ email }: { email: string } { email }: { email: string }
) => ({ ) => ({
isSignedIn, isSignedIn,

View File

@ -1,10 +1,9 @@
import fontawesome from '@fortawesome/fontawesome'; import fontawesome from '@fortawesome/fontawesome';
import PropTypes from 'prop-types'; import React, { Component, ReactNode } from 'react';
import React, { Component } from 'react';
import Helmet from 'react-helmet'; import Helmet from 'react-helmet';
import { withTranslation } from 'react-i18next'; import { TFunction, withTranslation } from 'react-i18next';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'; import { bindActionCreators, Dispatch } from 'redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import latoBoldURL from '../../../static/fonts/lato/Lato-Bold.woff'; import latoBoldURL from '../../../static/fonts/lato/Lato-Bold.woff';
@ -23,9 +22,9 @@ import {
isServerOnlineSelector, isServerOnlineSelector,
userFetchStateSelector, userFetchStateSelector,
userSelector, userSelector,
usernameSelector,
executeGA executeGA
} from '../../redux'; } from '../../redux';
import { UserFetchState, User } from '../../redux/prop-types';
import Flash from '../Flash'; import Flash from '../Flash';
import { flashMessageSelector, removeFlashMessage } from '../Flash/redux'; import { flashMessageSelector, removeFlashMessage } from '../Flash/redux';
@ -38,35 +37,7 @@ import './fonts.css';
import './global.css'; import './global.css';
import './variables.css'; import './variables.css';
fontawesome.config = { fontawesome.config.autoAddCss = false;
autoAddCss: false
};
const propTypes = {
children: PropTypes.node.isRequired,
executeGA: PropTypes.func,
fetchState: PropTypes.shape({ pending: PropTypes.bool }),
fetchUser: PropTypes.func.isRequired,
flashMessage: PropTypes.shape({
id: PropTypes.string,
type: PropTypes.string,
message: PropTypes.string
}),
hasMessage: PropTypes.bool,
isOnline: PropTypes.bool.isRequired,
isServerOnline: PropTypes.bool.isRequired,
isSignedIn: PropTypes.bool,
onlineStatusChange: PropTypes.func.isRequired,
pathname: PropTypes.string.isRequired,
removeFlashMessage: PropTypes.func.isRequired,
serverStatusChange: PropTypes.func.isRequired,
showFooter: PropTypes.bool,
signedInUserName: PropTypes.string,
t: PropTypes.func.isRequired,
theme: PropTypes.string,
useTheme: PropTypes.bool,
user: PropTypes.object
};
const mapStateToProps = createSelector( const mapStateToProps = createSelector(
isSignedInSelector, isSignedInSelector,
@ -75,8 +46,14 @@ const mapStateToProps = createSelector(
isServerOnlineSelector, isServerOnlineSelector,
userFetchStateSelector, userFetchStateSelector,
userSelector, userSelector,
usernameSelector, (
(isSignedIn, flashMessage, isOnline, isServerOnline, fetchState, user) => ({ isSignedIn,
flashMessage,
isOnline: boolean,
isServerOnline: boolean,
fetchState: UserFetchState,
user: User
) => ({
isSignedIn, isSignedIn,
flashMessage, flashMessage,
hasMessage: !!flashMessage.message, hasMessage: !!flashMessage.message,
@ -88,7 +65,9 @@ const mapStateToProps = createSelector(
}) })
); );
const mapDispatchToProps = dispatch => type StateProps = ReturnType<typeof mapStateToProps>;
const mapDispatchToProps = (dispatch: Dispatch) =>
bindActionCreators( bindActionCreators(
{ {
fetchUser, fetchUser,
@ -100,7 +79,19 @@ const mapDispatchToProps = dispatch =>
dispatch dispatch
); );
class DefaultLayout extends Component { type DispatchProps = ReturnType<typeof mapDispatchToProps>;
interface DefaultLayoutProps extends StateProps, DispatchProps {
children: ReactNode;
pathname: string;
showFooter?: boolean;
t: TFunction;
useTheme?: boolean;
}
class DefaultLayout extends Component<DefaultLayoutProps> {
static displayName = 'DefaultLayout';
componentDidMount() { componentDidMount() {
const { isSignedIn, fetchUser, pathname, executeGA } = this.props; const { isSignedIn, fetchUser, pathname, executeGA } = this.props;
if (!isSignedIn) { if (!isSignedIn) {
@ -112,7 +103,7 @@ class DefaultLayout extends Component {
window.addEventListener('offline', this.updateOnlineStatus); window.addEventListener('offline', this.updateOnlineStatus);
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps: DefaultLayoutProps) {
const { pathname, executeGA } = this.props; const { pathname, executeGA } = this.props;
const { pathname: prevPathname } = prevProps; const { pathname: prevPathname } = prevProps;
if (pathname !== prevPathname) { if (pathname !== prevPathname) {
@ -230,9 +221,6 @@ class DefaultLayout extends Component {
} }
} }
DefaultLayout.displayName = 'DefaultLayout';
DefaultLayout.propTypes = propTypes;
export default connect( export default connect(
mapStateToProps, mapStateToProps,
mapDispatchToProps mapDispatchToProps

View File

@ -1,3 +1,3 @@
export { default as CertificationLayout } from './certification'; export { default as CertificationLayout } from './certification';
export { default as DefaultLayout } from './Default'; export { default as DefaultLayout } from './default';
export { default as LearnLayout } from './learn'; export { default as LearnLayout } from './learn';

View File

@ -9,6 +9,10 @@ declare module '*.svg' {
const content: string; const content: string;
export default content; export default content;
} }
declare module '*.woff' {
const url: string;
export default url;
}
declare module '*.png' { declare module '*.png' {
const content: string; const content: string;

View File

@ -347,3 +347,10 @@ export type ChallengeFile = {
}; };
export type ChallengeFiles = ChallengeFile[] | null; export type ChallengeFiles = ChallengeFile[] | null;
export interface UserFetchState {
pending: boolean;
complete: boolean;
errored: boolean;
error: string | null;
}