From e951bb7747210447028f350e5935f0bedb6e83e6 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Tue, 28 Nov 2023 17:24:39 +0100 Subject: [PATCH 01/25] [TS migration] Migrate 'TransactionEdit.js' lib --- src/ONYXKEYS.ts | 1 + .../{TransactionEdit.js => TransactionEdit.ts} | 17 ++++++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) rename src/libs/actions/{TransactionEdit.js => TransactionEdit.ts} (76%) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 5576eb64736d..0cb3f67bd990 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -446,6 +446,7 @@ type OnyxValues = { [ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM]: boolean; [ONYXKEYS.COLLECTION.SECURITY_GROUP]: OnyxTypes.SecurityGroup; [ONYXKEYS.COLLECTION.TRANSACTION]: OnyxTypes.Transaction; + [ONYXKEYS.COLLECTION.TRANSACTION_DRAFT]: OnyxTypes.Transaction; [ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS]: OnyxTypes.RecentlyUsedTags; [ONYXKEYS.COLLECTION.SELECTED_TAB]: string; diff --git a/src/libs/actions/TransactionEdit.js b/src/libs/actions/TransactionEdit.ts similarity index 76% rename from src/libs/actions/TransactionEdit.js rename to src/libs/actions/TransactionEdit.ts index 2cb79ac387bd..387dacddbcdc 100644 --- a/src/libs/actions/TransactionEdit.js +++ b/src/libs/actions/TransactionEdit.ts @@ -1,28 +1,31 @@ -import Onyx from 'react-native-onyx'; +import Onyx, {OnyxEntry} from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; +import {Transaction} from '@src/types/onyx'; /** * Makes a backup copy of a transaction object that can be restored when the user cancels editing a transaction. - * - * @param {Object} transaction */ -function createBackupTransaction(transaction) { +function createBackupTransaction(transaction: OnyxEntry) { + if (!transaction) { + return; + } + const newTransaction = { ...transaction, }; + // Use set so that it will always fully overwrite any backup transaction that could have existed before Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`, newTransaction); } /** * Removes a transaction from Onyx that was only used temporary in the edit flow - * @param {String} transactionID */ -function removeBackupTransaction(transactionID) { +function removeBackupTransaction(transactionID: string) { Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, null); } -function restoreOriginalTransactionFromBackup(transactionID) { +function restoreOriginalTransactionFromBackup(transactionID: string) { const connectionID = Onyx.connect({ key: `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, callback: (backupTransaction) => { From 76c1781273e5dd7829d8aa92e87de8e7a0503d4b Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Tue, 28 Nov 2023 17:58:49 +0100 Subject: [PATCH 02/25] [TS migration] Migrate 'MemoryOnlyKeys' lib --- .../{MemoryOnlyKeys.js => MemoryOnlyKeys.ts} | 3 ++- .../exposeGlobalMemoryOnlyKeysMethods/index.js | 12 ------------ .../index.native.js | 6 ------ .../index.native.ts | 8 ++++++++ .../exposeGlobalMemoryOnlyKeysMethods/index.ts | 18 ++++++++++++++++++ .../exposeGlobalMemoryOnlyKeysMethods/types.ts | 3 +++ 6 files changed, 31 insertions(+), 19 deletions(-) rename src/libs/actions/MemoryOnlyKeys/{MemoryOnlyKeys.js => MemoryOnlyKeys.ts} (72%) delete mode 100644 src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.js delete mode 100644 src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.native.js create mode 100644 src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.native.ts create mode 100644 src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.ts create mode 100644 src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/types.ts diff --git a/src/libs/actions/MemoryOnlyKeys/MemoryOnlyKeys.js b/src/libs/actions/MemoryOnlyKeys/MemoryOnlyKeys.ts similarity index 72% rename from src/libs/actions/MemoryOnlyKeys/MemoryOnlyKeys.js rename to src/libs/actions/MemoryOnlyKeys/MemoryOnlyKeys.ts index 028bce225909..79d1ec0f82d9 100644 --- a/src/libs/actions/MemoryOnlyKeys/MemoryOnlyKeys.js +++ b/src/libs/actions/MemoryOnlyKeys/MemoryOnlyKeys.ts @@ -1,8 +1,9 @@ import Onyx from 'react-native-onyx'; +import {OnyxKey} from 'react-native-onyx/lib/types'; import Log from '@libs/Log'; import ONYXKEYS from '@src/ONYXKEYS'; -const memoryOnlyKeys = [ONYXKEYS.COLLECTION.REPORT, ONYXKEYS.COLLECTION.POLICY, ONYXKEYS.PERSONAL_DETAILS_LIST]; +const memoryOnlyKeys: OnyxKey[] = [ONYXKEYS.COLLECTION.REPORT, ONYXKEYS.COLLECTION.POLICY, ONYXKEYS.PERSONAL_DETAILS_LIST]; const enable = () => { Log.info('[MemoryOnlyKeys] enabled'); diff --git a/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.js b/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.js deleted file mode 100644 index 1d039c8980a9..000000000000 --- a/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.js +++ /dev/null @@ -1,12 +0,0 @@ -import * as MemoryOnlyKeys from '@userActions/MemoryOnlyKeys/MemoryOnlyKeys'; - -const exposeGlobalMemoryOnlyKeysMethods = () => { - window.enableMemoryOnlyKeys = () => { - MemoryOnlyKeys.enable(); - }; - window.disableMemoryOnlyKeys = () => { - MemoryOnlyKeys.disable(); - }; -}; - -export default exposeGlobalMemoryOnlyKeysMethods; diff --git a/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.native.js b/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.native.js deleted file mode 100644 index 9d08b9db6aa4..000000000000 --- a/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.native.js +++ /dev/null @@ -1,6 +0,0 @@ -/** - * This is a no-op because the global methods will only work for web and desktop - */ -const exposeGlobalMemoryOnlyKeysMethods = () => {}; - -export default exposeGlobalMemoryOnlyKeysMethods; diff --git a/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.native.ts b/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.native.ts new file mode 100644 index 000000000000..b89e03bdefdc --- /dev/null +++ b/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.native.ts @@ -0,0 +1,8 @@ +import type ExposeGlobalMemoryOnlyKeysMethods from './types'; + +/** + * This is a no-op because the global methods will only work for web and desktop + */ +const exposeGlobalMemoryOnlyKeysMethods: ExposeGlobalMemoryOnlyKeysMethods = () => {}; + +export default exposeGlobalMemoryOnlyKeysMethods; diff --git a/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.ts b/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.ts new file mode 100644 index 000000000000..6d72188803d7 --- /dev/null +++ b/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.ts @@ -0,0 +1,18 @@ +import * as MemoryOnlyKeys from '@userActions/MemoryOnlyKeys/MemoryOnlyKeys'; +import type ExposeGlobalMemoryOnlyKeysMethods from './types'; + +type WindowWithMemoryOnlyKeys = Window & { + enableMemoryOnlyKeys?: () => void; + disableMemoryOnlyKeys?: () => void; +}; + +const exposeGlobalMemoryOnlyKeysMethods: ExposeGlobalMemoryOnlyKeysMethods = () => { + (window as WindowWithMemoryOnlyKeys).enableMemoryOnlyKeys = () => { + MemoryOnlyKeys.enable(); + }; + (window as WindowWithMemoryOnlyKeys).disableMemoryOnlyKeys = () => { + MemoryOnlyKeys.disable(); + }; +}; + +export default exposeGlobalMemoryOnlyKeysMethods; diff --git a/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/types.ts b/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/types.ts new file mode 100644 index 000000000000..4cb50041b627 --- /dev/null +++ b/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/types.ts @@ -0,0 +1,3 @@ +type ExposeGlobalMemoryOnlyKeysMethods = () => void; + +export default ExposeGlobalMemoryOnlyKeysMethods; From cf2d8e60ac26d35726312388187a4b9f495c3015 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Tue, 28 Nov 2023 18:10:36 +0100 Subject: [PATCH 03/25] [TS migration] Migrate 'CanvasSize.js' lib --- src/libs/actions/{CanvasSize.js => CanvasSize.ts} | 6 +++--- src/types/modules/canvas-size.d.ts | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) rename src/libs/actions/{CanvasSize.js => CanvasSize.ts} (89%) create mode 100644 src/types/modules/canvas-size.d.ts diff --git a/src/libs/actions/CanvasSize.js b/src/libs/actions/CanvasSize.ts similarity index 89% rename from src/libs/actions/CanvasSize.js rename to src/libs/actions/CanvasSize.ts index b313763131b9..9de851aacae3 100644 --- a/src/libs/actions/CanvasSize.js +++ b/src/libs/actions/CanvasSize.ts @@ -16,7 +16,7 @@ function retrieveMaxCanvasArea() { useWorker: false, }) .then(() => ({ - onSuccess: (width, height) => { + onSuccess: (width: number, height: number) => { Onyx.merge(ONYXKEYS.MAX_CANVAS_AREA, width * height); }, })); @@ -27,7 +27,7 @@ function retrieveMaxCanvasArea() { */ function retrieveMaxCanvasHeight() { canvasSize.maxHeight({ - onSuccess: (width, height) => { + onSuccess: (width: number, height: number) => { Onyx.merge(ONYXKEYS.MAX_CANVAS_HEIGHT, height); }, }); @@ -38,7 +38,7 @@ function retrieveMaxCanvasHeight() { */ function retrieveMaxCanvasWidth() { canvasSize.maxWidth({ - onSuccess: (width) => { + onSuccess: (width: number) => { Onyx.merge(ONYXKEYS.MAX_CANVAS_WIDTH, width); }, }); diff --git a/src/types/modules/canvas-size.d.ts b/src/types/modules/canvas-size.d.ts new file mode 100644 index 000000000000..6e1243aa657a --- /dev/null +++ b/src/types/modules/canvas-size.d.ts @@ -0,0 +1,6 @@ +/* eslint-disable @typescript-eslint/consistent-type-definitions */ +declare module 'canvas-size' { + import canvasSize from 'canvas-size'; + + export default canvasSize; +} From 819b77ab8f52e06c259d63ffa2877128237638c2 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Tue, 28 Nov 2023 18:19:21 +0100 Subject: [PATCH 04/25] Add window.d.ts file --- .../exposeGlobalMemoryOnlyKeysMethods/index.ts | 9 ++------- src/types/modules/window.d.ts | 10 ++++++++++ 2 files changed, 12 insertions(+), 7 deletions(-) create mode 100644 src/types/modules/window.d.ts diff --git a/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.ts b/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.ts index 6d72188803d7..4514edacb288 100644 --- a/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.ts +++ b/src/libs/actions/MemoryOnlyKeys/exposeGlobalMemoryOnlyKeysMethods/index.ts @@ -1,16 +1,11 @@ import * as MemoryOnlyKeys from '@userActions/MemoryOnlyKeys/MemoryOnlyKeys'; import type ExposeGlobalMemoryOnlyKeysMethods from './types'; -type WindowWithMemoryOnlyKeys = Window & { - enableMemoryOnlyKeys?: () => void; - disableMemoryOnlyKeys?: () => void; -}; - const exposeGlobalMemoryOnlyKeysMethods: ExposeGlobalMemoryOnlyKeysMethods = () => { - (window as WindowWithMemoryOnlyKeys).enableMemoryOnlyKeys = () => { + window.enableMemoryOnlyKeys = () => { MemoryOnlyKeys.enable(); }; - (window as WindowWithMemoryOnlyKeys).disableMemoryOnlyKeys = () => { + window.disableMemoryOnlyKeys = () => { MemoryOnlyKeys.disable(); }; }; diff --git a/src/types/modules/window.d.ts b/src/types/modules/window.d.ts new file mode 100644 index 000000000000..1910c26768f5 --- /dev/null +++ b/src/types/modules/window.d.ts @@ -0,0 +1,10 @@ +declare global { + // eslint-disable-next-line @typescript-eslint/consistent-type-definitions + interface Window { + enableMemoryOnlyKeys: () => void; + disableMemoryOnlyKeys: () => void; + } +} + +// We used the export {} line to mark this file as an external module +export {}; From 2b59ded20f16607387c43b37bfa85230c6f04e31 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 29 Nov 2023 09:25:51 +0100 Subject: [PATCH 05/25] [TS migration] Migrate 'Card.js' lib --- src/libs/actions/Card.js | 176 ------------------------------------- src/libs/actions/Card.ts | 184 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+), 176 deletions(-) delete mode 100644 src/libs/actions/Card.js create mode 100644 src/libs/actions/Card.ts diff --git a/src/libs/actions/Card.js b/src/libs/actions/Card.js deleted file mode 100644 index 9adcd3803766..000000000000 --- a/src/libs/actions/Card.js +++ /dev/null @@ -1,176 +0,0 @@ -import Onyx from 'react-native-onyx'; -import * as API from '@libs/API'; -import * as Localize from '@libs/Localize'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; - -/** - * @param {Number} cardID - */ -function reportVirtualExpensifyCardFraud(cardID) { - API.write( - 'ReportVirtualExpensifyCardFraud', - { - cardID, - }, - { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, - value: { - isLoading: true, - }, - }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, - value: { - isLoading: false, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, - value: { - isLoading: false, - }, - }, - ], - }, - ); -} - -/** - * Call the API to deactivate the card and request a new one - * @param {String} cardId - id of the card that is going to be replaced - * @param {String} reason - reason for replacement ('damaged' | 'stolen') - */ -function requestReplacementExpensifyCard(cardId, reason) { - API.write( - 'RequestReplacementExpensifyCard', - { - cardId, - reason, - }, - { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM, - value: { - isLoading: true, - errors: null, - }, - }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM, - value: { - isLoading: false, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM, - value: { - isLoading: false, - }, - }, - ], - }, - ); -} - -/** - * Activates the physical Expensify card based on the last four digits of the card number - * - * @param {Number} cardLastFourDigits - * @param {Number} cardID - */ -function activatePhysicalExpensifyCard(cardLastFourDigits, cardID) { - API.write( - 'ActivatePhysicalExpensifyCard', - {cardLastFourDigits, cardID}, - { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.CARD_LIST, - value: { - [cardID]: { - errors: null, - isLoading: true, - }, - }, - }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.CARD_LIST, - value: { - [cardID]: { - isLoading: false, - }, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.CARD_LIST, - value: { - [cardID]: { - isLoading: false, - }, - }, - }, - ], - }, - ); -} - -/** - * Clears errors for a specific cardID - * - * @param {Number} cardID - */ -function clearCardListErrors(cardID) { - Onyx.merge(ONYXKEYS.CARD_LIST, {[cardID]: {errors: null, isLoading: false}}); -} - -/** - * Makes an API call to get virtual card details (pan, cvv, expiration date, address) - * This function purposefully uses `makeRequestWithSideEffects` method. For security reason - * card details cannot be persisted in Onyx and have to be asked for each time a user want's to - * reveal them. - * - * @param {String} cardID - virtual card ID - * - * @returns {Promise} - promise with card details object - */ -function revealVirtualCardDetails(cardID) { - return new Promise((resolve, reject) => { - // eslint-disable-next-line rulesdir/no-api-side-effects-method - API.makeRequestWithSideEffects('RevealExpensifyCardDetails', {cardID}) - .then((response) => { - if (response.jsonCode !== CONST.JSON_CODE.SUCCESS) { - reject(Localize.translateLocal('cardPage.cardDetailsLoadingFailure')); - return; - } - resolve(response); - }) - .catch(() => reject(Localize.translateLocal('cardPage.cardDetailsLoadingFailure'))); - }); -} - -export {requestReplacementExpensifyCard, activatePhysicalExpensifyCard, clearCardListErrors, reportVirtualExpensifyCardFraud, revealVirtualCardDetails}; diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts new file mode 100644 index 000000000000..8dd049db1f30 --- /dev/null +++ b/src/libs/actions/Card.ts @@ -0,0 +1,184 @@ +import Onyx from 'react-native-onyx'; +import * as API from '@libs/API'; +import * as Localize from '@libs/Localize'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import {Response} from '@src/types/onyx'; + +function reportVirtualExpensifyCardFraud(cardID: number) { + type ReportVirtualExpensifyCardFraudParams = { + cardID: number; + }; + + const reportVirtualExpensifyCardFraudParams: ReportVirtualExpensifyCardFraudParams = { + cardID, + }; + + API.write('ReportVirtualExpensifyCardFraud', reportVirtualExpensifyCardFraudParams, { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, + value: { + isLoading: true, + }, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, + value: { + isLoading: false, + }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, + value: { + isLoading: false, + }, + }, + ], + }); +} + +/** + * Call the API to deactivate the card and request a new one + * @param cardId - id of the card that is going to be replaced + * @param reason - reason for replacement ('damaged' | 'stolen') + */ +function requestReplacementExpensifyCard(cardId: number, reason: string) { + type RequestReplacementExpensifyCardParams = { + cardId: number; + reason: string; + }; + + const requestReplacementExpensifyCardParams: RequestReplacementExpensifyCardParams = { + cardId, + reason, + }; + + API.write('RequestReplacementExpensifyCard', requestReplacementExpensifyCardParams, { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM, + value: { + isLoading: true, + errors: null, + }, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM, + value: { + isLoading: false, + }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM, + value: { + isLoading: false, + }, + }, + ], + }); +} + +/** + * Activates the physical Expensify card based on the last four digits of the card number + */ +function activatePhysicalExpensifyCard(cardLastFourDigits: number, cardID: number) { + type ActivatePhysicalExpensifyCardParams = { + cardLastFourDigits: number; + cardID: number; + }; + + const activatePhysicalExpensifyCardParams: ActivatePhysicalExpensifyCardParams = { + cardLastFourDigits, + cardID, + }; + + API.write('ActivatePhysicalExpensifyCard', activatePhysicalExpensifyCardParams, { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.CARD_LIST, + value: { + [cardID]: { + errors: null, + isLoading: true, + }, + }, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.CARD_LIST, + value: { + [cardID]: { + isLoading: false, + }, + }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.CARD_LIST, + value: { + [cardID]: { + isLoading: false, + }, + }, + }, + ], + }); +} + +/** + * Clears errors for a specific cardID + */ +function clearCardListErrors(cardID: number) { + Onyx.merge(ONYXKEYS.CARD_LIST, {[cardID]: {errors: null, isLoading: false}}); +} + +/** + * Makes an API call to get virtual card details (pan, cvv, expiration date, address) + * This function purposefully uses `makeRequestWithSideEffects` method. For security reason + * card details cannot be persisted in Onyx and have to be asked for each time a user want's to + * reveal them. + * + * @param cardID - virtual card ID + * + * @returns promise with card details object + */ +function revealVirtualCardDetails(cardID: number): Promise { + return new Promise((resolve, reject) => { + type RevealExpensifyCardDetailsParams = {cardID: number}; + + const revealExpensifyCardDetailsParams: RevealExpensifyCardDetailsParams = {cardID}; + + // eslint-disable-next-line rulesdir/no-api-side-effects-method + API.makeRequestWithSideEffects('RevealExpensifyCardDetails', revealExpensifyCardDetailsParams) + .then((response) => { + if (response?.jsonCode !== CONST.JSON_CODE.SUCCESS) { + reject(Localize.translateLocal('cardPage.cardDetailsLoadingFailure')); + return; + } + resolve(response); + }) + .catch(() => reject(Localize.translateLocal('cardPage.cardDetailsLoadingFailure'))); + }); +} + +export {requestReplacementExpensifyCard, activatePhysicalExpensifyCard, clearCardListErrors, reportVirtualExpensifyCardFraud, revealVirtualCardDetails}; From 3e15c67d4feb074f8bd6f949c75cda9bae8dc6e9 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 29 Nov 2023 09:31:46 +0100 Subject: [PATCH 06/25] TS update after main merging --- src/libs/actions/Card.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 8dd049db1f30..82137cc7c4cc 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -96,9 +96,9 @@ function requestReplacementExpensifyCard(cardId: number, reason: string) { /** * Activates the physical Expensify card based on the last four digits of the card number */ -function activatePhysicalExpensifyCard(cardLastFourDigits: number, cardID: number) { +function activatePhysicalExpensifyCard(cardLastFourDigits: string, cardID: number) { type ActivatePhysicalExpensifyCardParams = { - cardLastFourDigits: number; + cardLastFourDigits: string; cardID: number; }; From ad02a8c6f431f5a75fcebe3e1b27a13e97000f13 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 29 Nov 2023 09:55:10 +0100 Subject: [PATCH 07/25] [TS migration] Migrate 'OnyxUpdateManager.ts' lib --- src/libs/actions/App.ts | 4 ++-- ...xUpdateManager.js => OnyxUpdateManager.ts} | 24 +++++++++---------- src/libs/actions/OnyxUpdates.ts | 1 + 3 files changed, 15 insertions(+), 14 deletions(-) rename src/libs/actions/{OnyxUpdateManager.js => OnyxUpdateManager.ts} (85%) diff --git a/src/libs/actions/App.ts b/src/libs/actions/App.ts index 4de8f1c1f171..ff4e798ba92a 100644 --- a/src/libs/actions/App.ts +++ b/src/libs/actions/App.ts @@ -293,12 +293,12 @@ function finalReconnectAppAfterActivatingReliableUpdates(): Promise { +function getMissingOnyxUpdates(updateIDFrom = 0, updateIDTo: number | string = 0): Promise { console.debug(`[OnyxUpdates] Fetching missing updates updateIDFrom: ${updateIDFrom} and updateIDTo: ${updateIDTo}`); type GetMissingOnyxMessagesParams = { updateIDFrom: number; - updateIDTo: number; + updateIDTo: number | string; }; const parameters: GetMissingOnyxMessagesParams = { diff --git a/src/libs/actions/OnyxUpdateManager.js b/src/libs/actions/OnyxUpdateManager.ts similarity index 85% rename from src/libs/actions/OnyxUpdateManager.js rename to src/libs/actions/OnyxUpdateManager.ts index 21cea452295b..b61c8eeae268 100644 --- a/src/libs/actions/OnyxUpdateManager.js +++ b/src/libs/actions/OnyxUpdateManager.ts @@ -1,5 +1,4 @@ import Onyx from 'react-native-onyx'; -import _ from 'underscore'; import Log from '@libs/Log'; import * as SequentialQueue from '@libs/Network/SequentialQueue'; import CONST from '@src/CONST'; @@ -22,27 +21,28 @@ import * as OnyxUpdates from './OnyxUpdates'; // The circular dependency happens because this file calls API.GetMissingOnyxUpdates() which uses the SaveResponseInOnyx.js file // (as a middleware). Therefore, SaveResponseInOnyx.js can't import and use this file directly. -let lastUpdateIDAppliedToClient = 0; +let lastUpdateIDAppliedToClient: number | null = 0; Onyx.connect({ key: ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT, - callback: (val) => (lastUpdateIDAppliedToClient = val), + callback: (value) => (lastUpdateIDAppliedToClient = value), }); export default () => { console.debug('[OnyxUpdateManager] Listening for updates from the server'); Onyx.connect({ key: ONYXKEYS.ONYX_UPDATES_FROM_SERVER, - callback: (val) => { - if (!val) { + callback: (value) => { + if (!value) { return; } // Since we used the same key that used to store another object, let's confirm that the current object is // following the new format before we proceed. If it isn't, then let's clear the object in Onyx. if ( - !_.isObject(val) || - !_.has(val, 'type') || - (!(val.type === CONST.ONYX_UPDATE_TYPES.HTTPS && _.has(val, 'request') && _.has(val, 'response')) && !(val.type === CONST.ONYX_UPDATE_TYPES.PUSHER && _.has(val, 'updates'))) + value === null || + !Object.hasOwn(value, 'type') || + (!(value.type === CONST.ONYX_UPDATE_TYPES.HTTPS && Object.hasOwn(value, 'request') && Object.hasOwn(value, 'response')) && + !(value.type === CONST.ONYX_UPDATE_TYPES.PUSHER && Object.hasOwn(value, 'updates'))) ) { console.debug('[OnyxUpdateManager] Invalid format found for updates, cleaning and unpausing the queue'); Onyx.set(ONYXKEYS.ONYX_UPDATES_FROM_SERVER, null); @@ -50,9 +50,9 @@ export default () => { return; } - const updateParams = val; - const lastUpdateIDFromServer = val.lastUpdateID; - const previousUpdateIDFromServer = val.previousUpdateID; + const updateParams = value; + const lastUpdateIDFromServer = value.lastUpdateID; + const previousUpdateIDFromServer = value.previousUpdateID; // In cases where we received a previousUpdateID and it doesn't match our lastUpdateIDAppliedToClient // we need to perform one of the 2 possible cases: @@ -76,7 +76,7 @@ export default () => { canUnpauseQueuePromise = App.finalReconnectAppAfterActivatingReliableUpdates(); } else { // The flow below is setting the promise to a getMissingOnyxUpdates to address flow (2) explained above. - console.debug(`[OnyxUpdateManager] Client is behind the server by ${previousUpdateIDFromServer - lastUpdateIDAppliedToClient} so fetching incremental updates`); + console.debug(`[OnyxUpdateManager] Client is behind the server by ${Number(previousUpdateIDFromServer) - lastUpdateIDAppliedToClient} so fetching incremental updates`); Log.info('Gap detected in update IDs from server so fetching incremental updates', true, { lastUpdateIDFromServer, previousUpdateIDFromServer, diff --git a/src/libs/actions/OnyxUpdates.ts b/src/libs/actions/OnyxUpdates.ts index ce673fa6aaaf..af3a16cd3b54 100644 --- a/src/libs/actions/OnyxUpdates.ts +++ b/src/libs/actions/OnyxUpdates.ts @@ -68,6 +68,7 @@ function applyPusherOnyxUpdates(updates: OnyxUpdateEvent[]) { */ function apply({lastUpdateID, type, request, response, updates}: Merge): Promise; function apply({lastUpdateID, type, request, response, updates}: Merge): Promise; +function apply({lastUpdateID, type, request, response, updates}: OnyxUpdatesFromServer): Promise; function apply({lastUpdateID, type, request, response, updates}: OnyxUpdatesFromServer): Promise | undefined { console.debug(`[OnyxUpdateManager] Applying update type: ${type} with lastUpdateID: ${lastUpdateID}`, {request, response, updates}); From 21eac298f59a709433b1110633f796d4dd848528 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 29 Nov 2023 10:06:43 +0100 Subject: [PATCH 08/25] [TS migration] Migrate 'DemoActions.js' lib --- src/libs/Navigation/Navigation.ts | 4 ++-- .../{DemoActions.js => DemoActions.ts} | 24 ++++++++++++------- src/types/onyx/Response.ts | 1 + 3 files changed, 18 insertions(+), 11 deletions(-) rename src/libs/actions/{DemoActions.js => DemoActions.ts} (80%) diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts index c2dd3e76e7ad..e90c092327fd 100644 --- a/src/libs/Navigation/Navigation.ts +++ b/src/libs/Navigation/Navigation.ts @@ -69,7 +69,7 @@ function getActiveRouteIndex(stateOrRoute: StateOrRoute, index?: number): number * @param path - Path that you are looking for. * @return - Returns distance to path or -1 if the path is not found in root navigator. */ -function getDistanceFromPathInRootNavigator(path: string): number { +function getDistanceFromPathInRootNavigator(path?: string): number { let currentState = navigationRef.getRootState(); for (let index = 0; index < 5; index++) { @@ -138,7 +138,7 @@ function navigate(route: Route = ROUTES.HOME, type?: string) { * @param shouldEnforceFallback - Enforces navigation to fallback route * @param shouldPopToTop - Should we navigate to LHN on back press */ -function goBack(fallbackRoute: Route, shouldEnforceFallback = false, shouldPopToTop = false) { +function goBack(fallbackRoute?: Route, shouldEnforceFallback = false, shouldPopToTop = false) { if (!canNavigate('goBack')) { return; } diff --git a/src/libs/actions/DemoActions.js b/src/libs/actions/DemoActions.ts similarity index 80% rename from src/libs/actions/DemoActions.js rename to src/libs/actions/DemoActions.ts index 245e475e7ca9..41f5a54977cb 100644 --- a/src/libs/actions/DemoActions.js +++ b/src/libs/actions/DemoActions.ts @@ -1,4 +1,3 @@ -import lodashGet from 'lodash/get'; import Config from 'react-native-config'; import Onyx from 'react-native-onyx'; import * as API from '@libs/API'; @@ -7,17 +6,17 @@ import * as ReportUtils from '@libs/ReportUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -let currentUserEmail; +let currentUserEmail: string; Onyx.connect({ key: ONYXKEYS.SESSION, callback: (val) => { - currentUserEmail = lodashGet(val, 'email', ''); + currentUserEmail = val?.email ?? ''; }, }); function runMoney2020Demo() { // Try to navigate to existing demo chat if it exists in Onyx - const money2020AccountID = Number(lodashGet(Config, 'EXPENSIFY_ACCOUNT_ID_MONEY2020', 15864555)); + const money2020AccountID = Number(Config.EXPENSIFY_ACCOUNT_ID_MONEY2020 ?? 15864555); const existingChatReport = ReportUtils.getChatByParticipants([money2020AccountID]); if (existingChatReport) { // We must call goBack() to remove the demo route from nav history @@ -26,12 +25,19 @@ function runMoney2020Demo() { return; } - // We use makeRequestWithSideEffects here because we need to get the chat report ID to navigate to it after it's created - // eslint-disable-next-line rulesdir/no-api-side-effects-method - API.makeRequestWithSideEffects('CreateChatReport', { + type CreateChatReportParams = { + emailList: string; + activationConference: string; + }; + + const createChatReportParams: CreateChatReportParams = { emailList: `${currentUserEmail},money2020@expensify.com`, activationConference: 'money2020', - }).then((response) => { + }; + + // We use makeRequestWithSideEffects here because we need to get the chat report ID to navigate to it after it's created + // eslint-disable-next-line rulesdir/no-api-side-effects-method + API.makeRequestWithSideEffects('CreateChatReport', createChatReportParams).then((response) => { // If there's no response or no reportID in the response, navigate the user home so user doesn't get stuck. if (!response || !response.reportID) { Navigation.goBack(); @@ -50,7 +56,7 @@ function runMoney2020Demo() { /** * Runs code for specific demos, based on the provided URL * - * @param {String} url - URL user is navigating to via deep link (or regular link in web) + * @param url - URL user is navigating to via deep link (or regular link in web) */ function runDemoByURL(url = '') { const cleanUrl = (url || '').toLowerCase(); diff --git a/src/types/onyx/Response.ts b/src/types/onyx/Response.ts index 66d5dcbdfd5b..c002c75ec075 100644 --- a/src/types/onyx/Response.ts +++ b/src/types/onyx/Response.ts @@ -11,6 +11,7 @@ type Response = { jsonCode?: number | string; onyxData?: OnyxUpdate[]; requestID?: string; + reportID?: string; shouldPauseQueue?: boolean; authToken?: string; encryptedAuthToken?: string; From 02d646d1c4d503639077a60d4eb97813446d6d82 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 29 Nov 2023 12:12:23 +0100 Subject: [PATCH 09/25] [TS migration] Migrate 'TeacherUnite.js' lib --- src/ONYXKEYS.ts | 2 +- src/libs/PolicyUtils.ts | 2 +- src/libs/ReportUtils.ts | 12 +- src/libs/actions/TeachersUnite.js | 180 ---------------------------- src/libs/actions/TeachersUnite.ts | 189 ++++++++++++++++++++++++++++++ src/types/onyx/OriginalMessage.ts | 4 +- src/types/onyx/PersonalDetails.ts | 4 +- src/types/onyx/Policy.ts | 10 +- src/types/onyx/Report.ts | 3 + src/types/onyx/ReportAction.ts | 2 +- src/types/onyx/index.ts | 3 +- 11 files changed, 213 insertions(+), 198 deletions(-) delete mode 100644 src/libs/actions/TeachersUnite.js create mode 100644 src/libs/actions/TeachersUnite.ts diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 0cb3f67bd990..d9d6fb502e5e 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -366,7 +366,7 @@ type OnyxValues = { [ONYXKEYS.NETWORK]: OnyxTypes.Network; [ONYXKEYS.CUSTOM_STATUS_DRAFT]: OnyxTypes.CustomStatusDraft; [ONYXKEYS.INPUT_FOCUSED]: boolean; - [ONYXKEYS.PERSONAL_DETAILS_LIST]: Record; + [ONYXKEYS.PERSONAL_DETAILS_LIST]: OnyxTypes.PersonalDetailsList; [ONYXKEYS.PRIVATE_PERSONAL_DETAILS]: OnyxTypes.PrivatePersonalDetails; [ONYXKEYS.TASK]: OnyxTypes.Task; [ONYXKEYS.CURRENCY_LIST]: Record; diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 19129959d016..04bf08889870 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -16,7 +16,7 @@ type UnitRate = {rate: number}; function getActivePolicies(policies: OnyxCollection): Policy[] | undefined { return Object.values(policies ?? {}).filter( (policy): policy is Policy => - policy !== null && policy && (policy.isPolicyExpenseChatEnabled || policy.areChatRoomsEnabled) && policy.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, + policy !== null && policy && (policy.isPolicyExpenseChatEnabled || !!policy.areChatRoomsEnabled) && policy.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, ); } diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index d93661778b83..a97a24608d66 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -16,8 +16,8 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import {Beta, Login, PersonalDetails, Policy, PolicyTags, Report, ReportAction, Transaction} from '@src/types/onyx'; import {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; -import {ChangeLog, IOUMessage, OriginalMessageActionName} from '@src/types/onyx/OriginalMessage'; -import {Message, ReportActions} from '@src/types/onyx/ReportAction'; +import {ChangeLog, IOUMessage, OriginalMessageActionName, OriginalMessageCreated} from '@src/types/onyx/OriginalMessage'; +import {Message, ReportActionBase, ReportActions} from '@src/types/onyx/ReportAction'; import {Receipt, WaypointCollection} from '@src/types/onyx/Transaction'; import DeepValueOf from '@src/types/utils/DeepValueOf'; import {EmptyObject, isEmptyObject, isNotEmptyObject} from '@src/types/utils/EmptyObject'; @@ -184,9 +184,10 @@ type OptimisticClosedReportAction = Pick< >; type OptimisticCreatedReportAction = Pick< - ReportAction, - 'actionName' | 'actorAccountID' | 'automatic' | 'avatar' | 'created' | 'message' | 'person' | 'reportActionID' | 'shouldShow' | 'pendingAction' ->; + ReportActionBase, + 'actorAccountID' | 'automatic' | 'avatar' | 'created' | 'message' | 'person' | 'reportActionID' | 'shouldShow' | 'pendingAction' +> & + OriginalMessageCreated; type OptimisticChatReport = Pick< Report, @@ -311,7 +312,6 @@ type DisplayNameWithTooltips = Array { - sessionEmail = lodashGet(val, 'email', ''); - sessionAccountID = lodashGet(val, 'accountID', 0); - }, -}); - -let allPersonalDetails; -Onyx.connect({ - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - callback: (val) => (allPersonalDetails = val), -}); - -/** - * @param {String} partnerUserID - * @param {String} firstName - * @param {String} lastName - */ -function referTeachersUniteVolunteer(partnerUserID, firstName, lastName) { - const optimisticPublicRoom = ReportUtils.buildOptimisticChatReport([], CONST.TEACHERS_UNITE.PUBLIC_ROOM_NAME, CONST.REPORT.CHAT_TYPE.POLICY_ROOM, CONST.TEACHERS_UNITE.POLICY_ID); - const optimisticData = [ - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.REPORT}${optimisticPublicRoom.reportID}`, - value: { - ...optimisticPublicRoom, - reportID: optimisticPublicRoom.reportID, - policyName: CONST.TEACHERS_UNITE.POLICY_NAME, - }, - }, - ]; - API.write( - 'ReferTeachersUniteVolunteer', - { - publicRoomReportID: optimisticPublicRoom.reportID, - firstName, - lastName, - partnerUserID, - }, - {optimisticData}, - ); - Navigation.dismissModal(CONST.TEACHERS_UNITE.PUBLIC_ROOM_ID); -} - -/** - * Optimistically creates a policyExpenseChat for the school principal and passes data to AddSchoolPrincipal - * @param {String} firstName - * @param {String} partnerUserID - * @param {String} lastName - */ -function addSchoolPrincipal(firstName, partnerUserID, lastName) { - const policyName = CONST.TEACHERS_UNITE.POLICY_NAME; - const policyID = CONST.TEACHERS_UNITE.POLICY_ID; - const loggedInEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(sessionEmail); - const reportCreationData = {}; - - const expenseChatData = ReportUtils.buildOptimisticChatReport([sessionAccountID], '', CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, policyID, sessionAccountID, true, policyName); - const expenseChatReportID = expenseChatData.reportID; - const expenseReportCreatedAction = ReportUtils.buildOptimisticCreatedReportAction(sessionEmail); - const expenseReportActionData = { - [expenseReportCreatedAction.reportActionID]: expenseReportCreatedAction, - }; - - reportCreationData[loggedInEmail] = { - reportID: expenseChatReportID, - reportActionID: expenseReportCreatedAction.reportActionID, - }; - - API.write( - 'AddSchoolPrincipal', - { - firstName, - lastName, - partnerUserID, - reportCreationData: JSON.stringify(reportCreationData), - }, - { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - id: policyID, - isPolicyExpenseChatEnabled: true, - type: CONST.POLICY.TYPE.CORPORATE, - name: policyName, - role: CONST.POLICY.ROLE.USER, - owner: sessionEmail, - outputCurrency: lodashGet(allPersonalDetails, [sessionAccountID, 'localCurrencyCode'], CONST.CURRENCY.USD), - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - }, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, - value: { - [sessionAccountID]: { - role: CONST.POLICY.ROLE.USER, - errors: {}, - }, - }, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, - value: { - pendingFields: { - addWorkspaceRoom: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - }, - ...expenseChatData, - }, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, - value: expenseReportActionData, - }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: {pendingAction: null}, - }, - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, - value: { - pendingFields: { - addWorkspaceRoom: null, - }, - pendingAction: null, - }, - }, - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, - value: { - [_.keys(expenseChatData)[0]]: { - pendingAction: null, - }, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, - value: null, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, - value: null, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, - value: null, - }, - ], - }, - ); - Navigation.dismissModal(expenseChatReportID); -} - -export default {referTeachersUniteVolunteer, addSchoolPrincipal}; diff --git a/src/libs/actions/TeachersUnite.ts b/src/libs/actions/TeachersUnite.ts new file mode 100644 index 000000000000..4b1438090312 --- /dev/null +++ b/src/libs/actions/TeachersUnite.ts @@ -0,0 +1,189 @@ +import Onyx, {OnyxEntry, OnyxUpdate} from 'react-native-onyx'; +import * as API from '@libs/API'; +import Navigation from '@libs/Navigation/Navigation'; +import * as OptionsListUtils from '@libs/OptionsListUtils'; +import * as ReportUtils from '@libs/ReportUtils'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import {PersonalDetailsList} from '@src/types/onyx'; + +type CreationData = { + reportID: string; + reportActionID: string; +}; + +type ReportCreationData = Record; + +let sessionEmail = ''; +let sessionAccountID = 0; +Onyx.connect({ + key: ONYXKEYS.SESSION, + callback: (value) => { + sessionEmail = value?.email ?? ''; + sessionAccountID = value?.accountID ?? 0; + }, +}); + +let allPersonalDetails: OnyxEntry; +Onyx.connect({ + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + callback: (val) => (allPersonalDetails = val), +}); + +function referTeachersUniteVolunteer(partnerUserID: string, firstName: string, lastName: string) { + const optimisticPublicRoom = ReportUtils.buildOptimisticChatReport([], CONST.TEACHERS_UNITE.PUBLIC_ROOM_NAME, CONST.REPORT.CHAT_TYPE.POLICY_ROOM, CONST.TEACHERS_UNITE.POLICY_ID); + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${optimisticPublicRoom.reportID}`, + value: { + ...optimisticPublicRoom, + reportID: optimisticPublicRoom.reportID, + policyName: CONST.TEACHERS_UNITE.POLICY_NAME, + }, + }, + ]; + + type ReferTeachersUniteVolunteerParams = { + publicRoomReportID: string; + firstName: string; + lastName: string; + partnerUserID: string; + }; + + const parameters: ReferTeachersUniteVolunteerParams = { + publicRoomReportID: optimisticPublicRoom.reportID, + firstName, + lastName, + partnerUserID, + }; + + API.write('ReferTeachersUniteVolunteer', parameters, {optimisticData}); + Navigation.dismissModal(CONST.TEACHERS_UNITE.PUBLIC_ROOM_ID); +} + +/** + * Optimistically creates a policyExpenseChat for the school principal and passes data to AddSchoolPrincipal + */ +function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: string) { + const policyName = CONST.TEACHERS_UNITE.POLICY_NAME; + const policyID = CONST.TEACHERS_UNITE.POLICY_ID; + const loggedInEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(sessionEmail); + const reportCreationData: ReportCreationData = {}; + + const expenseChatData = ReportUtils.buildOptimisticChatReport([sessionAccountID], '', CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, policyID, sessionAccountID, true, policyName); + const expenseChatReportID = expenseChatData.reportID; + const expenseReportCreatedAction = ReportUtils.buildOptimisticCreatedReportAction(sessionEmail); + const expenseReportActionData = { + [expenseReportCreatedAction.reportActionID]: expenseReportCreatedAction, + }; + + reportCreationData[loggedInEmail] = { + reportID: expenseChatReportID, + reportActionID: expenseReportCreatedAction.reportActionID, + }; + + type AddSchoolPrincipalParams = { + firstName: string; + lastName: string; + partnerUserID: string; + reportCreationData: string; + }; + + const parameters: AddSchoolPrincipalParams = { + firstName, + lastName, + partnerUserID, + reportCreationData: JSON.stringify(reportCreationData), + }; + + API.write('AddSchoolPrincipal', parameters, { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + id: policyID, + isPolicyExpenseChatEnabled: true, + type: CONST.POLICY.TYPE.CORPORATE, + name: policyName, + role: CONST.POLICY.ROLE.USER, + owner: sessionEmail, + outputCurrency: allPersonalDetails?.[sessionAccountID]?.localCurrencyCode ?? CONST.CURRENCY.USD, + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, + value: { + [sessionAccountID]: { + role: CONST.POLICY.ROLE.USER, + errors: {}, + }, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, + value: { + pendingFields: { + addWorkspaceRoom: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }, + ...expenseChatData, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, + value: expenseReportActionData, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: {pendingAction: null}, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, + value: { + pendingFields: { + addWorkspaceRoom: null, + }, + pendingAction: null, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, + value: { + [Object.keys(expenseChatData)[0]]: { + pendingAction: null, + }, + }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, + value: null, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, + value: null, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, + value: null, + }, + ], + }); + Navigation.dismissModal(expenseChatReportID); +} + +export default {referTeachersUniteVolunteer, addSchoolPrincipal}; diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index 0dc532ebeded..5e0b70831626 100644 --- a/src/types/onyx/OriginalMessage.ts +++ b/src/types/onyx/OriginalMessage.ts @@ -117,7 +117,7 @@ type OriginalMessageClosed = { type OriginalMessageCreated = { actionName: typeof CONST.REPORT.ACTIONS.TYPE.CREATED; - originalMessage: unknown; + originalMessage?: unknown; }; type OriginalMessageRenamed = { @@ -225,4 +225,4 @@ type OriginalMessage = | OriginalMessageMoved; export default OriginalMessage; -export type {ChronosOOOEvent, Decision, Reaction, ActionName, IOUMessage, Closed, OriginalMessageActionName, ChangeLog}; +export type {ChronosOOOEvent, Decision, Reaction, ActionName, IOUMessage, Closed, OriginalMessageActionName, OriginalMessageCreated, ChangeLog}; diff --git a/src/types/onyx/PersonalDetails.ts b/src/types/onyx/PersonalDetails.ts index af559eafd0a1..8f824272230e 100644 --- a/src/types/onyx/PersonalDetails.ts +++ b/src/types/onyx/PersonalDetails.ts @@ -76,6 +76,8 @@ type PersonalDetails = { payPalMeAddress?: string; }; +type PersonalDetailsList = Record; + export default PersonalDetails; -export type {Timezone, SelectedTimezone}; +export type {Timezone, SelectedTimezone, PersonalDetailsList}; diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index e6e3240d1b23..5bef0cf932b1 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -19,7 +19,7 @@ type Policy = { owner: string; /** The accountID of the policy owner */ - ownerAccountID: number; + ownerAccountID?: number; /** The output currency for the policy */ outputCurrency: string; @@ -34,7 +34,7 @@ type Policy = { pendingAction?: OnyxCommon.PendingAction; /** A list of errors keyed by microtime */ - errors: OnyxCommon.Errors; + errors?: OnyxCommon.Errors; /** Whether this policy was loaded from a policy summary, or loaded completely with all of its values */ isFromFullPolicy?: boolean; @@ -46,16 +46,16 @@ type Policy = { customUnits?: Record; /** Whether chat rooms can be created and used on this policy. Enabled manually by CQ/JS snippet. Always true for free policies. */ - areChatRoomsEnabled: boolean; + areChatRoomsEnabled?: boolean; /** Whether policy expense chats can be created and used on this policy. Enabled manually by CQ/JS snippet. Always true for free policies. */ isPolicyExpenseChatEnabled: boolean; /** Whether the scheduled submit is enabled */ - autoReporting: boolean; + autoReporting?: boolean; /** The scheduled submit frequency set up on the this policy */ - autoReportingFrequency: ValueOf; + autoReportingFrequency?: ValueOf; /** The employee list of the policy */ employeeList?: []; diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index 81a92c4bf603..0f0ccdd0826e 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -130,6 +130,9 @@ type Report = { /** Pending fields for the report */ pendingFields?: Record; + /** Pending action for the report */ + pendingAction?: OnyxCommon.PendingAction | null; + /** The ID of the preexisting report (it is possible that we optimistically created a Report for which a report already exists) */ preexistingReportID?: string; diff --git a/src/types/onyx/ReportAction.ts b/src/types/onyx/ReportAction.ts index 891a0ffcb7b8..895ce793ad53 100644 --- a/src/types/onyx/ReportAction.ts +++ b/src/types/onyx/ReportAction.ts @@ -145,4 +145,4 @@ type ReportAction = ReportActionBase & OriginalMessage; type ReportActions = Record; export default ReportAction; -export type {ReportActions, Message}; +export type {ReportActions, Message, ReportActionBase, OriginalMessage}; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index e7b9c7661c79..f4acef24cd18 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -18,7 +18,7 @@ import Modal from './Modal'; import Network from './Network'; import {OnyxUpdateEvent, OnyxUpdatesFromServer} from './OnyxUpdatesFromServer'; import PersonalBankAccount from './PersonalBankAccount'; -import PersonalDetails from './PersonalDetails'; +import PersonalDetails, {PersonalDetailsList} from './PersonalDetails'; import PlaidData from './PlaidData'; import Policy from './Policy'; import PolicyCategory from './PolicyCategory'; @@ -77,6 +77,7 @@ export type { OnyxUpdatesFromServer, PersonalBankAccount, PersonalDetails, + PersonalDetailsList, PlaidData, Policy, PolicyCategory, From 2857187b7c5831e2ddd436c4a4d4ab19a832fd2a Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 29 Nov 2023 12:42:17 +0100 Subject: [PATCH 10/25] Code improvements --- src/libs/ReportUtils.ts | 2 +- src/libs/actions/Card.ts | 18 +++++++++--------- src/libs/actions/DemoActions.ts | 4 ++-- src/libs/actions/TeachersUnite.ts | 9 ++++++--- src/libs/actions/TransactionEdit.ts | 2 +- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a97a24608d66..ae4c4217e6aa 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4383,4 +4383,4 @@ export { canEditWriteCapability, }; -export type {OptionData}; +export type {OptionData, OptimisticCreatedReportAction}; diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 82137cc7c4cc..8a2923d9c6fd 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -3,18 +3,18 @@ import * as API from '@libs/API'; import * as Localize from '@libs/Localize'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import {Response} from '@src/types/onyx'; +import type {Response} from '@src/types/onyx'; function reportVirtualExpensifyCardFraud(cardID: number) { type ReportVirtualExpensifyCardFraudParams = { cardID: number; }; - const reportVirtualExpensifyCardFraudParams: ReportVirtualExpensifyCardFraudParams = { + const parameters: ReportVirtualExpensifyCardFraudParams = { cardID, }; - API.write('ReportVirtualExpensifyCardFraud', reportVirtualExpensifyCardFraudParams, { + API.write('ReportVirtualExpensifyCardFraud', parameters, { optimisticData: [ { onyxMethod: Onyx.METHOD.MERGE, @@ -56,12 +56,12 @@ function requestReplacementExpensifyCard(cardId: number, reason: string) { reason: string; }; - const requestReplacementExpensifyCardParams: RequestReplacementExpensifyCardParams = { + const parameters: RequestReplacementExpensifyCardParams = { cardId, reason, }; - API.write('RequestReplacementExpensifyCard', requestReplacementExpensifyCardParams, { + API.write('RequestReplacementExpensifyCard', parameters, { optimisticData: [ { onyxMethod: Onyx.METHOD.MERGE, @@ -102,12 +102,12 @@ function activatePhysicalExpensifyCard(cardLastFourDigits: string, cardID: numbe cardID: number; }; - const activatePhysicalExpensifyCardParams: ActivatePhysicalExpensifyCardParams = { + const parameters: ActivatePhysicalExpensifyCardParams = { cardLastFourDigits, cardID, }; - API.write('ActivatePhysicalExpensifyCard', activatePhysicalExpensifyCardParams, { + API.write('ActivatePhysicalExpensifyCard', parameters, { optimisticData: [ { onyxMethod: Onyx.METHOD.MERGE, @@ -166,10 +166,10 @@ function revealVirtualCardDetails(cardID: number): Promise { return new Promise((resolve, reject) => { type RevealExpensifyCardDetailsParams = {cardID: number}; - const revealExpensifyCardDetailsParams: RevealExpensifyCardDetailsParams = {cardID}; + const parameters: RevealExpensifyCardDetailsParams = {cardID}; // eslint-disable-next-line rulesdir/no-api-side-effects-method - API.makeRequestWithSideEffects('RevealExpensifyCardDetails', revealExpensifyCardDetailsParams) + API.makeRequestWithSideEffects('RevealExpensifyCardDetails', parameters) .then((response) => { if (response?.jsonCode !== CONST.JSON_CODE.SUCCESS) { reject(Localize.translateLocal('cardPage.cardDetailsLoadingFailure')); diff --git a/src/libs/actions/DemoActions.ts b/src/libs/actions/DemoActions.ts index 41f5a54977cb..79c7c1652b1c 100644 --- a/src/libs/actions/DemoActions.ts +++ b/src/libs/actions/DemoActions.ts @@ -30,14 +30,14 @@ function runMoney2020Demo() { activationConference: string; }; - const createChatReportParams: CreateChatReportParams = { + const parameters: CreateChatReportParams = { emailList: `${currentUserEmail},money2020@expensify.com`, activationConference: 'money2020', }; // We use makeRequestWithSideEffects here because we need to get the chat report ID to navigate to it after it's created // eslint-disable-next-line rulesdir/no-api-side-effects-method - API.makeRequestWithSideEffects('CreateChatReport', createChatReportParams).then((response) => { + API.makeRequestWithSideEffects('CreateChatReport', parameters).then((response) => { // If there's no response or no reportID in the response, navigate the user home so user doesn't get stuck. if (!response || !response.reportID) { Navigation.goBack(); diff --git a/src/libs/actions/TeachersUnite.ts b/src/libs/actions/TeachersUnite.ts index 4b1438090312..f264d81f33d4 100644 --- a/src/libs/actions/TeachersUnite.ts +++ b/src/libs/actions/TeachersUnite.ts @@ -3,9 +3,10 @@ import * as API from '@libs/API'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as ReportUtils from '@libs/ReportUtils'; +import type {OptimisticCreatedReportAction} from '@libs/ReportUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import {PersonalDetailsList} from '@src/types/onyx'; +import type {PersonalDetailsList} from '@src/types/onyx'; type CreationData = { reportID: string; @@ -14,6 +15,8 @@ type CreationData = { type ReportCreationData = Record; +type ExpenseReportActionData = Record; + let sessionEmail = ''; let sessionAccountID = 0; Onyx.connect({ @@ -27,7 +30,7 @@ Onyx.connect({ let allPersonalDetails: OnyxEntry; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, - callback: (val) => (allPersonalDetails = val), + callback: (value) => (allPersonalDetails = value), }); function referTeachersUniteVolunteer(partnerUserID: string, firstName: string, lastName: string) { @@ -74,7 +77,7 @@ function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: const expenseChatData = ReportUtils.buildOptimisticChatReport([sessionAccountID], '', CONST.REPORT.CHAT_TYPE.POLICY_EXPENSE_CHAT, policyID, sessionAccountID, true, policyName); const expenseChatReportID = expenseChatData.reportID; const expenseReportCreatedAction = ReportUtils.buildOptimisticCreatedReportAction(sessionEmail); - const expenseReportActionData = { + const expenseReportActionData: ExpenseReportActionData = { [expenseReportCreatedAction.reportActionID]: expenseReportCreatedAction, }; diff --git a/src/libs/actions/TransactionEdit.ts b/src/libs/actions/TransactionEdit.ts index 387dacddbcdc..3831ba8e437d 100644 --- a/src/libs/actions/TransactionEdit.ts +++ b/src/libs/actions/TransactionEdit.ts @@ -1,6 +1,6 @@ import Onyx, {OnyxEntry} from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; -import {Transaction} from '@src/types/onyx'; +import type {Transaction} from '@src/types/onyx'; /** * Makes a backup copy of a transaction object that can be restored when the user cancels editing a transaction. From 00cad5e62b9e96fb894c5b40a8c1da27e023aee6 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 29 Nov 2023 15:09:22 +0100 Subject: [PATCH 11/25] Fix crash --- src/libs/actions/DemoActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/DemoActions.ts b/src/libs/actions/DemoActions.ts index 79c7c1652b1c..b764d8268482 100644 --- a/src/libs/actions/DemoActions.ts +++ b/src/libs/actions/DemoActions.ts @@ -16,7 +16,7 @@ Onyx.connect({ function runMoney2020Demo() { // Try to navigate to existing demo chat if it exists in Onyx - const money2020AccountID = Number(Config.EXPENSIFY_ACCOUNT_ID_MONEY2020 ?? 15864555); + const money2020AccountID = Number(Config?.EXPENSIFY_ACCOUNT_ID_MONEY2020 ?? 15864555); const existingChatReport = ReportUtils.getChatByParticipants([money2020AccountID]); if (existingChatReport) { // We must call goBack() to remove the demo route from nav history From f205afe637eab9117f07b3c493fe831eba0d32b1 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Thu, 30 Nov 2023 09:49:29 +0100 Subject: [PATCH 12/25] Add @types/canvas-size lib --- package-lock.json | 13 +++++++++++++ package.json | 1 + src/libs/actions/CanvasSize.ts | 6 +++--- src/libs/actions/Card.ts | 6 ++++-- src/types/modules/canvas-size.d.ts | 6 ------ 5 files changed, 21 insertions(+), 11 deletions(-) delete mode 100644 src/types/modules/canvas-size.d.ts diff --git a/package-lock.json b/package-lock.json index 32271f8dc743..4a333726f64f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -159,6 +159,7 @@ "@testing-library/jest-native": "5.4.1", "@testing-library/react-native": "11.5.1", "@trivago/prettier-plugin-sort-imports": "^4.2.0", + "@types/canvas-size": "^1.2.2", "@types/concurrently": "^7.0.0", "@types/jest": "^29.5.2", "@types/jest-when": "^3.5.2", @@ -19082,6 +19083,12 @@ "@types/responselike": "^1.0.0" } }, + "node_modules/@types/canvas-size": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/canvas-size/-/canvas-size-1.2.2.tgz", + "integrity": "sha512-yuTXFWC4tHV3lt5ZtbIP9VeeMNbDYm5mPyqaQnaMuSSx2mjsfZGXMNmHTnfdsR5qZdB6dtbaV5IP2PKv79vmKg==", + "dev": true + }, "node_modules/@types/concurrently": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@types/concurrently/-/concurrently-7.0.0.tgz", @@ -66435,6 +66442,12 @@ "@types/responselike": "^1.0.0" } }, + "@types/canvas-size": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/canvas-size/-/canvas-size-1.2.2.tgz", + "integrity": "sha512-yuTXFWC4tHV3lt5ZtbIP9VeeMNbDYm5mPyqaQnaMuSSx2mjsfZGXMNmHTnfdsR5qZdB6dtbaV5IP2PKv79vmKg==", + "dev": true + }, "@types/concurrently": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@types/concurrently/-/concurrently-7.0.0.tgz", diff --git a/package.json b/package.json index 7da3658e67b6..15d0f876d45d 100644 --- a/package.json +++ b/package.json @@ -206,6 +206,7 @@ "@testing-library/jest-native": "5.4.1", "@testing-library/react-native": "11.5.1", "@trivago/prettier-plugin-sort-imports": "^4.2.0", + "@types/canvas-size": "^1.2.2", "@types/concurrently": "^7.0.0", "@types/jest": "^29.5.2", "@types/jest-when": "^3.5.2", diff --git a/src/libs/actions/CanvasSize.ts b/src/libs/actions/CanvasSize.ts index 9de851aacae3..8e0a155f25eb 100644 --- a/src/libs/actions/CanvasSize.ts +++ b/src/libs/actions/CanvasSize.ts @@ -11,7 +11,7 @@ function retrieveMaxCanvasArea() { // More information at: https://github.com/jhildenbiddle/canvas-size/issues/13 canvasSize .maxArea({ - max: Browser.isMobile() ? 8192 : null, + max: Browser.isMobile() ? 8192 : undefined, usePromise: true, useWorker: false, }) @@ -27,7 +27,7 @@ function retrieveMaxCanvasArea() { */ function retrieveMaxCanvasHeight() { canvasSize.maxHeight({ - onSuccess: (width: number, height: number) => { + onSuccess: (width, height) => { Onyx.merge(ONYXKEYS.MAX_CANVAS_HEIGHT, height); }, }); @@ -38,7 +38,7 @@ function retrieveMaxCanvasHeight() { */ function retrieveMaxCanvasWidth() { canvasSize.maxWidth({ - onSuccess: (width: number) => { + onSuccess: (width) => { Onyx.merge(ONYXKEYS.MAX_CANVAS_WIDTH, width); }, }); diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 8a2923d9c6fd..6e1753fbd591 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -5,6 +5,8 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Response} from '@src/types/onyx'; +type Reason = 'damaged' | 'stolen'; + function reportVirtualExpensifyCardFraud(cardID: number) { type ReportVirtualExpensifyCardFraudParams = { cardID: number; @@ -48,9 +50,9 @@ function reportVirtualExpensifyCardFraud(cardID: number) { /** * Call the API to deactivate the card and request a new one * @param cardId - id of the card that is going to be replaced - * @param reason - reason for replacement ('damaged' | 'stolen') + * @param reason - reason for replacement */ -function requestReplacementExpensifyCard(cardId: number, reason: string) { +function requestReplacementExpensifyCard(cardId: number, reason: Reason) { type RequestReplacementExpensifyCardParams = { cardId: number; reason: string; diff --git a/src/types/modules/canvas-size.d.ts b/src/types/modules/canvas-size.d.ts deleted file mode 100644 index 6e1243aa657a..000000000000 --- a/src/types/modules/canvas-size.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -/* eslint-disable @typescript-eslint/consistent-type-definitions */ -declare module 'canvas-size' { - import canvasSize from 'canvas-size'; - - export default canvasSize; -} From 27c9dde4f846bcbe58187e53ea500618a748c77b Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Thu, 30 Nov 2023 10:04:28 +0100 Subject: [PATCH 13/25] Update code to use PersonalDetailsList type --- src/components/ArchivedReportFooter.tsx | 4 ++-- src/libs/GroupChatUtils.ts | 4 ++-- src/libs/PolicyUtils.ts | 3 +-- src/libs/ReportUtils.ts | 4 ++-- src/libs/actions/PersonalDetails.ts | 4 ++-- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/components/ArchivedReportFooter.tsx b/src/components/ArchivedReportFooter.tsx index 3187bf3604e8..712ef6be769e 100644 --- a/src/components/ArchivedReportFooter.tsx +++ b/src/components/ArchivedReportFooter.tsx @@ -8,7 +8,7 @@ import * as ReportUtils from '@libs/ReportUtils'; import useThemeStyles from '@styles/useThemeStyles'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {PersonalDetails, Report, ReportAction} from '@src/types/onyx'; +import type {PersonalDetailsList, Report, ReportAction} from '@src/types/onyx'; import Banner from './Banner'; type ArchivedReportFooterOnyxProps = { @@ -16,7 +16,7 @@ type ArchivedReportFooterOnyxProps = { reportClosedAction: OnyxEntry; /** Personal details of all users */ - personalDetails: OnyxEntry>; + personalDetails: OnyxEntry; }; type ArchivedReportFooterProps = ArchivedReportFooterOnyxProps & { diff --git a/src/libs/GroupChatUtils.ts b/src/libs/GroupChatUtils.ts index db64f6574824..862c50700c0c 100644 --- a/src/libs/GroupChatUtils.ts +++ b/src/libs/GroupChatUtils.ts @@ -1,10 +1,10 @@ import Onyx, {OnyxEntry} from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; -import {PersonalDetails, Report} from '@src/types/onyx'; +import {PersonalDetailsList, Report} from '@src/types/onyx'; import * as OptionsListUtils from './OptionsListUtils'; import * as ReportUtils from './ReportUtils'; -let allPersonalDetails: OnyxEntry> = {}; +let allPersonalDetails: OnyxEntry = {}; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, callback: (val) => (allPersonalDetails = val), diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 04bf08889870..d09fdbc892da 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -2,11 +2,10 @@ import Str from 'expensify-common/lib/str'; import {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import {PersonalDetails, Policy, PolicyMembers, PolicyTag, PolicyTags} from '@src/types/onyx'; +import {PersonalDetailsList, Policy, PolicyMembers, PolicyTag, PolicyTags} from '@src/types/onyx'; import {EmptyObject, isEmptyObject} from '@src/types/utils/EmptyObject'; type MemberEmailsToAccountIDs = Record; -type PersonalDetailsList = Record; type UnitRate = {rate: number}; /** diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index ae4c4217e6aa..fb452ce6f26a 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -14,7 +14,7 @@ import CONST from '@src/CONST'; import {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import {Beta, Login, PersonalDetails, Policy, PolicyTags, Report, ReportAction, Transaction} from '@src/types/onyx'; +import {Beta, Login, PersonalDetails, PersonalDetailsList, Policy, PolicyTags, Report, ReportAction, Transaction} from '@src/types/onyx'; import {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; import {ChangeLog, IOUMessage, OriginalMessageActionName, OriginalMessageCreated} from '@src/types/onyx/OriginalMessage'; import {Message, ReportActionBase, ReportActions} from '@src/types/onyx/ReportAction'; @@ -1396,7 +1396,7 @@ function getDisplayNameForParticipant(accountID?: number, shouldUseShortForm = f } function getDisplayNamesWithTooltips( - personalDetailsList: PersonalDetails[] | Record, + personalDetailsList: PersonalDetails[] | PersonalDetailsList, isMultipleParticipantReport: boolean, shouldFallbackToHidden = true, ): DisplayNameWithTooltips { diff --git a/src/libs/actions/PersonalDetails.ts b/src/libs/actions/PersonalDetails.ts index 29d18d543a11..02b5f70db285 100644 --- a/src/libs/actions/PersonalDetails.ts +++ b/src/libs/actions/PersonalDetails.ts @@ -9,7 +9,7 @@ import * as UserUtils from '@libs/UserUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import {DateOfBirthForm, PersonalDetails, PrivatePersonalDetails} from '@src/types/onyx'; +import {DateOfBirthForm, PersonalDetails, PersonalDetailsList, PrivatePersonalDetails} from '@src/types/onyx'; import {SelectedTimezone, Timezone} from '@src/types/onyx/PersonalDetails'; type FirstAndLastName = { @@ -27,7 +27,7 @@ Onyx.connect({ }, }); -let allPersonalDetails: OnyxEntry> = null; +let allPersonalDetails: OnyxEntry = null; Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, callback: (val) => (allPersonalDetails = val), From 2dfbe5da9b46001579cdfca33f8fb4f16274f368 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Thu, 30 Nov 2023 10:28:35 +0100 Subject: [PATCH 14/25] Update invalid format check --- src/libs/actions/DemoActions.ts | 4 ++-- src/libs/actions/OnyxUpdateManager.ts | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libs/actions/DemoActions.ts b/src/libs/actions/DemoActions.ts index b764d8268482..363b8434a2ce 100644 --- a/src/libs/actions/DemoActions.ts +++ b/src/libs/actions/DemoActions.ts @@ -9,8 +9,8 @@ import ROUTES from '@src/ROUTES'; let currentUserEmail: string; Onyx.connect({ key: ONYXKEYS.SESSION, - callback: (val) => { - currentUserEmail = val?.email ?? ''; + callback: (value) => { + currentUserEmail = value?.email ?? ''; }, }); diff --git a/src/libs/actions/OnyxUpdateManager.ts b/src/libs/actions/OnyxUpdateManager.ts index b61c8eeae268..ab0dea960b27 100644 --- a/src/libs/actions/OnyxUpdateManager.ts +++ b/src/libs/actions/OnyxUpdateManager.ts @@ -39,10 +39,9 @@ export default () => { // Since we used the same key that used to store another object, let's confirm that the current object is // following the new format before we proceed. If it isn't, then let's clear the object in Onyx. if ( - value === null || - !Object.hasOwn(value, 'type') || - (!(value.type === CONST.ONYX_UPDATE_TYPES.HTTPS && Object.hasOwn(value, 'request') && Object.hasOwn(value, 'response')) && - !(value.type === CONST.ONYX_UPDATE_TYPES.PUSHER && Object.hasOwn(value, 'updates'))) + !(typeof value === 'object' && !!value) || + !('type' in value) || + (!(value.type === CONST.ONYX_UPDATE_TYPES.HTTPS && value.request && value.response) && !(value.type === CONST.ONYX_UPDATE_TYPES.PUSHER && value.updates)) ) { console.debug('[OnyxUpdateManager] Invalid format found for updates, cleaning and unpausing the queue'); Onyx.set(ONYXKEYS.ONYX_UPDATES_FROM_SERVER, null); From 815f45cecdbd6ed5b5f5b09345338dd3ba769164 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Mon, 4 Dec 2023 16:15:40 +0100 Subject: [PATCH 15/25] Put onyx update data into separate variables --- src/libs/actions/Card.ts | 190 +++++++++++++++--------------- src/libs/actions/TeachersUnite.ts | 174 +++++++++++++-------------- 2 files changed, 186 insertions(+), 178 deletions(-) diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 6e1753fbd591..82b9cbc47e7c 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -1,4 +1,4 @@ -import Onyx from 'react-native-onyx'; +import Onyx, {OnyxUpdate} from 'react-native-onyx'; import * as API from '@libs/API'; import * as Localize from '@libs/Localize'; import CONST from '@src/CONST'; @@ -8,6 +8,36 @@ import type {Response} from '@src/types/onyx'; type Reason = 'damaged' | 'stolen'; function reportVirtualExpensifyCardFraud(cardID: number) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, + value: { + isLoading: true, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, + value: { + isLoading: false, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, + value: { + isLoading: false, + }, + }, + ]; + type ReportVirtualExpensifyCardFraudParams = { cardID: number; }; @@ -16,35 +46,7 @@ function reportVirtualExpensifyCardFraud(cardID: number) { cardID, }; - API.write('ReportVirtualExpensifyCardFraud', parameters, { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, - value: { - isLoading: true, - }, - }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, - value: { - isLoading: false, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, - value: { - isLoading: false, - }, - }, - ], - }); + API.write('ReportVirtualExpensifyCardFraud', parameters, {optimisticData, successData, failureData}); } /** @@ -53,6 +55,37 @@ function reportVirtualExpensifyCardFraud(cardID: number) { * @param reason - reason for replacement */ function requestReplacementExpensifyCard(cardId: number, reason: Reason) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM, + value: { + isLoading: true, + errors: null, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM, + value: { + isLoading: false, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM, + value: { + isLoading: false, + }, + }, + ]; + type RequestReplacementExpensifyCardParams = { cardId: number; reason: string; @@ -63,42 +96,50 @@ function requestReplacementExpensifyCard(cardId: number, reason: Reason) { reason, }; - API.write('RequestReplacementExpensifyCard', parameters, { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM, - value: { - isLoading: true, + API.write('RequestReplacementExpensifyCard', parameters, {optimisticData, successData, failureData}); +} + +/** + * Activates the physical Expensify card based on the last four digits of the card number + */ +function activatePhysicalExpensifyCard(cardLastFourDigits: string, cardID: number) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.CARD_LIST, + value: { + [cardID]: { errors: null, + isLoading: true, }, }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM, - value: { + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.CARD_LIST, + value: { + [cardID]: { isLoading: false, }, }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM, - value: { + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.CARD_LIST, + value: { + [cardID]: { isLoading: false, }, }, - ], - }); -} + }, + ]; -/** - * Activates the physical Expensify card based on the last four digits of the card number - */ -function activatePhysicalExpensifyCard(cardLastFourDigits: string, cardID: number) { type ActivatePhysicalExpensifyCardParams = { cardLastFourDigits: string; cardID: number; @@ -109,42 +150,7 @@ function activatePhysicalExpensifyCard(cardLastFourDigits: string, cardID: numbe cardID, }; - API.write('ActivatePhysicalExpensifyCard', parameters, { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.CARD_LIST, - value: { - [cardID]: { - errors: null, - isLoading: true, - }, - }, - }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.CARD_LIST, - value: { - [cardID]: { - isLoading: false, - }, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.CARD_LIST, - value: { - [cardID]: { - isLoading: false, - }, - }, - }, - ], - }); + API.write('ActivatePhysicalExpensifyCard', parameters, {optimisticData, successData, failureData}); } /** diff --git a/src/libs/actions/TeachersUnite.ts b/src/libs/actions/TeachersUnite.ts index f264d81f33d4..4768794c39f2 100644 --- a/src/libs/actions/TeachersUnite.ts +++ b/src/libs/actions/TeachersUnite.ts @@ -86,6 +86,93 @@ function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: reportActionID: expenseReportCreatedAction.reportActionID, }; + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + id: policyID, + isPolicyExpenseChatEnabled: true, + type: CONST.POLICY.TYPE.CORPORATE, + name: policyName, + role: CONST.POLICY.ROLE.USER, + owner: sessionEmail, + outputCurrency: allPersonalDetails?.[sessionAccountID]?.localCurrencyCode ?? CONST.CURRENCY.USD, + pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, + value: { + [sessionAccountID]: { + role: CONST.POLICY.ROLE.USER, + errors: {}, + }, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, + value: { + pendingFields: { + addWorkspaceRoom: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + }, + ...expenseChatData, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, + value: expenseReportActionData, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: {pendingAction: null}, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, + value: { + pendingFields: { + addWorkspaceRoom: null, + }, + pendingAction: null, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, + value: { + [Object.keys(expenseChatData)[0]]: { + pendingAction: null, + }, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, + value: null, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, + value: null, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, + value: null, + }, + ]; + type AddSchoolPrincipalParams = { firstName: string; lastName: string; @@ -100,92 +187,7 @@ function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: reportCreationData: JSON.stringify(reportCreationData), }; - API.write('AddSchoolPrincipal', parameters, { - optimisticData: [ - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - id: policyID, - isPolicyExpenseChatEnabled: true, - type: CONST.POLICY.TYPE.CORPORATE, - name: policyName, - role: CONST.POLICY.ROLE.USER, - owner: sessionEmail, - outputCurrency: allPersonalDetails?.[sessionAccountID]?.localCurrencyCode ?? CONST.CURRENCY.USD, - pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - }, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, - value: { - [sessionAccountID]: { - role: CONST.POLICY.ROLE.USER, - errors: {}, - }, - }, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, - value: { - pendingFields: { - addWorkspaceRoom: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - }, - ...expenseChatData, - }, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, - value: expenseReportActionData, - }, - ], - successData: [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: {pendingAction: null}, - }, - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, - value: { - pendingFields: { - addWorkspaceRoom: null, - }, - pendingAction: null, - }, - }, - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, - value: { - [Object.keys(expenseChatData)[0]]: { - pendingAction: null, - }, - }, - }, - ], - failureData: [ - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.POLICY_MEMBERS}${policyID}`, - value: null, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.REPORT}${expenseChatReportID}`, - value: null, - }, - { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseChatReportID}`, - value: null, - }, - ], - }); + API.write('AddSchoolPrincipal', parameters, {optimisticData, successData, failureData}); Navigation.dismissModal(expenseChatReportID); } From e51ee0bdbaaa43cecd74ebca8bd051fac4ac514d Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Wed, 6 Dec 2023 16:21:58 +0100 Subject: [PATCH 16/25] Fix TS issue --- src/types/onyx/DemoInfo.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/DemoInfo.ts b/src/types/onyx/DemoInfo.ts index dcd7efc44d8d..300846fb1a0e 100644 --- a/src/types/onyx/DemoInfo.ts +++ b/src/types/onyx/DemoInfo.ts @@ -1,5 +1,5 @@ type DemoInfo = { - money2020: { + money2020?: { /** If the beginning demo should be shown */ isBeginningDemo?: boolean; }; From 8e55cca513ff56b47031a8332a4cba849e46722f Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Fri, 8 Dec 2023 11:25:27 +0100 Subject: [PATCH 17/25] Move updates to global.d.ts file --- src/types/global.d.ts | 6 ++++++ src/types/modules/window.d.ts | 10 ---------- 2 files changed, 6 insertions(+), 10 deletions(-) delete mode 100644 src/types/modules/window.d.ts diff --git a/src/types/global.d.ts b/src/types/global.d.ts index a807b4328d50..f131eb5ef849 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -22,3 +22,9 @@ declare module '*.lottie' { } declare module 'react-native-device-info/jest/react-native-device-info-mock'; + +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +interface Window { + enableMemoryOnlyKeys: () => void; + disableMemoryOnlyKeys: () => void; +} diff --git a/src/types/modules/window.d.ts b/src/types/modules/window.d.ts deleted file mode 100644 index 1910c26768f5..000000000000 --- a/src/types/modules/window.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -declare global { - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions - interface Window { - enableMemoryOnlyKeys: () => void; - disableMemoryOnlyKeys: () => void; - } -} - -// We used the export {} line to mark this file as an external module -export {}; From a96cdbbec47dbaa72ba62dfa374f93b3699ebd5f Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Tue, 12 Dec 2023 09:49:53 +0100 Subject: [PATCH 18/25] Fix ts issues --- src/types/onyx/OriginalMessage.ts | 2 +- src/types/onyx/Report.ts | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index f30dcb750c14..f68cf06310c5 100644 --- a/src/types/onyx/OriginalMessage.ts +++ b/src/types/onyx/OriginalMessage.ts @@ -234,4 +234,4 @@ type OriginalMessage = | OriginalMessageMoved; export default OriginalMessage; -export type {ChronosOOOEvent, Decision, Reaction, ActionName, IOUMessage, Closed, OriginalMessageActionName, OriginalMessageCreated, ChangeLog, OriginalMessageIOU, OriginalMessageCreated}; +export type {ChronosOOOEvent, Decision, Reaction, ActionName, IOUMessage, Closed, OriginalMessageActionName, OriginalMessageCreated, ChangeLog, OriginalMessageIOU}; diff --git a/src/types/onyx/Report.ts b/src/types/onyx/Report.ts index 70665210547f..25c544f6f5c3 100644 --- a/src/types/onyx/Report.ts +++ b/src/types/onyx/Report.ts @@ -146,9 +146,6 @@ type Report = { /** Pending fields for the report */ pendingFields?: Record; - /** Pending action for the report */ - pendingAction?: OnyxCommon.PendingAction | null; - /** The ID of the preexisting report (it is possible that we optimistically created a Report for which a report already exists) */ preexistingReportID?: string; From 5641af0b4752f2a0e010ecad60d3409de25433f4 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Tue, 12 Dec 2023 09:54:56 +0100 Subject: [PATCH 19/25] Rename type --- src/libs/actions/Card.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 82b9cbc47e7c..e5ae09d5b28a 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -5,7 +5,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Response} from '@src/types/onyx'; -type Reason = 'damaged' | 'stolen'; +type ReplacementReason = 'damaged' | 'stolen'; function reportVirtualExpensifyCardFraud(cardID: number) { const optimisticData: OnyxUpdate[] = [ @@ -54,7 +54,7 @@ function reportVirtualExpensifyCardFraud(cardID: number) { * @param cardId - id of the card that is going to be replaced * @param reason - reason for replacement */ -function requestReplacementExpensifyCard(cardId: number, reason: Reason) { +function requestReplacementExpensifyCard(cardId: number, reason: ReplacementReason) { const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, From 84e2fd5212b2b717f7a124768e2417f9537d26c5 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Tue, 12 Dec 2023 17:29:16 +0100 Subject: [PATCH 20/25] Add comments to window methods --- src/types/global.d.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/types/global.d.ts b/src/types/global.d.ts index f131eb5ef849..1df100f67fe3 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -25,6 +25,9 @@ declare module 'react-native-device-info/jest/react-native-device-info-mock'; // eslint-disable-next-line @typescript-eslint/consistent-type-definitions interface Window { + // Method to enable memory only keys feature enableMemoryOnlyKeys: () => void; + + // Method to disable memory only keys feature disableMemoryOnlyKeys: () => void; } From 486ae09632799a90800731e056f709575db64890 Mon Sep 17 00:00:00 2001 From: Viktoryia Kliushun Date: Mon, 18 Dec 2023 13:27:00 +0100 Subject: [PATCH 21/25] Update comment --- src/types/global.d.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/types/global.d.ts b/src/types/global.d.ts index 1df100f67fe3..935c48942a68 100644 --- a/src/types/global.d.ts +++ b/src/types/global.d.ts @@ -23,11 +23,9 @@ declare module '*.lottie' { declare module 'react-native-device-info/jest/react-native-device-info-mock'; +// Global methods for Onyx key management for debugging purposes // eslint-disable-next-line @typescript-eslint/consistent-type-definitions interface Window { - // Method to enable memory only keys feature enableMemoryOnlyKeys: () => void; - - // Method to disable memory only keys feature disableMemoryOnlyKeys: () => void; } From d4ce66fd9f3e23696ebf66065396f7c419981d38 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Wed, 3 Jan 2024 09:14:45 +0100 Subject: [PATCH 22/25] TS fix after merging main --- src/types/onyx/Policy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 2a0990580ed0..9cc8464e2b28 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -75,7 +75,7 @@ type Policy = { autoReportingFrequency?: ValueOf; /** Whether the scheduled submit is enabled */ - isHarvestingEnabled: boolean; + isHarvestingEnabled?: boolean; /** The accountID of manager who the employee submits their expenses to on paid policies */ submitsTo?: number; From 8a99355d3fa2660f987e363d869d636df09fd5b3 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Wed, 3 Jan 2024 11:06:41 +0100 Subject: [PATCH 23/25] Re-run performance test From 4de7a5ed23c231251f1bee824c46bac35892efa1 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Thu, 4 Jan 2024 10:08:21 +0100 Subject: [PATCH 24/25] Fix lint errors --- src/libs/actions/Card.ts | 3 ++- src/libs/actions/MemoryOnlyKeys/MemoryOnlyKeys.ts | 2 +- src/libs/actions/TeachersUnite.ts | 3 ++- src/libs/actions/TransactionEdit.ts | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index e5ae09d5b28a..172b0ac73ca6 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -1,4 +1,5 @@ -import Onyx, {OnyxUpdate} from 'react-native-onyx'; +import Onyx from 'react-native-onyx'; +import type {OnyxUpdate} from 'react-native-onyx'; import * as API from '@libs/API'; import * as Localize from '@libs/Localize'; import CONST from '@src/CONST'; diff --git a/src/libs/actions/MemoryOnlyKeys/MemoryOnlyKeys.ts b/src/libs/actions/MemoryOnlyKeys/MemoryOnlyKeys.ts index 79d1ec0f82d9..3e8c613187b4 100644 --- a/src/libs/actions/MemoryOnlyKeys/MemoryOnlyKeys.ts +++ b/src/libs/actions/MemoryOnlyKeys/MemoryOnlyKeys.ts @@ -1,5 +1,5 @@ import Onyx from 'react-native-onyx'; -import {OnyxKey} from 'react-native-onyx/lib/types'; +import type {OnyxKey} from 'react-native-onyx/lib/types'; import Log from '@libs/Log'; import ONYXKEYS from '@src/ONYXKEYS'; diff --git a/src/libs/actions/TeachersUnite.ts b/src/libs/actions/TeachersUnite.ts index 4768794c39f2..066e55a4d365 100644 --- a/src/libs/actions/TeachersUnite.ts +++ b/src/libs/actions/TeachersUnite.ts @@ -1,4 +1,5 @@ -import Onyx, {OnyxEntry, OnyxUpdate} from 'react-native-onyx'; +import Onyx from 'react-native-onyx'; +import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import * as API from '@libs/API'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; diff --git a/src/libs/actions/TransactionEdit.ts b/src/libs/actions/TransactionEdit.ts index 3831ba8e437d..b1710aa72cbb 100644 --- a/src/libs/actions/TransactionEdit.ts +++ b/src/libs/actions/TransactionEdit.ts @@ -1,4 +1,5 @@ -import Onyx, {OnyxEntry} from 'react-native-onyx'; +import Onyx from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Transaction} from '@src/types/onyx'; From 733b3b127506686d76f13cddb784c26db3135b7e Mon Sep 17 00:00:00 2001 From: VickyStash Date: Tue, 9 Jan 2024 09:42:32 +0100 Subject: [PATCH 25/25] Updates from main branch --- src/libs/actions/TeachersUnite.ts | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/libs/actions/TeachersUnite.ts b/src/libs/actions/TeachersUnite.ts index 066e55a4d365..6aff31ad3836 100644 --- a/src/libs/actions/TeachersUnite.ts +++ b/src/libs/actions/TeachersUnite.ts @@ -34,44 +34,46 @@ Onyx.connect({ callback: (value) => (allPersonalDetails = value), }); -function referTeachersUniteVolunteer(partnerUserID: string, firstName: string, lastName: string) { - const optimisticPublicRoom = ReportUtils.buildOptimisticChatReport([], CONST.TEACHERS_UNITE.PUBLIC_ROOM_NAME, CONST.REPORT.CHAT_TYPE.POLICY_ROOM, CONST.TEACHERS_UNITE.POLICY_ID); +/** + * @param publicRoomReportID - This is the global reportID for the public room, we'll ignore the optimistic one + */ +function referTeachersUniteVolunteer(partnerUserID: string, firstName: string, lastName: string, policyID: string, publicRoomReportID: string) { + const optimisticPublicRoom = ReportUtils.buildOptimisticChatReport([], CONST.TEACHERS_UNITE.PUBLIC_ROOM_NAME, CONST.REPORT.CHAT_TYPE.POLICY_ROOM, policyID); const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.REPORT}${optimisticPublicRoom.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${publicRoomReportID}`, value: { ...optimisticPublicRoom, - reportID: optimisticPublicRoom.reportID, + reportID: publicRoomReportID, policyName: CONST.TEACHERS_UNITE.POLICY_NAME, }, }, ]; type ReferTeachersUniteVolunteerParams = { - publicRoomReportID: string; + reportID: string; firstName: string; lastName: string; partnerUserID: string; }; const parameters: ReferTeachersUniteVolunteerParams = { - publicRoomReportID: optimisticPublicRoom.reportID, + reportID: publicRoomReportID, firstName, lastName, partnerUserID, }; API.write('ReferTeachersUniteVolunteer', parameters, {optimisticData}); - Navigation.dismissModal(CONST.TEACHERS_UNITE.PUBLIC_ROOM_ID); + Navigation.dismissModal(publicRoomReportID); } /** * Optimistically creates a policyExpenseChat for the school principal and passes data to AddSchoolPrincipal */ -function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: string) { +function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: string, policyID: string) { const policyName = CONST.TEACHERS_UNITE.POLICY_NAME; - const policyID = CONST.TEACHERS_UNITE.POLICY_ID; const loggedInEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(sessionEmail); const reportCreationData: ReportCreationData = {}; @@ -178,6 +180,7 @@ function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: firstName: string; lastName: string; partnerUserID: string; + policyID: string; reportCreationData: string; }; @@ -185,6 +188,7 @@ function addSchoolPrincipal(firstName: string, partnerUserID: string, lastName: firstName, lastName, partnerUserID, + policyID, reportCreationData: JSON.stringify(reportCreationData), };