From 0935b43971df02139a83b3b602ca18da5ef4dcf0 Mon Sep 17 00:00:00 2001 From: Sebastian Szewczyk Date: Wed, 25 Oct 2023 12:31:19 +0200 Subject: [PATCH 1/2] Created migration to change ONYX resource personalDetailsList to ONYX.COLLECTION personalDetails - optimized BaseUserDetailsTooltip --- src/ONYXKEYS.ts | 2 + .../BaseUserDetailsTooltip.web.js | 17 +++--- src/libs/migrateOnyx.js | 3 +- .../migrations/PersonalDetailsToCollection.js | 54 +++++++++++++++++++ 4 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 src/libs/migrations/PersonalDetailsToCollection.js diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 11c2318672d8..b7c1962e1b41 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -268,6 +268,8 @@ const ONYXKEYS = { // Manual request tab selector SELECTED_TAB: 'selectedTab_', + PERSONAL_DETAILS: 'personalDetails_', + /** This is deprecated, but needed for a migration, so we still need to include it here so that it will be initialized in Onyx.init */ DEPRECATED_POLICY_MEMBER_LIST: 'policyMemberList_', }, diff --git a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.web.js b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.web.js index 871173d01b56..d6d8fbd7e20d 100644 --- a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.web.js +++ b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.web.js @@ -16,8 +16,7 @@ import {defaultProps, propTypes} from './userDetailsTooltipPropTypes'; function BaseUserDetailsTooltip(props) { const {translate} = useLocalize(); - - const userDetails = lodashGet(props.personalDetailsList, props.accountID, props.fallbackUserDetails); + const userDetails = props.personalDetails ?? props.fallbackUserDetails; let userDisplayName = userDetails.displayName ? userDetails.displayName.trim() : ''; let userLogin = (userDetails.login || '').trim() && !_.isEqual(userDetails.login, userDetails.displayName) ? Str.removeSMSDomain(userDetails.login) : ''; let userAvatar = userDetails.avatar; @@ -26,11 +25,8 @@ function BaseUserDetailsTooltip(props) { // We replace the actor's email, name, and avatar with the Copilot manually for now. This will be improved upon when // the Copilot feature is implemented. if (props.delegateAccountID) { - const delegateUserDetails = lodashGet(props.personalDetailsList, props.delegateAccountID, {}); - const delegateUserDisplayName = delegateUserDetails.displayName ? delegateUserDetails.displayName.trim() : ''; - userDisplayName = `${delegateUserDisplayName} (${translate('reportAction.asCopilot')} ${userDisplayName})`; - userLogin = delegateUserDetails.login; - userAvatar = delegateUserDetails.avatar; + userDisplayName = `${userDisplayName} (${translate('reportAction.asCopilot')} ${userDisplayName})`; + userLogin = userDetails.login; userAccountID = props.delegateAccountID; } @@ -79,7 +75,10 @@ BaseUserDetailsTooltip.defaultProps = defaultProps; BaseUserDetailsTooltip.displayName = 'BaseUserDetailsTooltip'; export default withOnyx({ - personalDetailsList: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, + personalDetails: { + key: ({delegateAccountID, accountID}) => { + const id = delegateAccountID ?? accountID; + return `${ONYXKEYS.COLLECTION.PERSONAL_DETAILS}${id}`; + }, }, })(BaseUserDetailsTooltip); diff --git a/src/libs/migrateOnyx.js b/src/libs/migrateOnyx.js index b65670819418..2e92811dd8b0 100644 --- a/src/libs/migrateOnyx.js +++ b/src/libs/migrateOnyx.js @@ -3,6 +3,7 @@ import Log from './Log'; import KeyReportActionsDraftByReportActionID from './migrations/KeyReportActionsDraftByReportActionID'; import PersonalDetailsByAccountID from './migrations/PersonalDetailsByAccountID'; import RenameReceiptFilename from './migrations/RenameReceiptFilename'; +import PersonalDetailsToCollection from './migrations/PersonalDetailsToCollection'; export default function () { const startTime = Date.now(); @@ -10,7 +11,7 @@ export default function () { return new Promise((resolve) => { // Add all migrations to an array so they are executed in order - const migrationPromises = [PersonalDetailsByAccountID, RenameReceiptFilename, KeyReportActionsDraftByReportActionID]; + const migrationPromises = [PersonalDetailsByAccountID, RenameReceiptFilename, KeyReportActionsDraftByReportActionID, PersonalDetailsToCollection]; // Reduce all promises down to a single promise. All promises run in a linear fashion, waiting for the // previous promise to finish before moving onto the next one. diff --git a/src/libs/migrations/PersonalDetailsToCollection.js b/src/libs/migrations/PersonalDetailsToCollection.js new file mode 100644 index 000000000000..b871d91594b7 --- /dev/null +++ b/src/libs/migrations/PersonalDetailsToCollection.js @@ -0,0 +1,54 @@ +import Onyx from 'react-native-onyx'; +import _ from 'lodash'; +import ONYXKEYS from '../../ONYXKEYS'; +import Log from '../Log'; + +// This migration changes personalDetailsList to a collection so that we can subscribe to changes on a single personalDetails +export default function PersonalDetailsToCollection() { + return new Promise((resolve) => { + // Check if migration has already been run + const outerConnectionID = Onyx.connect({ + key: ONYXKEYS.COLLECTION.PERSONAL_DETAILS, + waitForCollectionCallback: true, + callback: (personalDetailsCollection) => { + Onyx.disconnect(outerConnectionID); + if (personalDetailsCollection) { + Log.info('[Migrate Onyx] Skipping migration PersonalDetailsToCollection because it is already migrated'); + return resolve(); + } + + const connectionID = Onyx.connect({ + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + waitForCollectionCallback: true, + callback: (personalDetailsList) => { + Onyx.disconnect(connectionID); + const personalDetailsListLength = _.keys(personalDetailsList).length; + if (!personalDetailsList || personalDetailsListLength === 0) { + Log.info('[Migrate Onyx] Skipped migration PersonalDetailsToCollection because there are no personalDetailsList'); + return resolve(); + } + + Log.info('[Migrate Onyx] Running PersonalDetailsToCollection migration'); + const dataToSave = _.reduce( + personalDetailsList, + (result, personalDetails, key) => { + const personalDetailsKey = `${ONYXKEYS.COLLECTION.PERSONAL_DETAILS}${key}`; + // Param reassign justified to avoid creating a new object on each iteration + // eslint-disable-next-line no-param-reassign + result[personalDetailsKey] = personalDetails; + return result; + }, + {}, + ); + + // eslint-disable-next-line rulesdir/prefer-actions-set-data + Onyx.mergeCollection(ONYXKEYS.COLLECTION.PERSONAL_DETAILS, dataToSave).then(() => { + Log.info(`[Migrate Onyx] Ran migration PersonalDetailsToCollection - moved object with ${personalDetailsListLength} keys to a collection`); + resolve(); + }); + }, + }); + }, + }); + }); +} From 441d996645863bfe02fd5abaa8bec328b75a1028 Mon Sep 17 00:00:00 2001 From: Sebastian Szewczyk Date: Wed, 25 Oct 2023 13:54:22 +0200 Subject: [PATCH 2/2] Changed reduce to mapKeys in onyx migration --- src/libs/migrations/PersonalDetailsToCollection.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/libs/migrations/PersonalDetailsToCollection.js b/src/libs/migrations/PersonalDetailsToCollection.js index b871d91594b7..733f3602ef4b 100644 --- a/src/libs/migrations/PersonalDetailsToCollection.js +++ b/src/libs/migrations/PersonalDetailsToCollection.js @@ -29,16 +29,9 @@ export default function PersonalDetailsToCollection() { } Log.info('[Migrate Onyx] Running PersonalDetailsToCollection migration'); - const dataToSave = _.reduce( + const dataToSave = _.mapKeys( personalDetailsList, - (result, personalDetails, key) => { - const personalDetailsKey = `${ONYXKEYS.COLLECTION.PERSONAL_DETAILS}${key}`; - // Param reassign justified to avoid creating a new object on each iteration - // eslint-disable-next-line no-param-reassign - result[personalDetailsKey] = personalDetails; - return result; - }, - {}, + (_value, key) => `${ONYXKEYS.COLLECTION.PERSONAL_DETAILS}${key}` ); // eslint-disable-next-line rulesdir/prefer-actions-set-data