Skip to content

Commit

Permalink
move privateNotes from report to reportMetadata
Browse files Browse the repository at this point in the history
  • Loading branch information
TMisiukiewicz committed Nov 18, 2024
1 parent 63c8dd2 commit 12df426
Show file tree
Hide file tree
Showing 16 changed files with 135 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import tryResolveUrlFromApiRoot from '@libs/tryResolveUrlFromApiRoot';
import CONST from '@src/CONST';
import type {ReportAction, ReportActions} from '@src/types/onyx';
import type {Note} from '@src/types/onyx/Report';
import type {Note} from '@src/types/onyx/ReportMetadata';

/**
* Constructs the initial component state from report actions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function AttachmentCarousel({report, source, onNavigate, setDownloadButtonVisibi
const pagerRef = useRef<AttachmentCarouselPagerHandle>(null);
const [parentReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`, {canEvict: false});
const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, {canEvict: false});
const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report.reportID}`, {canEvict: false});
const [page, setPage] = useState<number>();
const [attachments, setAttachments] = useState<Attachment[]>([]);
const {shouldShowArrows, setShouldShowArrows, autoHideArrows, cancelAutoHideArrows} = useCarouselArrows();
Expand All @@ -34,7 +35,7 @@ function AttachmentCarousel({report, source, onNavigate, setDownloadButtonVisibi
const parentReportAction = report.parentReportActionID && parentReportActions ? parentReportActions[report.parentReportActionID] : undefined;
let newAttachments: Attachment[] = [];
if (type === CONST.ATTACHMENT_TYPE.NOTE && accountID) {
newAttachments = extractAttachments(CONST.ATTACHMENT_TYPE.NOTE, {privateNotes: report.privateNotes, accountID});
newAttachments = extractAttachments(CONST.ATTACHMENT_TYPE.NOTE, {privateNotes: reportMetadata?.privateNotes, accountID});
} else {
newAttachments = extractAttachments(CONST.ATTACHMENT_TYPE.REPORT, {parentReportAction, reportActions});
}
Expand Down
5 changes: 3 additions & 2 deletions src/components/Attachments/AttachmentCarousel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ function AttachmentCarousel({report, source, onNavigate, setDownloadButtonVisibi
const pagerRef = useRef<GestureType>(null);
const [parentReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`, {canEvict: false});
const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.reportID}`, {canEvict: false});
const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report.reportID}`, {canEvict: false});
const canUseTouchScreen = DeviceCapabilities.canUseTouchScreen();

const modalStyles = styles.centeredModalStyles(shouldUseNarrowLayout, true);
Expand All @@ -76,7 +77,7 @@ function AttachmentCarousel({report, source, onNavigate, setDownloadButtonVisibi
const parentReportAction = report.parentReportActionID && parentReportActions ? parentReportActions[report.parentReportActionID] : undefined;
let newAttachments: Attachment[] = [];
if (type === CONST.ATTACHMENT_TYPE.NOTE && accountID) {
newAttachments = extractAttachments(CONST.ATTACHMENT_TYPE.NOTE, {privateNotes: report.privateNotes, accountID});
newAttachments = extractAttachments(CONST.ATTACHMENT_TYPE.NOTE, {privateNotes: reportMetadata?.privateNotes, accountID});
} else {
newAttachments = extractAttachments(CONST.ATTACHMENT_TYPE.REPORT, {parentReportAction, reportActions: reportActions ?? undefined});
}
Expand Down Expand Up @@ -117,7 +118,7 @@ function AttachmentCarousel({report, source, onNavigate, setDownloadButtonVisibi
onNavigate(attachment);
}
}
}, [report.privateNotes, reportActions, parentReportActions, compareImage, report.parentReportActionID, attachments, setDownloadButtonVisibility, onNavigate, accountID, type]);
}, [reportMetadata?.privateNotes, reportActions, parentReportActions, compareImage, report.parentReportActionID, attachments, setDownloadButtonVisibility, onNavigate, accountID, type]);

// Scroll position is affected when window width is resized, so we readjust it on width changes
useEffect(() => {
Expand Down
9 changes: 0 additions & 9 deletions src/libs/DebugUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,15 +427,6 @@ function validateReportDraftProperty(key: keyof Report, value: string) {
if (REPORT_REQUIRED_PROPERTIES.includes(key) && value === 'undefined') {
throw SyntaxError('debug.missingValue');
}
if (key === 'privateNotes') {
return validateObject(
value,
{
note: 'string',
},
'number',
);
}
if (key === 'permissions') {
return validateArray(value, CONST.REPORT.PERMISSIONS);
}
Expand Down
8 changes: 4 additions & 4 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4218,11 +4218,11 @@ function navigateBackAfterDeleteTransaction(backRoute: Route | undefined, isFrom
/**
* Go back to the previous page from the edit private page of a given report
*/
function goBackFromPrivateNotes(report: OnyxEntry<Report>, accountID?: number, backTo?: string) {
function goBackFromPrivateNotes(report: OnyxEntry<Report>, reportMetadata: OnyxEntry<ReportMetadata>, accountID?: number, backTo?: string) {
if (isEmpty(report) || !accountID) {
return;
}
const currentUserPrivateNote = report.privateNotes?.[accountID]?.note ?? '';
const currentUserPrivateNote = reportMetadata?.privateNotes?.[accountID]?.note ?? '';
if (isEmpty(currentUserPrivateNote)) {
const participantAccountIDs = getParticipantsAccountIDsForDisplay(report);

Expand Down Expand Up @@ -7711,11 +7711,11 @@ function shouldAutoFocusOnKeyPress(event: KeyboardEvent): boolean {
/**
* Navigates to the appropriate screen based on the presence of a private note for the current user.
*/
function navigateToPrivateNotes(report: OnyxEntry<Report>, session: OnyxEntry<Session>, backTo?: string) {
function navigateToPrivateNotes(report: OnyxEntry<Report>, reportMetadata: OnyxEntry<ReportMetadata>, session: OnyxEntry<Session>, backTo?: string) {
if (isEmpty(report) || isEmpty(session) || !session.accountID) {
return;
}
const currentUserPrivateNote = report.privateNotes?.[session.accountID]?.note ?? '';
const currentUserPrivateNote = reportMetadata?.privateNotes?.[session.accountID]?.note ?? '';
if (isEmpty(currentUserPrivateNote)) {
Navigation.navigate(ROUTES.PRIVATE_NOTES_EDIT.getRoute(report.reportID, session.accountID, backTo));
return;
Expand Down
13 changes: 7 additions & 6 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ import type {
RecentlyUsedReportFields,
ReportAction,
ReportActionReactions,
ReportMetadata,
ReportUserIsTyping,
} from '@src/types/onyx';
import type {Decision} from '@src/types/onyx/OriginalMessage';
Expand Down Expand Up @@ -3380,7 +3381,7 @@ const updatePrivateNotes = (reportID: string, accountID: number, note: string) =
const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`,
value: {
privateNotes: {
[accountID]: {
Expand All @@ -3396,7 +3397,7 @@ const updatePrivateNotes = (reportID: string, accountID: number, note: string) =
const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`,
value: {
privateNotes: {
[accountID]: {
Expand All @@ -3411,7 +3412,7 @@ const updatePrivateNotes = (reportID: string, accountID: number, note: string) =
const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`,
value: {
privateNotes: {
[accountID]: {
Expand Down Expand Up @@ -3954,14 +3955,14 @@ function openRoomMembersPage(reportID: string) {
*
* @returns Returns true if there are errors in any of the private notes on the report
*/
function hasErrorInPrivateNotes(report: OnyxEntry<Report>): boolean {
const privateNotes = report?.privateNotes ?? {};
function hasErrorInPrivateNotes(reportMetadata: OnyxEntry<ReportMetadata>): boolean {
const privateNotes = reportMetadata?.privateNotes ?? {};
return Object.values(privateNotes).some((privateNote) => !isEmpty(privateNote.errors));
}

/** Clears all errors associated with a given private note */
function clearPrivateNotesError(reportID: string, accountID: number) {
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {privateNotes: {[accountID]: {errors: null}}});
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, {privateNotes: {[accountID]: {errors: null}}});
}

function getDraftPrivateNote(reportID: string): string {
Expand Down
2 changes: 2 additions & 0 deletions src/libs/migrateOnyx.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Log from './Log';
import KeyReportActionsDraftByReportActionID from './migrations/KeyReportActionsDraftByReportActionID';
import NVPMigration from './migrations/NVPMigration';
import PrivateNotesMigration from './migrations/PrivateNotesMigration';
import PronounsMigration from './migrations/PronounsMigration';
import RemoveEmptyReportActionsDrafts from './migrations/RemoveEmptyReportActionsDrafts';
import RenameCardIsVirtual from './migrations/RenameCardIsVirtual';
Expand All @@ -21,6 +22,7 @@ export default function () {
RemoveEmptyReportActionsDrafts,
NVPMigration,
PronounsMigration,
PrivateNotesMigration,
];

// Reduce all promises down to a single promise. All promises run in a linear fashion, waiting for the
Expand Down
74 changes: 74 additions & 0 deletions src/libs/migrations/PrivateNotesMigration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import type {NullishDeep, OnyxInputValue} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import Log from '@libs/Log';
import ONYXKEYS from '@src/ONYXKEYS';
import type * as OnyxTypes from '@src/types/onyx';
import type {Note} from '@src/types/onyx/ReportMetadata';
import {isEmptyObject} from '@src/types/utils/EmptyObject';

type ReportMetadataKey = `${typeof ONYXKEYS.COLLECTION.REPORT_METADATA}${string}`;
type ReportKey = `${typeof ONYXKEYS.COLLECTION.REPORT}${string}`;

/**
* This migration moves private notes from the report object to reportMetadata.
* Before: report.privateNotes
* After: reportMetadata.privateNotes
*/
export default function (): Promise<void> {
return new Promise<void>((resolve) => {
const connection = Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (allReports) => {
Onyx.disconnect(connection);

if (!allReports) {
Log.info('[Migrate Onyx] Skipped migration PrivateNotesMigration because there were no reports');
return resolve();
}

// @ts-expect-error this migration moves privateNotes from Report to ReportMetadata so it is expected to not exist in Report type anymore
const reportsWithPrivateNotes = Object.entries(allReports).filter(([, report]) => report?.privateNotes);

if (reportsWithPrivateNotes.length === 0) {
Log.info('[Migrate Onyx] Skipped migration PrivateNotesMigration because there were no reports with private notes');
return resolve();
}

const newReportMetadata: Record<ReportMetadataKey, OnyxInputValue<OnyxTypes.ReportMetadata>> = {};
const reportsToUpdate: Record<`${typeof ONYXKEYS.COLLECTION.REPORT}${string}`, NullishDeep<OnyxTypes.Report>> = {};

reportsWithPrivateNotes.forEach(([reportOnyxKey, report]) => {
// @ts-expect-error this migration moves privateNotes from Report to ReportMetadata so it is expected to not exist in Report type anymore
if (!report?.reportID || !report.privateNotes) {
return;
}

// Move private notes to reportMetadata
const metadataKey: ReportMetadataKey = `${ONYXKEYS.COLLECTION.REPORT_METADATA}${report.reportID}`;
newReportMetadata[metadataKey] = {
// @ts-expect-error this migration moves privateNotes from Report to ReportMetadata so it is expected to not exist in Report type anymore
privateNotes: report?.privateNotes as Note,
};
// @ts-expect-error this migration moves privateNotes from Report to ReportMetadata so it is expected to not exist in Report type anymore
reportsToUpdate[reportOnyxKey as ReportKey] = {privateNotes: undefined};
});

if (isEmptyObject(newReportMetadata)) {
Log.info('[Migrate Onyx] Skipped migration PrivateNotesMigration because there were no private notes to migrate');
return resolve();
}

Log.info(`[Migrate Onyx] Moving private notes to reportMetadata for ${Object.keys(newReportMetadata).length} reports`);

// eslint-disable-next-line rulesdir/prefer-actions-set-data
const promises = [Onyx.multiSet(newReportMetadata), Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, reportsToUpdate)];

Promise.all(promises).then(() => {
Log.info('[Migrate Onyx] Successfully migrated private notes to reportMetadata');
resolve();
});
},
});
});
}
14 changes: 7 additions & 7 deletions src/pages/PrivateNotes/PrivateNotesEditPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,23 @@ import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
import INPUT_IDS from '@src/types/form/PrivateNotesForm';
import type {Report} from '@src/types/onyx';
import type {Note} from '@src/types/onyx/Report';
import type {Note} from '@src/types/onyx/ReportMetadata';

type PrivateNotesEditPageProps = WithReportAndPrivateNotesOrNotFoundProps &
StackScreenProps<PrivateNotesNavigatorParamList, typeof SCREENS.PRIVATE_NOTES.EDIT> & {
/** The report currently being looked at */
report: Report;
};

function PrivateNotesEditPage({route, report, accountID}: PrivateNotesEditPageProps) {
function PrivateNotesEditPage({route, report, accountID, reportMetadata}: PrivateNotesEditPageProps) {
const backTo = route.params.backTo;
const styles = useThemeStyles();
const {translate} = useLocalize();
const [personalDetailsList] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);

// We need to edit the note in markdown format, but display it in HTML format
const [privateNote, setPrivateNote] = useState(
() => ReportActions.getDraftPrivateNote(report.reportID).trim() || Parser.htmlToMarkdown(report?.privateNotes?.[Number(route.params.accountID)]?.note ?? '').trim(),
() => ReportActions.getDraftPrivateNote(report.reportID).trim() || Parser.htmlToMarkdown(reportMetadata?.privateNotes?.[Number(route.params.accountID)]?.note ?? '').trim(),
);

/**
Expand Down Expand Up @@ -85,7 +85,7 @@ function PrivateNotesEditPage({route, report, accountID}: PrivateNotesEditPagePr
);

const savePrivateNote = () => {
const originalNote = report?.privateNotes?.[Number(route.params.accountID)]?.note ?? '';
const originalNote = reportMetadata?.privateNotes?.[Number(route.params.accountID)]?.note ?? '';
let editedNote = '';
if (privateNote.trim() !== originalNote.trim()) {
editedNote = ReportActions.handleUserDeletedLinksInHtml(privateNote.trim(), Parser.htmlToMarkdown(originalNote).trim());
Expand All @@ -96,7 +96,7 @@ function PrivateNotesEditPage({route, report, accountID}: PrivateNotesEditPagePr
debouncedSavePrivateNote('');

Keyboard.dismiss();
if (!Object.values<Note>({...report.privateNotes, [route.params.accountID]: {note: editedNote}}).some((item) => item.note)) {
if (!Object.values<Note>({...reportMetadata?.privateNotes, [route.params.accountID]: {note: editedNote}}).some((item) => item.note)) {
ReportUtils.navigateToDetailsPage(report, backTo);
} else {
Navigation.goBack(ROUTES.PRIVATE_NOTES_LIST.getRoute(report.reportID, backTo));
Expand All @@ -111,7 +111,7 @@ function PrivateNotesEditPage({route, report, accountID}: PrivateNotesEditPagePr
>
<HeaderWithBackButton
title={translate('privateNotes.title')}
onBackButtonPress={() => ReportUtils.goBackFromPrivateNotes(report, accountID, backTo)}
onBackButtonPress={() => ReportUtils.goBackFromPrivateNotes(report, reportMetadata, accountID, backTo)}
shouldShowBackButton
onCloseButtonPress={() => Navigation.dismissModal()}
/>
Expand All @@ -131,7 +131,7 @@ function PrivateNotesEditPage({route, report, accountID}: PrivateNotesEditPagePr
</Text>
<OfflineWithFeedback
errors={{
...(report?.privateNotes?.[Number(route.params.accountID)]?.errors ?? ''),
...(reportMetadata?.privateNotes?.[Number(route.params.accountID)]?.errors ?? ''),
}}
onClose={() => ReportActions.clearPrivateNotesError(report.reportID, Number(route.params.accountID))}
style={[styles.mb3]}
Expand Down
9 changes: 5 additions & 4 deletions src/pages/PrivateNotes/PrivateNotesListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ function PrivateNotesListPage({report, accountID: sessionAccountID}: PrivateNote
const route = useRoute<RouteProp<PrivateNotesNavigatorParamList, typeof SCREENS.PRIVATE_NOTES.LIST>>();
const backTo = route.params.backTo;
const [personalDetailsList] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID ?? -1}`);
const styles = useThemeStyles();
const {translate} = useLocalize();
const getAttachmentValue = useCallback((item: NoteListItem) => ({reportID: item.reportID, accountID: Number(item.accountID), type: CONST.ATTACHMENT_TYPE.NOTE}), []);
Expand Down Expand Up @@ -70,9 +71,9 @@ function PrivateNotesListPage({report, accountID: sessionAccountID}: PrivateNote
* Returns a list of private notes on the given chat report
*/
const privateNotes = useMemo(() => {
const privateNoteBrickRoadIndicator = (accountID: number) => (report.privateNotes?.[accountID].errors ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined);
return Object.keys(report.privateNotes ?? {}).map((accountID: string) => {
const privateNote = report.privateNotes?.[Number(accountID)];
const privateNoteBrickRoadIndicator = (accountID: number) => (reportMetadata?.privateNotes?.[accountID].errors ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined);
return Object.keys(reportMetadata?.privateNotes ?? {}).map((accountID: string) => {
const privateNote = reportMetadata?.privateNotes?.[Number(accountID)];
return {
reportID: report.reportID,
accountID,
Expand All @@ -83,7 +84,7 @@ function PrivateNotesListPage({report, accountID: sessionAccountID}: PrivateNote
disabled: Number(sessionAccountID) !== Number(accountID),
};
});
}, [report, personalDetailsList, sessionAccountID, translate, backTo]);
}, [report, reportMetadata, personalDetailsList, sessionAccountID, translate, backTo]);

return (
<ScreenWrapper
Expand Down
Loading

0 comments on commit 12df426

Please sign in to comment.