From 8ee9a050d35849b5690bdafa06de54552b7f801e Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Mon, 22 Jan 2024 15:45:14 +0000 Subject: [PATCH 01/16] [TS Migration] Migrate WorkspaceSettingsPage and WorkspaceSettingsCurrencyPage --- src/libs/UserUtils.ts | 2 +- ...e.js => WorkspaceSettingsCurrencyPage.tsx} | 75 ++++++------ ...tingsPage.js => WorkspaceSettingsPage.tsx} | 108 +++++++----------- .../withPolicyAndFullscreenLoading.tsx | 2 + 4 files changed, 82 insertions(+), 105 deletions(-) rename src/pages/workspace/{WorkspaceSettingsCurrencyPage.js => WorkspaceSettingsCurrencyPage.tsx} (54%) rename src/pages/workspace/{WorkspaceSettingsPage.js => WorkspaceSettingsPage.tsx} (66%) diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts index 6ec386679a32..30522efe0fe9 100644 --- a/src/libs/UserUtils.ts +++ b/src/libs/UserUtils.ts @@ -184,7 +184,7 @@ function getAvatarUrl(avatarURL: string, accountID: number): string { * Avatars uploaded by users will have a _128 appended so that the asset server returns a small version. * This removes that part of the URL so the full version of the image can load. */ -function getFullSizeAvatar(avatarSource: AvatarSource, accountID: number): AvatarSource { +function getFullSizeAvatar(avatarSource: AvatarSource, accountID?: number): AvatarSource { const source = getAvatar(avatarSource, accountID); if (typeof source !== 'string') { return source; diff --git a/src/pages/workspace/WorkspaceSettingsCurrencyPage.js b/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx similarity index 54% rename from src/pages/workspace/WorkspaceSettingsCurrencyPage.js rename to src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx index ce1e1d7b8966..d3fea9061191 100644 --- a/src/pages/workspace/WorkspaceSettingsCurrencyPage.js +++ b/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx @@ -1,64 +1,61 @@ -import PropTypes from 'prop-types'; import React, {useCallback, useState} from 'react'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import type {OnyxEntry} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; import useLocalize from '@hooks/useLocalize'; -import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as Policy from '@userActions/Policy'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import {policyDefaultProps, policyPropTypes} from './withPolicy'; +import type {Currency} from '@src/types/onyx'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; -const propTypes = { +type WorkspaceSettingsCurrentPageWithOnyxProps = { /** Constant, list of available currencies */ - currencyList: PropTypes.objectOf( - PropTypes.shape({ - /** Symbol of the currency */ - symbol: PropTypes.string.isRequired, - }), - ), - isLoadingReportData: PropTypes.bool, - ...policyPropTypes, + currencyList: OnyxEntry>; }; -const defaultProps = { - currencyList: {}, - isLoadingReportData: true, - ...policyDefaultProps, +type WorkspaceSettingsCurrentPageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceSettingsCurrentPageWithOnyxProps; + +type WorkspaceSettingsCurrencyPageSectionItem = { + text: string; + keyForList: string; + isSelected: boolean; }; -const getDisplayText = (currencyCode, currencySymbol) => `${currencyCode} - ${currencySymbol}`; +const getDisplayText = (currencyCode: string, currencySymbol: string) => `${currencyCode} - ${currencySymbol}`; -function WorkspaceSettingsCurrencyPage({currencyList, policy, isLoadingReportData}) { +function WorkspaceSettingsCurrencyPage({currencyList, policy, isLoadingReportData}: WorkspaceSettingsCurrentPageProps) { const {translate} = useLocalize(); const [searchText, setSearchText] = useState(''); const trimmedText = searchText.trim().toLowerCase(); - const currencyListKeys = _.keys(currencyList); + const currencyListKeys = Object.keys(currencyList ?? {}); - const filteredItems = _.filter(currencyListKeys, (currencyCode) => { - const currency = currencyList[currencyCode]; - return getDisplayText(currencyCode, currency.symbol).toLowerCase().includes(trimmedText); + const filteredItems = currencyListKeys.filter((currencyCode: string) => { + const currency = currencyList?.[currencyCode]; + return getDisplayText(currencyCode, currency?.symbol ?? '') + .toLowerCase() + .includes(trimmedText); }); let initiallyFocusedOptionKey; - const currencyItems = _.map(filteredItems, (currencyCode) => { - const currency = currencyList[currencyCode]; - const isSelected = policy.outputCurrency === currencyCode; + const currencyItems: WorkspaceSettingsCurrencyPageSectionItem[] = filteredItems.map((currencyCode: string) => { + const currency = currencyList?.[currencyCode]; + const isSelected = policy?.outputCurrency === currencyCode; if (isSelected) { initiallyFocusedOptionKey = currencyCode; } return { - text: getDisplayText(currencyCode, currency.symbol), + text: getDisplayText(currencyCode, currency?.symbol ?? ''), keyForList: currencyCode, isSelected, }; @@ -68,11 +65,11 @@ function WorkspaceSettingsCurrencyPage({currencyList, policy, isLoadingReportDat const headerMessage = searchText.trim() && !currencyItems.length ? translate('common.noResultsFound') : ''; - const onBackButtonPress = useCallback(() => Navigation.goBack(ROUTES.WORKSPACE_SETTINGS.getRoute(policy.id)), [policy.id]); + const onBackButtonPress = useCallback(() => Navigation.goBack(ROUTES.WORKSPACE_SETTINGS.getRoute(policy?.id ?? '')), [policy?.id]); - const onSelectCurrency = (item) => { - Policy.updateGeneralSettings(policy.id, policy.name, item.keyForList); - Navigation.goBack(ROUTES.WORKSPACE_SETTINGS.getRoute(policy.id)); + const onSelectCurrency = (item: WorkspaceSettingsCurrencyPageSectionItem) => { + Policy.updateGeneralSettings(policy?.id ?? '', policy?.name ?? '', item.keyForList); + Navigation.goBack(ROUTES.WORKSPACE_SETTINGS.getRoute(policy?.id ?? '')); }; return ( @@ -82,8 +79,8 @@ function WorkspaceSettingsCurrencyPage({currencyList, policy, isLoadingReportDat > Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)} - shouldShow={(_.isEmpty(policy) && !isLoadingReportData) || !PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPendingDeletePolicy(policy)} - subtitleKey={_.isEmpty(policy) ? undefined : 'workspace.common.notAuthorized'} + shouldShow={(isEmptyObject(policy) && !isLoadingReportData) || !PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPendingDeletePolicy(policy)} + subtitleKey={isEmptyObject(policy) ? undefined : 'workspace.common.notAuthorized'} > ({ currencyList: {key: ONYXKEYS.CURRENCY_LIST}, - }), -)(WorkspaceSettingsCurrencyPage); + })(WorkspaceSettingsCurrencyPage), +); diff --git a/src/pages/workspace/WorkspaceSettingsPage.js b/src/pages/workspace/WorkspaceSettingsPage.tsx similarity index 66% rename from src/pages/workspace/WorkspaceSettingsPage.js rename to src/pages/workspace/WorkspaceSettingsPage.tsx index 737a5f1b7cf6..84209d9ca4a3 100644 --- a/src/pages/workspace/WorkspaceSettingsPage.js +++ b/src/pages/workspace/WorkspaceSettingsPage.tsx @@ -1,9 +1,7 @@ -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; import React, {useCallback} from 'react'; import {Keyboard, View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; import Avatar from '@components/Avatar'; import AvatarWithImagePicker from '@components/AvatarWithImagePicker'; import FormProvider from '@components/Form/FormProvider'; @@ -11,13 +9,11 @@ import InputWrapper from '@components/Form/InputWrapper'; import * as Expensicons from '@components/Icon/Expensicons'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import {withNetwork} from '@components/OnyxProvider'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; -import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; +import useWindowDimensions from '@hooks/useWindowDimensions'; import Navigation from '@libs/Navigation/Navigation'; import * as ReportUtils from '@libs/ReportUtils'; import * as UserUtils from '@libs/UserUtils'; @@ -26,57 +22,42 @@ import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import withPolicy, {policyDefaultProps, policyPropTypes} from './withPolicy'; +import type {Currency} from '@src/types/onyx'; +import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import type {WithPolicyProps} from './withPolicy'; +import withPolicy from './withPolicy'; import WorkspacePageWithSections from './WorkspacePageWithSections'; -const propTypes = { +type WorkSpaceSettingsPageOnyxProps = { /** Constant, list of available currencies */ - currencyList: PropTypes.objectOf( - PropTypes.shape({ - /** Symbol of the currency */ - symbol: PropTypes.string.isRequired, - }), - ), + currencyList: OnyxEntry>; +}; - /** 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 WorkSpaceSettingsPageProps = WithPolicyProps & WorkSpaceSettingsPageOnyxProps; - ...policyPropTypes, - ...windowDimensionsPropTypes, -}; +type WorkSpaceSettingsPageErrors = {name?: string}; -const defaultProps = { - currencyList: {}, - ...policyDefaultProps, -}; +type WorkSpaceSettingsPageValues = {name: string}; -function WorkspaceSettingsPage({policy, currencyList, windowWidth, route}) { +function WorkspaceSettingsPage({policy, currencyList, route}: WorkSpaceSettingsPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); + const {windowWidth} = useWindowDimensions(); - const formattedCurrency = !_.isEmpty(policy) && !_.isEmpty(currencyList) ? `${policy.outputCurrency} - ${currencyList[policy.outputCurrency].symbol}` : ''; + const formattedCurrency = !isEmptyObject(policy) && !isEmptyObject(currencyList) ? `${policy?.outputCurrency ?? ''} - ${currencyList?.[policy?.outputCurrency ?? ''].symbol ?? ''}` : ''; const submit = useCallback( - (values) => { - if (policy.isPolicyUpdating) { - return; - } - - Policy.updateGeneralSettings(policy.id, values.name.trim(), policy.outputCurrency); + (values: WorkSpaceSettingsPageValues) => { + Policy.updateGeneralSettings(policy?.id ?? '', values.name.trim(), policy?.outputCurrency ?? ''); Keyboard.dismiss(); - Navigation.goBack(ROUTES.WORKSPACE_INITIAL.getRoute(policy.id)); + Navigation.goBack(ROUTES.WORKSPACE_INITIAL.getRoute(policy?.id ?? '')); }, - [policy.id, policy.isPolicyUpdating, policy.outputCurrency], + [policy?.id, policy?.outputCurrency], ); - const validate = useCallback((values) => { - const errors = {}; + const validate = useCallback((values: WorkSpaceSettingsPageValues) => { + const errors: WorkSpaceSettingsPageErrors = {}; const name = values.name.trim(); if (!ValidationUtils.isRequiredFulfilled(name)) { @@ -92,7 +73,7 @@ function WorkspaceSettingsPage({policy, currencyList, windowWidth, route}) { const onPressCurrency = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_SETTINGS_CURRENCY.getRoute(policy.id)), [policy.id]); - const policyName = lodashGet(policy, 'name', ''); + const policyName = policy?.name ?? ''; return ( - {(hasVBA) => ( + {(hasVBA: boolean) => ( + // @ts-expect-error TODO: Remove this once FormProvider (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript. ( Policy.updateWorkspaceAvatar(lodashGet(policy, 'id', ''), file)} - onImageRemoved={() => Policy.deleteWorkspaceAvatar(lodashGet(policy, 'id', ''))} + isUsingDefaultAvatar={!policy?.avatar ?? null} + onImageSelected={(file: File) => Policy.updateWorkspaceAvatar(policy?.id ?? '', file)} + onImageRemoved={() => Policy.deleteWorkspaceAvatar(policy?.id ?? '')} editorMaskImage={Expensicons.ImageCropSquareMask} - pendingAction={lodashGet(policy, 'pendingFields.avatar', null)} - errors={lodashGet(policy, 'errorFields.avatar', null)} - onErrorClose={() => Policy.clearAvatarErrors(policy.id)} - previewSource={UserUtils.getFullSizeAvatar(policy.avatar, '')} + pendingAction={policy?.pendingFields?.avatar ?? null} + errors={policy?.errorFields?.avatar ?? null} + onErrorClose={() => Policy.clearAvatarErrors(policy?.id ?? '')} + previewSource={UserUtils.getFullSizeAvatar(policy?.avatar ?? '')} headerTitle={translate('workspace.common.workspaceAvatar')} - originalFileName={policy.originalFileName} + originalFileName={policy?.originalFileName ?? ''} + // TODO: Remove the line below once AvatarWithImagePicker (https://github.com/Expensify/App/issues/25122) is migrated to TypeScript. + errorRowStyles={undefined} /> - + ({ currencyList: {key: ONYXKEYS.CURRENCY_LIST}, - }), - withNetwork(), -)(WorkspaceSettingsPage); + })(WorkspaceSettingsPage), +); diff --git a/src/pages/workspace/withPolicyAndFullscreenLoading.tsx b/src/pages/workspace/withPolicyAndFullscreenLoading.tsx index 892facb92823..93e10cc1760c 100644 --- a/src/pages/workspace/withPolicyAndFullscreenLoading.tsx +++ b/src/pages/workspace/withPolicyAndFullscreenLoading.tsx @@ -63,3 +63,5 @@ export default function withPolicyAndFullscreenLoading Date: Mon, 22 Jan 2024 15:57:32 +0000 Subject: [PATCH 02/16] [TS migration] TS error fix WorkspaceSettingsPage --- src/pages/workspace/WorkspaceSettingsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceSettingsPage.tsx b/src/pages/workspace/WorkspaceSettingsPage.tsx index 84209d9ca4a3..c05d0f2b1833 100644 --- a/src/pages/workspace/WorkspaceSettingsPage.tsx +++ b/src/pages/workspace/WorkspaceSettingsPage.tsx @@ -71,7 +71,7 @@ function WorkspaceSettingsPage({policy, currencyList, route}: WorkSpaceSettingsP return errors; }, []); - const onPressCurrency = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_SETTINGS_CURRENCY.getRoute(policy.id)), [policy.id]); + const onPressCurrency = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_SETTINGS_CURRENCY.getRoute(policy?.id ?? '')), [policy?.id]); const policyName = policy?.name ?? ''; From 456e38cd3c069a4ec372049cf5c3391ef02d4313 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Mon, 22 Jan 2024 16:38:18 +0000 Subject: [PATCH 03/16] [TS migration] Added default values on currencyList --- src/pages/workspace/WorkspaceSettingsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceSettingsPage.tsx b/src/pages/workspace/WorkspaceSettingsPage.tsx index c05d0f2b1833..c60c8c30175a 100644 --- a/src/pages/workspace/WorkspaceSettingsPage.tsx +++ b/src/pages/workspace/WorkspaceSettingsPage.tsx @@ -40,7 +40,7 @@ type WorkSpaceSettingsPageErrors = {name?: string}; type WorkSpaceSettingsPageValues = {name: string}; -function WorkspaceSettingsPage({policy, currencyList, route}: WorkSpaceSettingsPageProps) { +function WorkspaceSettingsPage({policy, currencyList = {}, route}: WorkSpaceSettingsPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const {windowWidth} = useWindowDimensions(); From 63f2976483687a52abcc10aa7993c87c95021268 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Mon, 22 Jan 2024 16:53:44 +0000 Subject: [PATCH 04/16] [TS migration] WorkspaceSettings code improvements --- src/ONYXKEYS.ts | 2 +- .../workspace/WorkspaceSettingsCurrencyPage.tsx | 12 ++++++------ src/pages/workspace/WorkspaceSettingsPage.tsx | 4 ++-- src/types/onyx/Currency.ts | 3 +++ src/types/onyx/index.ts | 2 ++ 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 40a43d8195de..973a12cd9fa3 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -376,7 +376,7 @@ type OnyxValues = { [ONYXKEYS.PERSONAL_DETAILS_LIST]: OnyxTypes.PersonalDetailsList; [ONYXKEYS.PRIVATE_PERSONAL_DETAILS]: OnyxTypes.PrivatePersonalDetails; [ONYXKEYS.TASK]: OnyxTypes.Task; - [ONYXKEYS.CURRENCY_LIST]: Record; + [ONYXKEYS.CURRENCY_LIST]: OnyxTypes.CurrencyList; [ONYXKEYS.UPDATE_AVAILABLE]: boolean; [ONYXKEYS.SCREEN_SHARE_REQUEST]: OnyxTypes.ScreenShareRequest; [ONYXKEYS.COUNTRY_CODE]: number; diff --git a/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx b/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx index d3fea9061191..a8ec31e6d9a8 100644 --- a/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx +++ b/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx @@ -11,17 +11,17 @@ import * as PolicyUtils from '@libs/PolicyUtils'; import * as Policy from '@userActions/Policy'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {Currency} from '@src/types/onyx'; +import type {CurrencyList} from '@src/types/onyx/Currency'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; -type WorkspaceSettingsCurrentPageWithOnyxProps = { +type WorkspaceSettingsCurrentPageOnyxProps = { /** Constant, list of available currencies */ - currencyList: OnyxEntry>; + currencyList: OnyxEntry; }; -type WorkspaceSettingsCurrentPageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceSettingsCurrentPageWithOnyxProps; +type WorkspaceSettingsCurrentPageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceSettingsCurrentPageOnyxProps; type WorkspaceSettingsCurrencyPageSectionItem = { text: string; @@ -31,7 +31,7 @@ type WorkspaceSettingsCurrencyPageSectionItem = { const getDisplayText = (currencyCode: string, currencySymbol: string) => `${currencyCode} - ${currencySymbol}`; -function WorkspaceSettingsCurrencyPage({currencyList, policy, isLoadingReportData}: WorkspaceSettingsCurrentPageProps) { +function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingReportData = true}: WorkspaceSettingsCurrentPageProps) { const {translate} = useLocalize(); const [searchText, setSearchText] = useState(''); const trimmedText = searchText.trim().toLowerCase(); @@ -106,7 +106,7 @@ function WorkspaceSettingsCurrencyPage({currencyList, policy, isLoadingReportDat WorkspaceSettingsCurrencyPage.displayName = 'WorkspaceSettingsCurrencyPage'; export default withPolicyAndFullscreenLoading( - withOnyx({ + withOnyx({ currencyList: {key: ONYXKEYS.CURRENCY_LIST}, })(WorkspaceSettingsCurrencyPage), ); diff --git a/src/pages/workspace/WorkspaceSettingsPage.tsx b/src/pages/workspace/WorkspaceSettingsPage.tsx index c60c8c30175a..5c04c252f0c4 100644 --- a/src/pages/workspace/WorkspaceSettingsPage.tsx +++ b/src/pages/workspace/WorkspaceSettingsPage.tsx @@ -22,7 +22,7 @@ import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {Currency} from '@src/types/onyx'; +import type {CurrencyList} from '@src/types/onyx'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type {WithPolicyProps} from './withPolicy'; @@ -31,7 +31,7 @@ import WorkspacePageWithSections from './WorkspacePageWithSections'; type WorkSpaceSettingsPageOnyxProps = { /** Constant, list of available currencies */ - currencyList: OnyxEntry>; + currencyList: OnyxEntry; }; type WorkSpaceSettingsPageProps = WithPolicyProps & WorkSpaceSettingsPageOnyxProps; diff --git a/src/types/onyx/Currency.ts b/src/types/onyx/Currency.ts index a4767403381f..eca20a6c534f 100644 --- a/src/types/onyx/Currency.ts +++ b/src/types/onyx/Currency.ts @@ -21,4 +21,7 @@ type Currency = { cacheBurst?: number; }; +type CurrencyList = Record; + export default Currency; +export type {CurrencyList} diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index e6d6c27fc818..6d8d2cd6c1bd 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -7,6 +7,7 @@ import type BlockedFromConcierge from './BlockedFromConcierge'; import type Card from './Card'; import type Credentials from './Credentials'; import type Currency from './Currency'; +import type {CurrencyList} from './Currency'; import type CustomStatusDraft from './CustomStatusDraft'; import type Download from './Download'; import type {AddDebitCardForm, DateOfBirthForm} from './Form'; @@ -78,6 +79,7 @@ export type { Card, Credentials, Currency, + CurrencyList, CustomStatusDraft, DateOfBirthForm, Download, From fb683a9b82c5488f2f35b34a24743f032b66b05f Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Mon, 22 Jan 2024 16:56:32 +0000 Subject: [PATCH 05/16] [TS Migration] WorkspaceSettingsPage ts error fix --- src/pages/workspace/WorkspaceSettingsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceSettingsPage.tsx b/src/pages/workspace/WorkspaceSettingsPage.tsx index 5c04c252f0c4..7fbd66420a8f 100644 --- a/src/pages/workspace/WorkspaceSettingsPage.tsx +++ b/src/pages/workspace/WorkspaceSettingsPage.tsx @@ -45,7 +45,7 @@ function WorkspaceSettingsPage({policy, currencyList = {}, route}: WorkSpaceSett const {translate} = useLocalize(); const {windowWidth} = useWindowDimensions(); - const formattedCurrency = !isEmptyObject(policy) && !isEmptyObject(currencyList) ? `${policy?.outputCurrency ?? ''} - ${currencyList?.[policy?.outputCurrency ?? ''].symbol ?? ''}` : ''; + const formattedCurrency = !isEmptyObject(policy) && !isEmptyObject(currencyList) ? `${policy?.outputCurrency ?? ''} - ${currencyList?.[policy?.outputCurrency ?? '']?.symbol ?? ''}` : ''; const submit = useCallback( (values: WorkSpaceSettingsPageValues) => { From cd50da3bc4532cadf6fdb01082f52518c0978f57 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Mon, 22 Jan 2024 16:58:05 +0000 Subject: [PATCH 06/16] [TS migration] WorkspaceSettings prettified --- src/pages/workspace/WorkspaceSettingsPage.tsx | 2 +- src/types/onyx/Currency.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/WorkspaceSettingsPage.tsx b/src/pages/workspace/WorkspaceSettingsPage.tsx index 7fbd66420a8f..c021f1541fe7 100644 --- a/src/pages/workspace/WorkspaceSettingsPage.tsx +++ b/src/pages/workspace/WorkspaceSettingsPage.tsx @@ -31,7 +31,7 @@ import WorkspacePageWithSections from './WorkspacePageWithSections'; type WorkSpaceSettingsPageOnyxProps = { /** Constant, list of available currencies */ - currencyList: OnyxEntry; + currencyList: OnyxEntry; }; type WorkSpaceSettingsPageProps = WithPolicyProps & WorkSpaceSettingsPageOnyxProps; diff --git a/src/types/onyx/Currency.ts b/src/types/onyx/Currency.ts index eca20a6c534f..b8d6f8dda88b 100644 --- a/src/types/onyx/Currency.ts +++ b/src/types/onyx/Currency.ts @@ -24,4 +24,4 @@ type Currency = { type CurrencyList = Record; export default Currency; -export type {CurrencyList} +export type {CurrencyList}; From 4f20d019df8f9f765598d1e5d68cc41877eb6f89 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Thu, 25 Jan 2024 10:00:27 +0000 Subject: [PATCH 07/16] [TS migration][WorkspaceSettings] Removed unused todo --- src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx b/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx index a8ec31e6d9a8..2d1019d5c598 100644 --- a/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx +++ b/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx @@ -88,7 +88,6 @@ function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingRepo /> Date: Wed, 31 Jan 2024 15:01:38 +0000 Subject: [PATCH 08/16] [TS migration][WorkspaceSettings] Updated typings based on main merge --- src/ONYXKEYS.ts | 2 +- src/pages/workspace/WorkspaceSettingsPage.tsx | 77 +++++++++---------- src/types/onyx/Form.ts | 3 + src/types/onyx/index.ts | 3 +- 4 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 487377331db6..c68e34ecd9d1 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -482,7 +482,7 @@ type OnyxValues = { // Forms [ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM]: OnyxTypes.AddDebitCardForm; [ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM_DRAFT]: OnyxTypes.AddDebitCardForm; - [ONYXKEYS.FORMS.WORKSPACE_SETTINGS_FORM]: OnyxTypes.Form; + [ONYXKEYS.FORMS.WORKSPACE_SETTINGS_FORM]: OnyxTypes.WorkspaceSettingsForm; [ONYXKEYS.FORMS.WORKSPACE_SETTINGS_FORM_DRAFT]: OnyxTypes.Form; [ONYXKEYS.FORMS.WORKSPACE_RATE_AND_UNIT_FORM]: OnyxTypes.Form; [ONYXKEYS.FORMS.WORKSPACE_RATE_AND_UNIT_FORM_DRAFT]: OnyxTypes.Form; diff --git a/src/pages/workspace/WorkspaceSettingsPage.tsx b/src/pages/workspace/WorkspaceSettingsPage.tsx index c021f1541fe7..cd2a59006baa 100644 --- a/src/pages/workspace/WorkspaceSettingsPage.tsx +++ b/src/pages/workspace/WorkspaceSettingsPage.tsx @@ -6,6 +6,7 @@ import Avatar from '@components/Avatar'; import AvatarWithImagePicker from '@components/AvatarWithImagePicker'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; +import type {OnyxFormValuesFields} from '@components/Form/types'; import * as Expensicons from '@components/Icon/Expensicons'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; @@ -38,8 +39,6 @@ type WorkSpaceSettingsPageProps = WithPolicyProps & WorkSpaceSettingsPageOnyxPro type WorkSpaceSettingsPageErrors = {name?: string}; -type WorkSpaceSettingsPageValues = {name: string}; - function WorkspaceSettingsPage({policy, currencyList = {}, route}: WorkSpaceSettingsPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -48,7 +47,7 @@ function WorkspaceSettingsPage({policy, currencyList = {}, route}: WorkSpaceSett const formattedCurrency = !isEmptyObject(policy) && !isEmptyObject(currencyList) ? `${policy?.outputCurrency ?? ''} - ${currencyList?.[policy?.outputCurrency ?? '']?.symbol ?? ''}` : ''; const submit = useCallback( - (values: WorkSpaceSettingsPageValues) => { + (values: OnyxFormValuesFields) => { Policy.updateGeneralSettings(policy?.id ?? '', values.name.trim(), policy?.outputCurrency ?? ''); Keyboard.dismiss(); Navigation.goBack(ROUTES.WORKSPACE_INITIAL.getRoute(policy?.id ?? '')); @@ -56,7 +55,7 @@ function WorkspaceSettingsPage({policy, currencyList = {}, route}: WorkSpaceSett [policy?.id, policy?.outputCurrency], ); - const validate = useCallback((values: WorkSpaceSettingsPageValues) => { + const validate = useCallback((values: OnyxFormValuesFields) => { const errors: WorkSpaceSettingsPageErrors = {}; const name = values.name.trim(); @@ -82,8 +81,7 @@ function WorkspaceSettingsPage({policy, currencyList = {}, route}: WorkSpaceSett guidesCallTaskID={CONST.GUIDES_CALL_TASK_IDS.WORKSPACE_SETTINGS} shouldShowLoading={false} > - {(hasVBA: boolean) => ( - // @ts-expect-error TODO: Remove this once FormProvider (https://github.com/Expensify/App/issues/31972) is migrated to TypeScript. + {(hasVBA?: boolean) => ( - ( - - )} - type={CONST.ICON_TYPE_WORKSPACE} - fallbackIcon={Expensicons.FallbackWorkspaceAvatar} - style={[styles.mb3]} - anchorPosition={styles.createMenuPositionProfile(windowWidth)} - anchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP}} - isUsingDefaultAvatar={!policy?.avatar ?? null} - onImageSelected={(file: File) => Policy.updateWorkspaceAvatar(policy?.id ?? '', file)} - onImageRemoved={() => Policy.deleteWorkspaceAvatar(policy?.id ?? '')} - editorMaskImage={Expensicons.ImageCropSquareMask} - pendingAction={policy?.pendingFields?.avatar ?? null} - errors={policy?.errorFields?.avatar ?? null} - onErrorClose={() => Policy.clearAvatarErrors(policy?.id ?? '')} - previewSource={UserUtils.getFullSizeAvatar(policy?.avatar ?? '')} - headerTitle={translate('workspace.common.workspaceAvatar')} - originalFileName={policy?.originalFileName ?? ''} - // TODO: Remove the line below once AvatarWithImagePicker (https://github.com/Expensify/App/issues/25122) is migrated to TypeScript. - errorRowStyles={undefined} - /> + { + // @ts-expect-error TODO: Remove this once AvatarWithImagePicker (https://github.com/Expensify/App/issues/25122) is migrated to TypeScript. + ( + + )} + type={CONST.ICON_TYPE_WORKSPACE} + fallbackIcon={Expensicons.FallbackWorkspaceAvatar} + style={[styles.mb3]} + anchorPosition={styles.createMenuPositionProfile(windowWidth)} + anchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP}} + isUsingDefaultAvatar={!policy?.avatar ?? null} + onImageSelected={(file: File) => Policy.updateWorkspaceAvatar(policy?.id ?? '', file)} + onImageRemoved={() => Policy.deleteWorkspaceAvatar(policy?.id ?? '')} + editorMaskImage={Expensicons.ImageCropSquareMask} + pendingAction={policy?.pendingFields?.avatar ?? null} + errors={policy?.errorFields?.avatar ?? null} + onErrorClose={() => Policy.clearAvatarErrors(policy?.id ?? '')} + previewSource={UserUtils.getFullSizeAvatar(policy?.avatar ?? '')} + headerTitle={translate('workspace.common.workspaceAvatar')} + originalFileName={policy?.originalFileName ?? ''} + errorRowStyles={undefined} + /> + } ; +type WorkspaceSettingsForm = Form<{name: string}>; + export default Form; export type { @@ -70,4 +72,5 @@ export type { IKnowATeacherForm, IntroSchoolPrincipalForm, PersonalBankAccountForm, + WorkspaceSettingsForm, }; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 20b0511dbf32..7346eecb2d45 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -10,7 +10,7 @@ import type Currency from './Currency'; import type {CurrencyList} from './Currency'; import type CustomStatusDraft from './CustomStatusDraft'; import type Download from './Download'; -import type {AddDebitCardForm, DateOfBirthForm, DisplayNameForm, IKnowATeacherForm, IntroSchoolPrincipalForm, NewRoomForm, PrivateNotesForm} from './Form'; +import type {AddDebitCardForm, DateOfBirthForm, DisplayNameForm, IKnowATeacherForm, IntroSchoolPrincipalForm, NewRoomForm, PrivateNotesForm, WorkspaceSettingsForm} from './Form'; import type Form from './Form'; import type FrequentlyUsedEmoji from './FrequentlyUsedEmoji'; import type {FundList} from './Fund'; @@ -153,4 +153,5 @@ export type { IKnowATeacherForm, IntroSchoolPrincipalForm, PrivateNotesForm, + WorkspaceSettingsForm, }; From b3450878189bdaf5157c57a011df8b9b2a482660 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Wed, 7 Feb 2024 16:21:11 +0000 Subject: [PATCH 09/16] [TS migration] Lint and ts fixes --- .../WorkspaceOverviewCurrencyPage.js | 122 ------------------ .../WorkspaceSettingsCurrencyPage.tsx | 13 -- 2 files changed, 135 deletions(-) delete mode 100644 src/pages/workspace/WorkspaceOverviewCurrencyPage.js diff --git a/src/pages/workspace/WorkspaceOverviewCurrencyPage.js b/src/pages/workspace/WorkspaceOverviewCurrencyPage.js deleted file mode 100644 index 82685689c30c..000000000000 --- a/src/pages/workspace/WorkspaceOverviewCurrencyPage.js +++ /dev/null @@ -1,122 +0,0 @@ -<<<<<<<< HEAD:src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx -import React, {useCallback, useState} from 'react'; -======== -import PropTypes from 'prop-types'; -import React, {useState} from 'react'; ->>>>>>>> main:src/pages/workspace/WorkspaceOverviewCurrencyPage.js -import {withOnyx} from 'react-native-onyx'; -import type {OnyxEntry} from 'react-native-onyx'; -import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import SelectionList from '@components/SelectionList'; -import useLocalize from '@hooks/useLocalize'; -import Navigation from '@libs/Navigation/Navigation'; -import * as PolicyUtils from '@libs/PolicyUtils'; -import * as Policy from '@userActions/Policy'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import type {CurrencyList} from '@src/types/onyx/Currency'; -import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; -import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; - -type WorkspaceSettingsCurrentPageOnyxProps = { - /** Constant, list of available currencies */ - currencyList: OnyxEntry; -}; - -type WorkspaceSettingsCurrentPageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceSettingsCurrentPageOnyxProps; - -type WorkspaceSettingsCurrencyPageSectionItem = { - text: string; - keyForList: string; - isSelected: boolean; -}; - -const getDisplayText = (currencyCode: string, currencySymbol: string) => `${currencyCode} - ${currencySymbol}`; - -function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingReportData = true}: WorkspaceSettingsCurrentPageProps) { - const {translate} = useLocalize(); - const [searchText, setSearchText] = useState(''); - const trimmedText = searchText.trim().toLowerCase(); - const currencyListKeys = Object.keys(currencyList ?? {}); - - const filteredItems = currencyListKeys.filter((currencyCode: string) => { - const currency = currencyList?.[currencyCode]; - return getDisplayText(currencyCode, currency?.symbol ?? '') - .toLowerCase() - .includes(trimmedText); - }); - - let initiallyFocusedOptionKey; - - const currencyItems: WorkspaceSettingsCurrencyPageSectionItem[] = filteredItems.map((currencyCode: string) => { - const currency = currencyList?.[currencyCode]; - const isSelected = policy?.outputCurrency === currencyCode; - - if (isSelected) { - initiallyFocusedOptionKey = currencyCode; - } - - return { - text: getDisplayText(currencyCode, currency?.symbol ?? ''), - keyForList: currencyCode, - isSelected, - }; - }); - - const sections = [{data: currencyItems, indexOffset: 0}]; - - const headerMessage = searchText.trim() && !currencyItems.length ? translate('common.noResultsFound') : ''; - -<<<<<<<< HEAD:src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx - const onBackButtonPress = useCallback(() => Navigation.goBack(ROUTES.WORKSPACE_SETTINGS.getRoute(policy?.id ?? '')), [policy?.id]); - - const onSelectCurrency = (item: WorkspaceSettingsCurrencyPageSectionItem) => { - Policy.updateGeneralSettings(policy?.id ?? '', policy?.name ?? '', item.keyForList); - Navigation.goBack(ROUTES.WORKSPACE_SETTINGS.getRoute(policy?.id ?? '')); -======== - const onSelectCurrency = (item) => { - Policy.updateGeneralSettings(policy.id, policy.name, item.keyForList); - Navigation.goBack(); ->>>>>>>> main:src/pages/workspace/WorkspaceOverviewCurrencyPage.js - }; - - return ( - - Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)} - shouldShow={(isEmptyObject(policy) && !isLoadingReportData) || !PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPendingDeletePolicy(policy)} - subtitleKey={isEmptyObject(policy) ? undefined : 'workspace.common.notAuthorized'} - > - Navigation.goBack()} - /> - - - - - ); -} - -WorkspaceSettingsCurrencyPage.displayName = 'WorkspaceSettingsCurrencyPage'; - -export default withPolicyAndFullscreenLoading( - withOnyx({ - currencyList: {key: ONYXKEYS.CURRENCY_LIST}, - })(WorkspaceSettingsCurrencyPage), -); diff --git a/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx b/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx index 82685689c30c..cfedc3098fb2 100644 --- a/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx +++ b/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx @@ -1,9 +1,4 @@ -<<<<<<<< HEAD:src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx import React, {useCallback, useState} from 'react'; -======== -import PropTypes from 'prop-types'; -import React, {useState} from 'react'; ->>>>>>>> main:src/pages/workspace/WorkspaceOverviewCurrencyPage.js import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; @@ -70,17 +65,9 @@ function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingRepo const headerMessage = searchText.trim() && !currencyItems.length ? translate('common.noResultsFound') : ''; -<<<<<<<< HEAD:src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx - const onBackButtonPress = useCallback(() => Navigation.goBack(ROUTES.WORKSPACE_SETTINGS.getRoute(policy?.id ?? '')), [policy?.id]); - const onSelectCurrency = (item: WorkspaceSettingsCurrencyPageSectionItem) => { Policy.updateGeneralSettings(policy?.id ?? '', policy?.name ?? '', item.keyForList); Navigation.goBack(ROUTES.WORKSPACE_SETTINGS.getRoute(policy?.id ?? '')); -======== - const onSelectCurrency = (item) => { - Policy.updateGeneralSettings(policy.id, policy.name, item.keyForList); - Navigation.goBack(); ->>>>>>>> main:src/pages/workspace/WorkspaceOverviewCurrencyPage.js }; return ( From 37c12e21d4a8b532dfbf87568a1a349caac0c377 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Wed, 7 Feb 2024 16:26:55 +0000 Subject: [PATCH 10/16] [TS migration][WorkspaceSettings] Fixed wrongly resolved conflicts --- .../WorkspaceOverviewCurrencyPage.tsx | 109 ++++++++++++++++++ .../WorkspaceSettingsCurrencyPage.tsx | 2 +- 2 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx diff --git a/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx b/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx new file mode 100644 index 000000000000..949d53d0cf95 --- /dev/null +++ b/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx @@ -0,0 +1,109 @@ +import React, {useCallback, useState} from 'react'; +import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; +import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import SelectionList from '@components/SelectionList'; +import useLocalize from '@hooks/useLocalize'; +import Navigation from '@libs/Navigation/Navigation'; +import * as PolicyUtils from '@libs/PolicyUtils'; +import * as Policy from '@userActions/Policy'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import type {CurrencyList} from '@src/types/onyx/Currency'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; +import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; + +type WorkspaceSettingsCurrentPageOnyxProps = { + /** Constant, list of available currencies */ + currencyList: OnyxEntry; +}; + +type WorkspaceSettingsCurrentPageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceSettingsCurrentPageOnyxProps; + +type WorkspaceSettingsCurrencyPageSectionItem = { + text: string; + keyForList: string; + isSelected: boolean; +}; + +const getDisplayText = (currencyCode: string, currencySymbol: string) => `${currencyCode} - ${currencySymbol}`; + +function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingReportData = true}: WorkspaceSettingsCurrentPageProps) { + const {translate} = useLocalize(); + const [searchText, setSearchText] = useState(''); + const trimmedText = searchText.trim().toLowerCase(); + const currencyListKeys = Object.keys(currencyList ?? {}); + + const filteredItems = currencyListKeys.filter((currencyCode: string) => { + const currency = currencyList?.[currencyCode]; + return getDisplayText(currencyCode, currency?.symbol ?? '') + .toLowerCase() + .includes(trimmedText); + }); + + let initiallyFocusedOptionKey; + + const currencyItems: WorkspaceSettingsCurrencyPageSectionItem[] = filteredItems.map((currencyCode: string) => { + const currency = currencyList?.[currencyCode]; + const isSelected = policy?.outputCurrency === currencyCode; + + if (isSelected) { + initiallyFocusedOptionKey = currencyCode; + } + + return { + text: getDisplayText(currencyCode, currency?.symbol ?? ''), + keyForList: currencyCode, + isSelected, + }; + }); + + const sections = [{data: currencyItems, indexOffset: 0}]; + + const headerMessage = searchText.trim() && !currencyItems.length ? translate('common.noResultsFound') : ''; + + const onSelectCurrency = (item: WorkspaceSettingsCurrencyPageSectionItem) => { + Policy.updateGeneralSettings(policy?.id ?? '', policy?.name ?? '', item.keyForList); + Navigation.goBack(); + }; + + return ( + + Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)} + shouldShow={(isEmptyObject(policy) && !isLoadingReportData) || !PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPendingDeletePolicy(policy)} + subtitleKey={isEmptyObject(policy) ? undefined : 'workspace.common.notAuthorized'} + > + Navigation.goBack()} + /> + + + + + ); +} + +WorkspaceSettingsCurrencyPage.displayName = 'WorkspaceSettingsCurrencyPage'; + +export default withPolicyAndFullscreenLoading( + withOnyx({ + currencyList: {key: ONYXKEYS.CURRENCY_LIST}, + })(WorkspaceSettingsCurrencyPage), +); diff --git a/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx b/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx index cfedc3098fb2..4dd608d07937 100644 --- a/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx +++ b/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx @@ -67,7 +67,7 @@ function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingRepo const onSelectCurrency = (item: WorkspaceSettingsCurrencyPageSectionItem) => { Policy.updateGeneralSettings(policy?.id ?? '', policy?.name ?? '', item.keyForList); - Navigation.goBack(ROUTES.WORKSPACE_SETTINGS.getRoute(policy?.id ?? '')); + Navigation.goBack(); }; return ( From b2e0b3b93dd113b2e08fad886d7dac48e32e3b87 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Wed, 7 Feb 2024 16:27:54 +0000 Subject: [PATCH 11/16] [TS migration][WorkscpaceSettings] Lint fixes --- src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx | 4 ++-- src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx b/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx index 949d53d0cf95..e05ffddf7129 100644 --- a/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx +++ b/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx @@ -1,4 +1,4 @@ -import React, {useCallback, useState} from 'react'; +import React, {useState} from 'react'; import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; @@ -69,7 +69,7 @@ function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingRepo Policy.updateGeneralSettings(policy?.id ?? '', policy?.name ?? '', item.keyForList); Navigation.goBack(); }; - + return ( Date: Wed, 7 Feb 2024 16:33:40 +0000 Subject: [PATCH 12/16] [TS migration][WorkspaceSettings] Minor ts issues fixed --- src/CONST.ts | 1 + src/pages/workspace/WorkspaceSettingsPage.tsx | 64 +++++++++---------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 6c726cde12f7..a2f2c52fa9f6 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1515,6 +1515,7 @@ const CONST = { WORKSPACE_TRAVEL: 'WorkspaceBookTravel', WORKSPACE_MEMBERS: 'WorkspaceManageMembers', WORKSPACE_BANK_ACCOUNT: 'WorkspaceBankAccount', + WORKSPACE_SETTINGS: 'WorkspaceSettings', }, get EXPENSIFY_EMAILS() { return [ diff --git a/src/pages/workspace/WorkspaceSettingsPage.tsx b/src/pages/workspace/WorkspaceSettingsPage.tsx index cd2a59006baa..e1d63539b617 100644 --- a/src/pages/workspace/WorkspaceSettingsPage.tsx +++ b/src/pages/workspace/WorkspaceSettingsPage.tsx @@ -91,40 +91,38 @@ function WorkspaceSettingsPage({policy, currencyList = {}, route}: WorkSpaceSett onSubmit={submit} enabledWhenOffline > - { + ( + + )} + type={CONST.ICON_TYPE_WORKSPACE} + fallbackIcon={Expensicons.FallbackWorkspaceAvatar} + style={[styles.mb3]} // @ts-expect-error TODO: Remove this once AvatarWithImagePicker (https://github.com/Expensify/App/issues/25122) is migrated to TypeScript. - ( - - )} - type={CONST.ICON_TYPE_WORKSPACE} - fallbackIcon={Expensicons.FallbackWorkspaceAvatar} - style={[styles.mb3]} - anchorPosition={styles.createMenuPositionProfile(windowWidth)} - anchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP}} - isUsingDefaultAvatar={!policy?.avatar ?? null} - onImageSelected={(file: File) => Policy.updateWorkspaceAvatar(policy?.id ?? '', file)} - onImageRemoved={() => Policy.deleteWorkspaceAvatar(policy?.id ?? '')} - editorMaskImage={Expensicons.ImageCropSquareMask} - pendingAction={policy?.pendingFields?.avatar ?? null} - errors={policy?.errorFields?.avatar ?? null} - onErrorClose={() => Policy.clearAvatarErrors(policy?.id ?? '')} - previewSource={UserUtils.getFullSizeAvatar(policy?.avatar ?? '')} - headerTitle={translate('workspace.common.workspaceAvatar')} - originalFileName={policy?.originalFileName ?? ''} - errorRowStyles={undefined} - /> - } + anchorPosition={styles.createMenuPositionProfile(windowWidth)} + anchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP}} + isUsingDefaultAvatar={!policy?.avatar ?? null} + onImageSelected={(file: File) => Policy.updateWorkspaceAvatar(policy?.id ?? '', file)} + onImageRemoved={() => Policy.deleteWorkspaceAvatar(policy?.id ?? '')} + editorMaskImage={Expensicons.ImageCropSquareMask} + pendingAction={policy?.pendingFields?.avatar ?? null} + errors={policy?.errorFields?.avatar ?? null} + onErrorClose={() => Policy.clearAvatarErrors(policy?.id ?? '')} + previewSource={UserUtils.getFullSizeAvatar(policy?.avatar ?? '')} + headerTitle={translate('workspace.common.workspaceAvatar')} + originalFileName={policy?.originalFileName ?? ''} + errorRowStyles={undefined} + /> Date: Wed, 14 Feb 2024 12:22:21 +0000 Subject: [PATCH 13/16] [TS migration] Fixed migration of WorkspaceSettings based on the rename to WorkspaceProfile --- .../workspace/WorkspaceProfileCurrencyPage.js | 115 ------------ ...e.tsx => WorkspaceProfileCurrencyPage.tsx} | 4 +- ...rofilePage.js => WorkspaceProfilePage.tsx} | 75 +++----- src/pages/workspace/WorkspaceSettingsPage.tsx | 163 ------------------ 4 files changed, 29 insertions(+), 328 deletions(-) delete mode 100644 src/pages/workspace/WorkspaceProfileCurrencyPage.js rename src/pages/workspace/{WorkspaceSettingsCurrencyPage.tsx => WorkspaceProfileCurrencyPage.tsx} (98%) rename src/pages/workspace/{WorkspaceProfilePage.js => WorkspaceProfilePage.tsx} (72%) delete mode 100644 src/pages/workspace/WorkspaceSettingsPage.tsx diff --git a/src/pages/workspace/WorkspaceProfileCurrencyPage.js b/src/pages/workspace/WorkspaceProfileCurrencyPage.js deleted file mode 100644 index fda66fc0de80..000000000000 --- a/src/pages/workspace/WorkspaceProfileCurrencyPage.js +++ /dev/null @@ -1,115 +0,0 @@ -import PropTypes from 'prop-types'; -import React, {useState} from 'react'; -import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; -import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import SelectionList from '@components/SelectionList'; -import useLocalize from '@hooks/useLocalize'; -import compose from '@libs/compose'; -import Navigation from '@libs/Navigation/Navigation'; -import * as PolicyUtils from '@libs/PolicyUtils'; -import * as Policy from '@userActions/Policy'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import {policyDefaultProps, policyPropTypes} from './withPolicy'; -import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; - -const propTypes = { - /** Constant, list of available currencies */ - currencyList: PropTypes.objectOf( - PropTypes.shape({ - /** Symbol of the currency */ - symbol: PropTypes.string.isRequired, - }), - ), - isLoadingReportData: PropTypes.bool, - ...policyPropTypes, -}; - -const defaultProps = { - currencyList: {}, - isLoadingReportData: true, - ...policyDefaultProps, -}; - -const getDisplayText = (currencyCode, currencySymbol) => `${currencyCode} - ${currencySymbol}`; - -function WorkspaceSettingsCurrencyPage({currencyList, policy, isLoadingReportData}) { - const {translate} = useLocalize(); - const [searchText, setSearchText] = useState(''); - const trimmedText = searchText.trim().toLowerCase(); - const currencyListKeys = _.keys(currencyList); - - const filteredItems = _.filter(currencyListKeys, (currencyCode) => { - const currency = currencyList[currencyCode]; - return getDisplayText(currencyCode, currency.symbol).toLowerCase().includes(trimmedText); - }); - - let initiallyFocusedOptionKey; - - const currencyItems = _.map(filteredItems, (currencyCode) => { - const currency = currencyList[currencyCode]; - const isSelected = policy.outputCurrency === currencyCode; - - if (isSelected) { - initiallyFocusedOptionKey = currencyCode; - } - - return { - text: getDisplayText(currencyCode, currency.symbol), - keyForList: currencyCode, - isSelected, - }; - }); - - const sections = [{data: currencyItems, indexOffset: 0}]; - - const headerMessage = searchText.trim() && !currencyItems.length ? translate('common.noResultsFound') : ''; - - const onSelectCurrency = (item) => { - Policy.updateGeneralSettings(policy.id, policy.name, item.keyForList); - Navigation.goBack(); - }; - - return ( - - Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)} - shouldShow={(_.isEmpty(policy) && !isLoadingReportData) || !PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPendingDeletePolicy(policy)} - subtitleKey={_.isEmpty(policy) ? undefined : 'workspace.common.notAuthorized'} - > - Navigation.goBack()} - /> - - - - - ); -} - -WorkspaceSettingsCurrencyPage.displayName = 'WorkspaceSettingsCurrencyPage'; -WorkspaceSettingsCurrencyPage.propTypes = propTypes; -WorkspaceSettingsCurrencyPage.defaultProps = defaultProps; - -export default compose( - withPolicyAndFullscreenLoading, - withOnyx({ - currencyList: {key: ONYXKEYS.CURRENCY_LIST}, - }), -)(WorkspaceSettingsCurrencyPage); \ No newline at end of file diff --git a/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx b/src/pages/workspace/WorkspaceProfileCurrencyPage.tsx similarity index 98% rename from src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx rename to src/pages/workspace/WorkspaceProfileCurrencyPage.tsx index e05ffddf7129..773a9a689499 100644 --- a/src/pages/workspace/WorkspaceSettingsCurrencyPage.tsx +++ b/src/pages/workspace/WorkspaceProfileCurrencyPage.tsx @@ -1,6 +1,6 @@ import React, {useState} from 'react'; -import {withOnyx} from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -11,7 +11,7 @@ import * as PolicyUtils from '@libs/PolicyUtils'; import * as Policy from '@userActions/Policy'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {CurrencyList} from '@src/types/onyx/Currency'; +import type {CurrencyList} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; diff --git a/src/pages/workspace/WorkspaceProfilePage.js b/src/pages/workspace/WorkspaceProfilePage.tsx similarity index 72% rename from src/pages/workspace/WorkspaceProfilePage.js rename to src/pages/workspace/WorkspaceProfilePage.tsx index 2b7402fee3ac..ef7a44d996e1 100644 --- a/src/pages/workspace/WorkspaceProfilePage.js +++ b/src/pages/workspace/WorkspaceProfilePage.tsx @@ -1,9 +1,7 @@ -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; import React, {useCallback} from 'react'; import {View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; import Avatar from '@components/Avatar'; import AvatarWithImagePicker from '@components/AvatarWithImagePicker'; import * as Expensicons from '@components/Icon/Expensicons'; @@ -12,7 +10,6 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -21,45 +18,29 @@ import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import withPolicy, {policyDefaultProps, policyPropTypes} from './withPolicy'; +import type {CurrencyList} from '@src/types/onyx'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import withPolicy from './withPolicy'; +import type {WithPolicyProps} from './withPolicy'; import WorkspacePageWithSections from './WorkspacePageWithSections'; -const propTypes = { +type WorkSpaceProfilePageOnyxProps = { /** Constant, list of available currencies */ - currencyList: PropTypes.objectOf( - PropTypes.shape({ - /** Symbol of the currency */ - symbol: 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, - - ...policyPropTypes, + currencyList: OnyxEntry; }; -const defaultProps = { - currencyList: {}, - ...policyDefaultProps, -}; +type WorkSpaceProfilePageProps = WithPolicyProps & WorkSpaceProfilePageOnyxProps; -function WorkspaceProfilePage({policy, currencyList, route}) { +function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfilePageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); - const formattedCurrency = !_.isEmpty(policy) && !_.isEmpty(currencyList) && !!policy.outputCurrency ? `${policy.outputCurrency} - ${currencyList[policy.outputCurrency].symbol}` : ''; + const formattedCurrency = !isEmptyObject(policy) && !isEmptyObject(currencyList) ? `${policy?.outputCurrency ?? ''} - ${currencyList?.[policy?.outputCurrency ?? '']?.symbol ?? ''}` : ''; - const onPressCurrency = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_PROFILE_CURRENCY.getRoute(policy.id)), [policy.id]); - const onPressName = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_PROFILE_NAME.getRoute(policy.id)), [policy.id]); + const onPressCurrency = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_PROFILE_CURRENCY.getRoute(policy?.id ?? '')), [policy?.id]); + const onPressName = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_PROFILE_NAME.getRoute(policy?.id ?? '')), [policy?.id]); - const policyName = lodashGet(policy, 'name', ''); + const policyName = policy?.name ?? ''; const readOnly = !PolicyUtils.isPolicyAdmin(policy); return ( @@ -72,10 +53,10 @@ function WorkspaceProfilePage({policy, currencyList, route}) { shouldShowOfflineIndicatorInWideScreen shouldShowNonAdmin > - {(hasVBA) => ( + {(hasVBA?: boolean) => ( <> Navigation.navigate(ROUTES.WORKSPACE_AVATAR.getRoute(policy.id))} + onViewPhotoPress={() => Navigation.navigate(ROUTES.WORKSPACE_AVATAR.getRoute(policy?.id ?? ''))} source={lodashGet(policy, 'avatar')} size={CONST.AVATAR_SIZE.XLARGE} avatarStyle={styles.avatarXLarge} @@ -84,7 +65,7 @@ function WorkspaceProfilePage({policy, currencyList, route}) { Policy.updateWorkspaceAvatar(lodashGet(policy, 'id', ''), file)} + onImageSelected={(file: File) => Policy.updateWorkspaceAvatar(policy?.id ?? '', file)} onImageRemoved={() => Policy.deleteWorkspaceAvatar(lodashGet(policy, 'id', ''))} editorMaskImage={Expensicons.ImageCropSquareMask} pendingAction={lodashGet(policy, 'pendingFields.avatar', null)} errors={lodashGet(policy, 'errorFields.avatar', null)} - onErrorClose={() => Policy.clearAvatarErrors(policy.id)} - previewSource={UserUtils.getFullSizeAvatar(policy.avatar, '')} + onErrorClose={() => Policy.clearAvatarErrors(policy?.id ?? '')} + previewSource={UserUtils.getFullSizeAvatar(policy?.avatar ?? '')} headerTitle={translate('workspace.common.workspaceAvatar')} - originalFileName={policy.originalFileName} + originalFileName={policy?.originalFileName} disabled={readOnly} disabledStyle={styles.cursorDefault} + errorRowStyles={undefined} /> ({ currencyList: {key: ONYXKEYS.CURRENCY_LIST}, - }), -)(WorkspaceProfilePage); + })(WorkspaceProfilePage), +); diff --git a/src/pages/workspace/WorkspaceSettingsPage.tsx b/src/pages/workspace/WorkspaceSettingsPage.tsx deleted file mode 100644 index e1d63539b617..000000000000 --- a/src/pages/workspace/WorkspaceSettingsPage.tsx +++ /dev/null @@ -1,163 +0,0 @@ -import React, {useCallback} from 'react'; -import {Keyboard, View} from 'react-native'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; -import Avatar from '@components/Avatar'; -import AvatarWithImagePicker from '@components/AvatarWithImagePicker'; -import FormProvider from '@components/Form/FormProvider'; -import InputWrapper from '@components/Form/InputWrapper'; -import type {OnyxFormValuesFields} from '@components/Form/types'; -import * as Expensicons from '@components/Icon/Expensicons'; -import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; -import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import Text from '@components/Text'; -import TextInput from '@components/TextInput'; -import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; -import useWindowDimensions from '@hooks/useWindowDimensions'; -import Navigation from '@libs/Navigation/Navigation'; -import * as ReportUtils from '@libs/ReportUtils'; -import * as UserUtils from '@libs/UserUtils'; -import * as ValidationUtils from '@libs/ValidationUtils'; -import * as Policy from '@userActions/Policy'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import type {CurrencyList} from '@src/types/onyx'; -import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; -import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import type {WithPolicyProps} from './withPolicy'; -import withPolicy from './withPolicy'; -import WorkspacePageWithSections from './WorkspacePageWithSections'; - -type WorkSpaceSettingsPageOnyxProps = { - /** Constant, list of available currencies */ - currencyList: OnyxEntry; -}; - -type WorkSpaceSettingsPageProps = WithPolicyProps & WorkSpaceSettingsPageOnyxProps; - -type WorkSpaceSettingsPageErrors = {name?: string}; - -function WorkspaceSettingsPage({policy, currencyList = {}, route}: WorkSpaceSettingsPageProps) { - const styles = useThemeStyles(); - const {translate} = useLocalize(); - const {windowWidth} = useWindowDimensions(); - - const formattedCurrency = !isEmptyObject(policy) && !isEmptyObject(currencyList) ? `${policy?.outputCurrency ?? ''} - ${currencyList?.[policy?.outputCurrency ?? '']?.symbol ?? ''}` : ''; - - const submit = useCallback( - (values: OnyxFormValuesFields) => { - Policy.updateGeneralSettings(policy?.id ?? '', values.name.trim(), policy?.outputCurrency ?? ''); - Keyboard.dismiss(); - Navigation.goBack(ROUTES.WORKSPACE_INITIAL.getRoute(policy?.id ?? '')); - }, - [policy?.id, policy?.outputCurrency], - ); - - const validate = useCallback((values: OnyxFormValuesFields) => { - const errors: WorkSpaceSettingsPageErrors = {}; - const name = values.name.trim(); - - if (!ValidationUtils.isRequiredFulfilled(name)) { - errors.name = 'workspace.editor.nameIsRequiredError'; - } else if ([...name].length > CONST.WORKSPACE_NAME_CHARACTER_LIMIT) { - // Uses the spread syntax to count the number of Unicode code points instead of the number of UTF-16 - // code units. - errors.name = 'workspace.editor.nameIsTooLongError'; - } - - return errors; - }, []); - - const onPressCurrency = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_SETTINGS_CURRENCY.getRoute(policy?.id ?? '')), [policy?.id]); - - const policyName = policy?.name ?? ''; - - return ( - - {(hasVBA?: boolean) => ( - - ( - - )} - type={CONST.ICON_TYPE_WORKSPACE} - fallbackIcon={Expensicons.FallbackWorkspaceAvatar} - style={[styles.mb3]} - // @ts-expect-error TODO: Remove this once AvatarWithImagePicker (https://github.com/Expensify/App/issues/25122) is migrated to TypeScript. - anchorPosition={styles.createMenuPositionProfile(windowWidth)} - anchorAlignment={{horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.TOP}} - isUsingDefaultAvatar={!policy?.avatar ?? null} - onImageSelected={(file: File) => Policy.updateWorkspaceAvatar(policy?.id ?? '', file)} - onImageRemoved={() => Policy.deleteWorkspaceAvatar(policy?.id ?? '')} - editorMaskImage={Expensicons.ImageCropSquareMask} - pendingAction={policy?.pendingFields?.avatar ?? null} - errors={policy?.errorFields?.avatar ?? null} - onErrorClose={() => Policy.clearAvatarErrors(policy?.id ?? '')} - previewSource={UserUtils.getFullSizeAvatar(policy?.avatar ?? '')} - headerTitle={translate('workspace.common.workspaceAvatar')} - originalFileName={policy?.originalFileName ?? ''} - errorRowStyles={undefined} - /> - - - - - - {hasVBA ? translate('workspace.editor.currencyInputDisabledText') : translate('workspace.editor.currencyInputHelpText')} - - - - - )} - - ); -} - -WorkspaceSettingsPage.displayName = 'WorkspaceSettingsPage'; - -export default withPolicy( - withOnyx({ - currencyList: {key: ONYXKEYS.CURRENCY_LIST}, - })(WorkspaceSettingsPage), -); From 9d451c838d60a96871c218fbc2654282f5eeea97 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Wed, 14 Feb 2024 12:36:19 +0000 Subject: [PATCH 14/16] [TS migration][WorkspaceSettings] Fixed ts issues --- src/pages/workspace/WorkspaceProfilePage.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/pages/workspace/WorkspaceProfilePage.tsx b/src/pages/workspace/WorkspaceProfilePage.tsx index ef7a44d996e1..b96be8d2cd29 100644 --- a/src/pages/workspace/WorkspaceProfilePage.tsx +++ b/src/pages/workspace/WorkspaceProfilePage.tsx @@ -19,6 +19,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {CurrencyList} from '@src/types/onyx'; +import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import withPolicy from './withPolicy'; import type {WithPolicyProps} from './withPolicy'; @@ -57,7 +58,7 @@ function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfi <> Navigation.navigate(ROUTES.WORKSPACE_AVATAR.getRoute(policy?.id ?? ''))} - source={lodashGet(policy, 'avatar')} + source={policy?.avatar ?? ''} size={CONST.AVATAR_SIZE.XLARGE} avatarStyle={styles.avatarXLarge} enablePreview @@ -75,12 +76,12 @@ function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfi type={CONST.ICON_TYPE_WORKSPACE} fallbackIcon={Expensicons.FallbackWorkspaceAvatar} style={[styles.mb3, styles.mt5, styles.mh5]} - isUsingDefaultAvatar={!lodashGet(policy, 'avatar', null)} + isUsingDefaultAvatar={!(policy?.avatar ?? null)} onImageSelected={(file: File) => Policy.updateWorkspaceAvatar(policy?.id ?? '', file)} - onImageRemoved={() => Policy.deleteWorkspaceAvatar(lodashGet(policy, 'id', ''))} + onImageRemoved={() => Policy.deleteWorkspaceAvatar(policy?.id ?? '')} editorMaskImage={Expensicons.ImageCropSquareMask} - pendingAction={lodashGet(policy, 'pendingFields.avatar', null)} - errors={lodashGet(policy, 'errorFields.avatar', null)} + pendingAction={policy?.pendingFields?.avatar ?? null} + errors={policy?.errorFields?.avatar ?? null} onErrorClose={() => Policy.clearAvatarErrors(policy?.id ?? '')} previewSource={UserUtils.getFullSizeAvatar(policy?.avatar ?? '')} headerTitle={translate('workspace.common.workspaceAvatar')} @@ -89,7 +90,7 @@ function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfi disabledStyle={styles.cursorDefault} errorRowStyles={undefined} /> - + Date: Thu, 22 Feb 2024 15:01:38 +0000 Subject: [PATCH 15/16] [TS migration][WorkspaceSettings] Feedback addressed --- .../WorkspaceOverviewCurrencyPage.tsx | 109 ------------------ .../WorkspaceProfileCurrencyPage.tsx | 20 ++-- src/pages/workspace/WorkspaceProfilePage.tsx | 4 +- 3 files changed, 13 insertions(+), 120 deletions(-) delete mode 100644 src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx diff --git a/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx b/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx deleted file mode 100644 index e05ffddf7129..000000000000 --- a/src/pages/workspace/WorkspaceOverviewCurrencyPage.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import React, {useState} from 'react'; -import {withOnyx} from 'react-native-onyx'; -import type {OnyxEntry} from 'react-native-onyx'; -import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import SelectionList from '@components/SelectionList'; -import useLocalize from '@hooks/useLocalize'; -import Navigation from '@libs/Navigation/Navigation'; -import * as PolicyUtils from '@libs/PolicyUtils'; -import * as Policy from '@userActions/Policy'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import type {CurrencyList} from '@src/types/onyx/Currency'; -import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; -import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; - -type WorkspaceSettingsCurrentPageOnyxProps = { - /** Constant, list of available currencies */ - currencyList: OnyxEntry; -}; - -type WorkspaceSettingsCurrentPageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceSettingsCurrentPageOnyxProps; - -type WorkspaceSettingsCurrencyPageSectionItem = { - text: string; - keyForList: string; - isSelected: boolean; -}; - -const getDisplayText = (currencyCode: string, currencySymbol: string) => `${currencyCode} - ${currencySymbol}`; - -function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingReportData = true}: WorkspaceSettingsCurrentPageProps) { - const {translate} = useLocalize(); - const [searchText, setSearchText] = useState(''); - const trimmedText = searchText.trim().toLowerCase(); - const currencyListKeys = Object.keys(currencyList ?? {}); - - const filteredItems = currencyListKeys.filter((currencyCode: string) => { - const currency = currencyList?.[currencyCode]; - return getDisplayText(currencyCode, currency?.symbol ?? '') - .toLowerCase() - .includes(trimmedText); - }); - - let initiallyFocusedOptionKey; - - const currencyItems: WorkspaceSettingsCurrencyPageSectionItem[] = filteredItems.map((currencyCode: string) => { - const currency = currencyList?.[currencyCode]; - const isSelected = policy?.outputCurrency === currencyCode; - - if (isSelected) { - initiallyFocusedOptionKey = currencyCode; - } - - return { - text: getDisplayText(currencyCode, currency?.symbol ?? ''), - keyForList: currencyCode, - isSelected, - }; - }); - - const sections = [{data: currencyItems, indexOffset: 0}]; - - const headerMessage = searchText.trim() && !currencyItems.length ? translate('common.noResultsFound') : ''; - - const onSelectCurrency = (item: WorkspaceSettingsCurrencyPageSectionItem) => { - Policy.updateGeneralSettings(policy?.id ?? '', policy?.name ?? '', item.keyForList); - Navigation.goBack(); - }; - - return ( - - Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)} - shouldShow={(isEmptyObject(policy) && !isLoadingReportData) || !PolicyUtils.isPolicyAdmin(policy) || PolicyUtils.isPendingDeletePolicy(policy)} - subtitleKey={isEmptyObject(policy) ? undefined : 'workspace.common.notAuthorized'} - > - Navigation.goBack()} - /> - - - - - ); -} - -WorkspaceSettingsCurrencyPage.displayName = 'WorkspaceSettingsCurrencyPage'; - -export default withPolicyAndFullscreenLoading( - withOnyx({ - currencyList: {key: ONYXKEYS.CURRENCY_LIST}, - })(WorkspaceSettingsCurrencyPage), -); diff --git a/src/pages/workspace/WorkspaceProfileCurrencyPage.tsx b/src/pages/workspace/WorkspaceProfileCurrencyPage.tsx index 773a9a689499..1a06a5cc8985 100644 --- a/src/pages/workspace/WorkspaceProfileCurrencyPage.tsx +++ b/src/pages/workspace/WorkspaceProfileCurrencyPage.tsx @@ -16,14 +16,14 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type {WithPolicyAndFullscreenLoadingProps} from './withPolicyAndFullscreenLoading'; import withPolicyAndFullscreenLoading from './withPolicyAndFullscreenLoading'; -type WorkspaceSettingsCurrentPageOnyxProps = { +type WorkspaceProfileCurrentPageOnyxProps = { /** Constant, list of available currencies */ currencyList: OnyxEntry; }; -type WorkspaceSettingsCurrentPageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceSettingsCurrentPageOnyxProps; +type WorkspaceProfileCurrentPageProps = WithPolicyAndFullscreenLoadingProps & WorkspaceProfileCurrentPageOnyxProps; -type WorkspaceSettingsCurrencyPageSectionItem = { +type WorkspaceProfileCurrencyPageSectionItem = { text: string; keyForList: string; isSelected: boolean; @@ -31,7 +31,7 @@ type WorkspaceSettingsCurrencyPageSectionItem = { const getDisplayText = (currencyCode: string, currencySymbol: string) => `${currencyCode} - ${currencySymbol}`; -function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingReportData = true}: WorkspaceSettingsCurrentPageProps) { +function WorkspaceProfileCurrencyPage({currencyList = {}, policy, isLoadingReportData = true}: WorkspaceProfileCurrentPageProps) { const {translate} = useLocalize(); const [searchText, setSearchText] = useState(''); const trimmedText = searchText.trim().toLowerCase(); @@ -46,7 +46,7 @@ function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingRepo let initiallyFocusedOptionKey; - const currencyItems: WorkspaceSettingsCurrencyPageSectionItem[] = filteredItems.map((currencyCode: string) => { + const currencyItems: WorkspaceProfileCurrencyPageSectionItem[] = filteredItems.map((currencyCode: string) => { const currency = currencyList?.[currencyCode]; const isSelected = policy?.outputCurrency === currencyCode; @@ -65,7 +65,7 @@ function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingRepo const headerMessage = searchText.trim() && !currencyItems.length ? translate('common.noResultsFound') : ''; - const onSelectCurrency = (item: WorkspaceSettingsCurrencyPageSectionItem) => { + const onSelectCurrency = (item: WorkspaceProfileCurrencyPageSectionItem) => { Policy.updateGeneralSettings(policy?.id ?? '', policy?.name ?? '', item.keyForList); Navigation.goBack(); }; @@ -73,7 +73,7 @@ function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingRepo return ( Navigation.goBack(ROUTES.SETTINGS_WORKSPACES)} @@ -100,10 +100,10 @@ function WorkspaceSettingsCurrencyPage({currencyList = {}, policy, isLoadingRepo ); } -WorkspaceSettingsCurrencyPage.displayName = 'WorkspaceSettingsCurrencyPage'; +WorkspaceProfileCurrencyPage.displayName = 'WorkspaceProfileCurrencyPage'; export default withPolicyAndFullscreenLoading( - withOnyx({ + withOnyx({ currencyList: {key: ONYXKEYS.CURRENCY_LIST}, - })(WorkspaceSettingsCurrencyPage), + })(WorkspaceProfileCurrencyPage), ); diff --git a/src/pages/workspace/WorkspaceProfilePage.tsx b/src/pages/workspace/WorkspaceProfilePage.tsx index b96be8d2cd29..456155484de0 100644 --- a/src/pages/workspace/WorkspaceProfilePage.tsx +++ b/src/pages/workspace/WorkspaceProfilePage.tsx @@ -36,7 +36,9 @@ function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfi const styles = useThemeStyles(); const {translate} = useLocalize(); - const formattedCurrency = !isEmptyObject(policy) && !isEmptyObject(currencyList) ? `${policy?.outputCurrency ?? ''} - ${currencyList?.[policy?.outputCurrency ?? '']?.symbol ?? ''}` : ''; + const outputCurrency = policy?.outputCurrency ?? ''; + const currencySymbol = currencyList?.[outputCurrency]?.symbol ?? ''; + const formattedCurrency = !isEmptyObject(policy) && !isEmptyObject(currencyList) ? `${outputCurrency} - ${currencySymbol}` : ''; const onPressCurrency = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_PROFILE_CURRENCY.getRoute(policy?.id ?? '')), [policy?.id]); const onPressName = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_PROFILE_NAME.getRoute(policy?.id ?? '')), [policy?.id]); From 5d06edbbd72239dec268c9a2e5e130d34cce23b5 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Thu, 22 Feb 2024 15:15:28 +0000 Subject: [PATCH 16/16] [TS migration][WorkspaceSettings] Prettier run after merge --- src/pages/workspace/WorkspaceProfilePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceProfilePage.tsx b/src/pages/workspace/WorkspaceProfilePage.tsx index 81f69a508955..014445ee6e56 100644 --- a/src/pages/workspace/WorkspaceProfilePage.tsx +++ b/src/pages/workspace/WorkspaceProfilePage.tsx @@ -1,5 +1,5 @@ import React, {useCallback} from 'react'; -import type { ImageStyle, StyleProp} from 'react-native'; +import type {ImageStyle, StyleProp} from 'react-native'; import {Image, ScrollView, StyleSheet, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx';