-
Notifications
You must be signed in to change notification settings - Fork 3.9k
[TS migration] Migrate 'WorkspacePageWithSections' page to TypeScript #34391
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f5bf126
1b330c9
8071b7a
537f734
99ba295
7bedf19
be72cb5
a1409c1
c975738
016f612
5efe176
3b74a2a
08b57c0
93f450a
93656c3
bd9298d
e878e0f
b5602b2
866ed82
a292d26
88f0d0d
ee29a01
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -1,86 +1,70 @@ | ||||||||
| import lodashGet from 'lodash/get'; | ||||||||
| import PropTypes from 'prop-types'; | ||||||||
| import React, {useEffect, useRef} from 'react'; | ||||||||
| import type {RouteProp} from '@react-navigation/native'; | ||||||||
| import React, {useEffect, useMemo, useRef} from 'react'; | ||||||||
| import type {ReactNode} from 'react'; | ||||||||
| import {View} from 'react-native'; | ||||||||
| import {withOnyx} from 'react-native-onyx'; | ||||||||
| import _ from 'underscore'; | ||||||||
| import type {OnyxEntry} from 'react-native-onyx/lib/types'; | ||||||||
| import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; | ||||||||
| import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; | ||||||||
| import HeaderWithBackButton from '@components/HeaderWithBackButton'; | ||||||||
| import ScreenWrapper from '@components/ScreenWrapper'; | ||||||||
| import ScrollViewWithContext from '@components/ScrollViewWithContext'; | ||||||||
| import useNetwork from '@hooks/useNetwork'; | ||||||||
| import useThemeStyles from '@hooks/useThemeStyles'; | ||||||||
| import compose from '@libs/compose'; | ||||||||
| import BankAccount from '@libs/models/BankAccount'; | ||||||||
| import Navigation from '@libs/Navigation/Navigation'; | ||||||||
| import * as PolicyUtils from '@libs/PolicyUtils'; | ||||||||
| import * as ReimbursementAccountProps from '@pages/ReimbursementAccount/reimbursementAccountPropTypes'; | ||||||||
| import userPropTypes from '@pages/settings/userPropTypes'; | ||||||||
| import * as BankAccounts from '@userActions/BankAccounts'; | ||||||||
| import ONYXKEYS from '@src/ONYXKEYS'; | ||||||||
| import ROUTES from '@src/ROUTES'; | ||||||||
| import type {Route} from '@src/ROUTES'; | ||||||||
| import type {Policy, ReimbursementAccount, User} from '@src/types/onyx'; | ||||||||
| import {isEmptyObject} from '@src/types/utils/EmptyObject'; | ||||||||
| import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; | ||||||||
| import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; | ||||||||
|
|
||||||||
| const propTypes = { | ||||||||
| shouldSkipVBBACall: PropTypes.bool, | ||||||||
|
|
||||||||
| /** The text to display in the header */ | ||||||||
| headerText: PropTypes.string.isRequired, | ||||||||
|
|
||||||||
| /** The route object passed to this page from the navigator */ | ||||||||
| route: PropTypes.shape({ | ||||||||
| /** Each parameter passed via the URL */ | ||||||||
| params: PropTypes.shape({ | ||||||||
| /** The policyID that is being configured */ | ||||||||
| policyID: PropTypes.string.isRequired, | ||||||||
| }).isRequired, | ||||||||
| }).isRequired, | ||||||||
|
|
||||||||
| type WorkspacePageWithSectionsOnyxProps = { | ||||||||
| /** From Onyx */ | ||||||||
| /** Bank account attached to free plan */ | ||||||||
| reimbursementAccount: ReimbursementAccountProps.reimbursementAccountPropTypes, | ||||||||
| reimbursementAccount: OnyxEntry<ReimbursementAccount>; | ||||||||
|
|
||||||||
| /** User Data from Onyx */ | ||||||||
| user: userPropTypes, | ||||||||
| user: OnyxEntry<User>; | ||||||||
| }; | ||||||||
|
|
||||||||
| /** Main content of the page */ | ||||||||
| children: PropTypes.func, | ||||||||
| type WorkspacePageWithSectionsProps = WithPolicyAndFullscreenLoadingProps & | ||||||||
| WorkspacePageWithSectionsOnyxProps & { | ||||||||
| shouldSkipVBBACall?: boolean; | ||||||||
|
|
||||||||
| /** Content to be added as fixed footer */ | ||||||||
| footer: PropTypes.element, | ||||||||
| /** The text to display in the header */ | ||||||||
| headerText: string; | ||||||||
|
|
||||||||
| /** The guides call task ID to associate with the workspace page being shown */ | ||||||||
| guidesCallTaskID: PropTypes.string, | ||||||||
| /** The route object passed to this page from the navigator */ | ||||||||
| route: RouteProp<{params: {policyID: string}}>; | ||||||||
|
|
||||||||
| /** The route where we navigate when the user press the back button */ | ||||||||
| backButtonRoute: PropTypes.string, | ||||||||
| /** Main content of the page */ | ||||||||
| children: (hasVBA?: boolean, policyID?: string, isUsingECard?: boolean) => ReactNode; | ||||||||
|
|
||||||||
| /** Policy values needed in the component */ | ||||||||
| policy: PropTypes.shape({ | ||||||||
| name: PropTypes.string, | ||||||||
| }).isRequired, | ||||||||
| /** Content to be added as fixed footer */ | ||||||||
| footer?: ReactNode; | ||||||||
|
|
||||||||
| /** Option to use the default scroll view */ | ||||||||
| shouldUseScrollView: PropTypes.bool, | ||||||||
| /** The guides call task ID to associate with the workspace page being shown */ | ||||||||
| guidesCallTaskID: string; | ||||||||
|
|
||||||||
| /** Option to show the loading page while the API is calling */ | ||||||||
| shouldShowLoading: PropTypes.bool, | ||||||||
| }; | ||||||||
| /** The route where we navigate when the user press the back button */ | ||||||||
| backButtonRoute?: Route; | ||||||||
|
|
||||||||
| const defaultProps = { | ||||||||
| children: () => {}, | ||||||||
| user: {}, | ||||||||
| reimbursementAccount: ReimbursementAccountProps.reimbursementAccountDefaultProps, | ||||||||
| footer: null, | ||||||||
| guidesCallTaskID: '', | ||||||||
| shouldUseScrollView: false, | ||||||||
| shouldSkipVBBACall: false, | ||||||||
| backButtonRoute: '', | ||||||||
| shouldShowLoading: true, | ||||||||
| }; | ||||||||
| /** Option to use the default scroll view */ | ||||||||
| shouldUseScrollView?: boolean; | ||||||||
|
|
||||||||
| /** Option to show the loading page while the API is calling */ | ||||||||
| shouldShowLoading?: boolean; | ||||||||
|
|
||||||||
| /** Policy values needed in the component */ | ||||||||
| policy: OnyxEntry<Policy>; | ||||||||
| }; | ||||||||
|
|
||||||||
| function fetchData(skipVBBACal) { | ||||||||
| function fetchData(skipVBBACal?: boolean) { | ||||||||
| if (skipVBBACal) { | ||||||||
| return; | ||||||||
| } | ||||||||
|
|
@@ -89,28 +73,28 @@ function fetchData(skipVBBACal) { | |||||||
| } | ||||||||
|
|
||||||||
| function WorkspacePageWithSections({ | ||||||||
| backButtonRoute, | ||||||||
| children, | ||||||||
| footer, | ||||||||
| guidesCallTaskID, | ||||||||
| backButtonRoute = '', | ||||||||
| children = () => null, | ||||||||
| footer = null, | ||||||||
| guidesCallTaskID = '', | ||||||||
| headerText, | ||||||||
| policy, | ||||||||
| reimbursementAccount, | ||||||||
| reimbursementAccount = {}, | ||||||||
| route, | ||||||||
| shouldUseScrollView, | ||||||||
| shouldSkipVBBACall, | ||||||||
| shouldUseScrollView = false, | ||||||||
| shouldSkipVBBACall = false, | ||||||||
| user, | ||||||||
| shouldShowLoading, | ||||||||
| }) { | ||||||||
| shouldShowLoading = true, | ||||||||
| }: WorkspacePageWithSectionsProps) { | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add defaults to props.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updated! we have a same user prop on WorkspacePageWithSections page and TestToolMenu,On TestToolMenu component we're using default value defined on the page, so I have extracted App/src/components/TestToolMenu.tsx Lines 30 to 32 in 0ebc6e4
|
||||||||
| const styles = useThemeStyles(); | ||||||||
| useNetwork({onReconnect: () => fetchData(shouldSkipVBBACall)}); | ||||||||
|
|
||||||||
| const isLoading = lodashGet(reimbursementAccount, 'isLoading', true); | ||||||||
| const achState = lodashGet(reimbursementAccount, 'achData.state', ''); | ||||||||
| const isLoading = reimbursementAccount?.isLoading ?? true; | ||||||||
| const achState = reimbursementAccount?.achData?.state ?? ''; | ||||||||
| const isUsingECard = user?.isUsingExpensifyCard ?? false; | ||||||||
| const policyID = route.params.policyID; | ||||||||
| const policyName = policy?.name; | ||||||||
| const hasVBA = achState === BankAccount.STATE.OPEN; | ||||||||
| const isUsingECard = lodashGet(user, 'isUsingExpensifyCard', false); | ||||||||
| const policyID = lodashGet(route, 'params.policyID'); | ||||||||
| const policyName = lodashGet(policy, 'name'); | ||||||||
| const content = children(hasVBA, policyID, isUsingECard); | ||||||||
| const firstRender = useRef(true); | ||||||||
|
|
||||||||
|
|
@@ -123,6 +107,14 @@ function WorkspacePageWithSections({ | |||||||
| fetchData(shouldSkipVBBACall); | ||||||||
| }, [shouldSkipVBBACall]); | ||||||||
|
|
||||||||
| const shouldShow = useMemo(() => { | ||||||||
| if (isEmptyObject(policy)) { | ||||||||
| return true; | ||||||||
| } | ||||||||
|
|
||||||||
| return !PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPendingDeletePolicy(policy); | ||||||||
| }, [policy]); | ||||||||
|
Comment on lines
+110
to
+116
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NAB: IMO the code here don't justify a |
||||||||
|
|
||||||||
| return ( | ||||||||
| <ScreenWrapper | ||||||||
| includeSafeAreaPaddingBottom={false} | ||||||||
|
|
@@ -132,15 +124,15 @@ function WorkspacePageWithSections({ | |||||||
| > | ||||||||
| <FullPageNotFoundView | ||||||||
| onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)} | ||||||||
| shouldShow={_.isEmpty(policy) || !PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPendingDeletePolicy(policy)} | ||||||||
| subtitleKey={_.isEmpty(policy) ? undefined : 'workspace.common.notAuthorized'} | ||||||||
| shouldShow={shouldShow} | ||||||||
| subtitleKey={isEmptyObject(policy) ? undefined : 'workspace.common.notAuthorized'} | ||||||||
| > | ||||||||
| <HeaderWithBackButton | ||||||||
| title={headerText} | ||||||||
| subtitle={policyName} | ||||||||
| shouldShowGetAssistanceButton | ||||||||
| guidesCallTaskID={guidesCallTaskID} | ||||||||
| onBackButtonPress={() => Navigation.goBack(backButtonRoute || ROUTES.WORKSPACE_INITIAL.getRoute(policyID))} | ||||||||
| onBackButtonPress={() => Navigation.goBack(backButtonRoute ?? ROUTES.WORKSPACE_INITIAL.getRoute(policyID))} | ||||||||
| /> | ||||||||
| {(isLoading || firstRender.current) && shouldShowLoading ? ( | ||||||||
| <FullScreenLoadingIndicator style={[styles.flex1, styles.pRelative]} /> | ||||||||
|
|
@@ -164,18 +156,15 @@ function WorkspacePageWithSections({ | |||||||
| ); | ||||||||
| } | ||||||||
|
|
||||||||
| WorkspacePageWithSections.propTypes = propTypes; | ||||||||
| WorkspacePageWithSections.defaultProps = defaultProps; | ||||||||
| WorkspacePageWithSections.displayName = 'WorkspacePageWithSections'; | ||||||||
|
|
||||||||
| export default compose( | ||||||||
| withOnyx({ | ||||||||
| export default withPolicyAndFullscreenLoading( | ||||||||
| withOnyx<WorkspacePageWithSectionsProps, WorkspacePageWithSectionsOnyxProps>({ | ||||||||
| user: { | ||||||||
| key: ONYXKEYS.USER, | ||||||||
| }, | ||||||||
| reimbursementAccount: { | ||||||||
| key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, | ||||||||
| }, | ||||||||
| }), | ||||||||
| withPolicyAndFullscreenLoading, | ||||||||
| )(WorkspacePageWithSections); | ||||||||
| })(WorkspacePageWithSections), | ||||||||
| ); | ||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this change. Onyx props can be undefined so don't have to define a default value for them. Also, we should not put this value in CONST file.
Let's revert this change and not define any default value for user prop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, we will revert this change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have reverted the changes that we have added in this PR for USER_DEFAULT. For
src/components/TestToolMenu.tsxfile, we are not touching the USER_DEFAULT added by some other PR, please let me know if we need to update the USER_DEFAULT for this page to null