Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add private notes feature to newDot #25761

Merged
merged 33 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c506f34
added new route for private notes page
techievivek Aug 23, 2023
e15a765
added texts and logic for routing and api call
techievivek Aug 23, 2023
5b44c30
added new pages'
techievivek Aug 23, 2023
c981714
few minor fixes
techievivek Aug 24, 2023
6c53902
added read call
techievivek Aug 24, 2023
deb393a
tested private notes list page
techievivek Aug 26, 2023
3cfea9c
added private notes compose page
techievivek Aug 26, 2023
f9033dc
refactored to functional code and testing compose page
techievivek Aug 27, 2023
2e436e4
updated param name
techievivek Aug 27, 2023
0e6fd58
updated param name and fixed Your note case
techievivek Aug 28, 2023
d5d3bff
added private notes menu option on all the required pages
techievivek Aug 29, 2023
673a4fb
add offline feedback integration
techievivek Aug 29, 2023
c5dbac8
linter error
techievivek Aug 29, 2023
8183746
resolve conflicts
techievivek Aug 29, 2023
f879366
fix style
techievivek Aug 30, 2023
4bd3143
fix translation
techievivek Aug 30, 2023
d1c76a4
resolve conflicts
techievivek Aug 30, 2023
4c40d89
Fix lodashGet usasge
techievivek Aug 30, 2023
6cf1da8
use length and donot allow to edit if not current user note
techievivek Aug 30, 2023
11300b1
resovle conflicts
techievivek Sep 11, 2023
7b23352
added new page
techievivek Sep 12, 2023
87b9626
added logic for edit and render content separately
techievivek Sep 12, 2023
3835e9c
revert back podfile changes
techievivek Sep 12, 2023
90eaae9
testing and few fixes
techievivek Sep 12, 2023
15e9f77
some cleanups
techievivek Sep 12, 2023
3e65053
Merge branch 'main' into techievivek_private_notes_feature
techievivek Sep 12, 2023
0518f15
update Route code to ts
techievivek Sep 12, 2023
6c95fad
fix the horizontal padding for push to page
techievivek Sep 12, 2023
4e89344
donot show private notes option for thread and tasks
techievivek Sep 13, 2023
8b6ac1d
fix the navigation behaviour
techievivek Sep 15, 2023
3a07258
add auto-focus
techievivek Sep 15, 2023
9cfa85f
set the cursor at end for web, desktop and mweb
techievivek Sep 15, 2023
4b29f85
use focusAndUpdateMultilineInputRange for auto-focus
techievivek Sep 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1317,6 +1317,7 @@ const CONST = {
SETTINGS: 'settings',
LEAVE_ROOM: 'leaveRoom',
WELCOME_MESSAGE: 'welcomeMessage',
PRIVATE_NOTES: 'privateNotes',
},
EDIT_REQUEST_FIELD: {
AMOUNT: 'amount',
Expand Down
1 change: 1 addition & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ const ONYXKEYS = {
SETTINGS_STATUS_SET_FORM: 'settingsStatusSetForm',
SETTINGS_STATUS_CLEAR_AFTER_FORM: 'settingsStatusClearAfterForm',
SETTINGS_STATUS_SET_CLEAR_AFTER_FORM: 'settingsStatusSetClearAfterForm',
PRIVATE_NOTES_FORM: 'privateNotesForm',
I_KNOW_A_TEACHER_FORM: 'iKnowTeacherForm',
INTRO_SCHOOL_PRINCIPAL_FORM: 'introSchoolPrincipalForm',
},
Expand Down
8 changes: 8 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ export default {
GOOGLE_SIGN_IN: 'sign-in-with-google',
DESKTOP_SIGN_IN_REDIRECT: 'desktop-signin-redirect',

// Routes related to private notes added to the report
PRIVATE_NOTES_VIEW: 'r/:reportID/notes/:accountID',
getPrivateNotesViewRoute: (reportID: string, accountID: string | number) => `r/${reportID}/notes/${accountID}`,
PRIVATE_NOTES_LIST: 'r/:reportID/notes',
getPrivateNotesListRoute: (reportID: string) => `r/${reportID}/notes`,
PRIVATE_NOTES_EDIT: 'r/:reportID/notes/:accountID/edit',
getPrivateNotesEditRoute: (reportID: string, accountID: string | number) => `r/${reportID}/notes/${accountID}/edit`,

// This is a special validation URL that will take the user to /workspace/new after validation. This is used
// when linking users from e.com in order to share a session in this app.
ENABLE_PAYMENTS: 'enable-payments',
Expand Down
6 changes: 5 additions & 1 deletion src/components/MenuItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import variables from '../styles/variables';
import * as Session from '../libs/actions/Session';
import Hoverable from './Hoverable';
import useWindowDimensions from '../hooks/useWindowDimensions';
import RenderHTML from './RenderHTML';

const propTypes = menuItemPropTypes;

Expand Down Expand Up @@ -74,6 +75,7 @@ const defaultProps = {
title: '',
numberOfLinesTitle: 1,
shouldGreyOutWhenDisabled: true,
shouldRenderAsHTML: false,
};

const MenuItem = React.forwardRef((props, ref) => {
Expand Down Expand Up @@ -221,7 +223,9 @@ const MenuItem = React.forwardRef((props, ref) => {
</Text>
)}
<View style={[styles.flexRow, styles.alignItemsCenter]}>
{Boolean(props.title) && (
{Boolean(props.title) && Boolean(props.shouldRenderAsHTML) && <RenderHTML html={convertToLTR(props.title)} />}

{Boolean(props.title) && !props.shouldRenderAsHTML && (
<Text
style={titleTextStyle}
numberOfLines={props.numberOfLinesTitle || undefined}
Expand Down
3 changes: 3 additions & 0 deletions src/components/menuItemPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ const propTypes = {

/** Should we grey out the menu item when it is disabled? */
shouldGreyOutWhenDisabled: PropTypes.bool,

/** Should render the content in HTML format */
shouldRenderAsHTML: PropTypes.bool,
};

export default propTypes;
7 changes: 7 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,13 @@ export default {
passwordUpdated: 'Password updated!',
allSet: 'You’re all set. Keep your new password safe.',
},
privateNotes: {
title: 'Private notes',
personalNoteMessage: 'Keep notes about this chat here. You are the only person who can add, edit or view these notes.',
sharedNoteMessage: 'Keep notes about this chat here. Expensify employees and other users on the team.expensify.com domain can view these notes.',
notesUnavailable: 'No notes found for the user',
composerLabel: 'Notes',
},
addPayPalMePage: {
enterYourUsernameToGetPaidViaPayPal: 'Get paid back via PayPal.',
payPalMe: 'PayPal.me/',
Expand Down
7 changes: 7 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,13 @@ export default {
passwordUpdated: 'Contraseña actualizada!',
allSet: 'Todo está listo. Guarda tu contraseña en un lugar seguro.',
},
privateNotes: {
title: 'Notas privadas',
personalNoteMessage: 'Guarda notas sobre este chat aquí. Usted es la única persona que puede añadir, editar o ver estas notas.',
sharedNoteMessage: 'Guarda notas sobre este chat aquí. Los empleados de Expensify y otros usuarios del dominio team.expensify.com pueden ver estas notas.',
notesUnavailable: 'No se han encontrado notas para el usuario',
composerLabel: 'Notas',
},
addPayPalMePage: {
enterYourUsernameToGetPaidViaPayPal: 'Recibe pagos vía PayPal.',
payPalMe: 'PayPal.me/',
Expand Down
25 changes: 25 additions & 0 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.js
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,30 @@ const EditRequestStackNavigator = createModalStackNavigator([
},
]);

const PrivateNotesModalStackNavigator = createModalStackNavigator([
{
getComponent: () => {
const PrivateNotesPage = require('../../../pages/PrivateNotes/PrivateNotesViewPage').default;
return PrivateNotesPage;
},
name: 'PrivateNotes_View',
},
{
getComponent: () => {
const PrivateNotesListPage = require('../../../pages/PrivateNotes/PrivateNotesListPage').default;
return PrivateNotesListPage;
},
name: 'PrivateNotes_List',
},
{
getComponent: () => {
const PrivateNotesEditPage = require('../../../pages/PrivateNotes/PrivateNotesEditPage').default;
return PrivateNotesEditPage;
},
name: 'PrivateNotes_Edit',
},
]);

const SignInModalStackNavigator = createModalStackNavigator([
{
getComponent: () => {
Expand Down Expand Up @@ -794,6 +818,7 @@ export {
WalletStatementStackNavigator,
FlagCommentStackNavigator,
EditRequestStackNavigator,
PrivateNotesModalStackNavigator,
NewTeachersUniteNavigator,
SignInModalStackNavigator,
};
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ function RightModalNavigator(props) {
name="SignIn"
component={ModalStackNavigators.SignInModalStackNavigator}
/>
<Stack.Screen
name="Private_Notes"
component={ModalStackNavigators.PrivateNotesModalStackNavigator}
/>
</Stack.Navigator>
</View>
</NoDropZone>
Expand Down
7 changes: 7 additions & 0 deletions src/libs/Navigation/linkingConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@ export default {
},
},
},
Private_Notes: {
screens: {
PrivateNotes_View: ROUTES.PRIVATE_NOTES_VIEW,
PrivateNotes_List: ROUTES.PRIVATE_NOTES_LIST,
PrivateNotes_Edit: ROUTES.PRIVATE_NOTES_EDIT,
},
},
Report_Details: {
screens: {
Report_Details_Root: ROUTES.REPORT_WITH_ID_DETAILS,
Expand Down
31 changes: 31 additions & 0 deletions src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3462,6 +3462,36 @@ function getTaskAssigneeChatOnyxData(accountID, assigneeEmail, assigneeAccountID
};
}

/**
* Redirect the user to either privateNotesLisPage if the report has multiple notes otherwise, it redirects the user to their own private note on the report
*
* @param {Object} report
* @param {Number} accountID
*/
function navigateToPrivateNotesPage(report, accountID) {
if (_.isEmpty(report)) {
return;
}

const privateNotes = lodashGet(report, 'privateNotes', {});

// Redirect the user to privateNotesList page in case there are multiple notes and accountID is not set
// We will also redirect to the privateNotesList page if privateNotes is empty since we load the private notes on that page.
if ((_.isEmpty(accountID) && _.keys(privateNotes).length > 1) || _.isEmpty(privateNotes)) {
Navigation.navigate(ROUTES.getPrivateNotesListRoute(report.reportID));
return;
}

// If the privateNotes is empty, then we will redirect the user to the privateNotesEdit page
if (_.isEmpty(lodashGet(privateNotes[_.isEmpty(accountID) ? currentUserAccountID : accountID], 'note', ''))) {
Navigation.navigate(ROUTES.getPrivateNotesEditRoute(report.reportID, _.isEmpty(accountID) ? currentUserAccountID : accountID));
return;
}

// Default the accountID to current user's accountID in case it is empty
Navigation.navigate(ROUTES.getPrivateNotesViewRoute(report.reportID, _.isEmpty(accountID) ? currentUserAccountID : accountID));
}

/**
* Get the last 3 transactions with receipts of an IOU report that will be displayed on the report preview
*
Expand Down Expand Up @@ -3621,6 +3651,7 @@ export {
buildTransactionThread,
areAllRequestsBeingSmartScanned,
getReportPreviewDisplayTransactions,
navigateToPrivateNotesPage,
getTransactionsWithReceipts,
hasMissingSmartscanFields,
};
134 changes: 134 additions & 0 deletions src/libs/actions/Report.js
Original file line number Diff line number Diff line change
Expand Up @@ -1933,6 +1933,136 @@ function flagComment(reportID, reportAction, severity) {
API.write('FlagComment', parameters, {optimisticData, successData, failureData});
}

/**
* Updates a given user's private notes on a report
*
* @param {String} reportID
* @param {Number} accountID
* @param {String} note
*/
const updatePrivateNotes = (reportID, accountID, note) => {
const optimisticData = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
privateNotes: {
[accountID]: {
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
errors: null,
note,
},
},
},
},
];

const successData = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
privateNotes: {
[accountID]: {
pendingAction: null,
errors: null,
},
},
},
},
];

const failureData = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
privateNotes: {
[accountID]: {
errors: ErrorUtils.getMicroSecondOnyxError("Private notes couldn't be saved"),
},
},
},
},
];

API.write(
'UpdateReportPrivateNote',
{
reportID,
privateNotes: note,
},
{optimisticData, successData, failureData},
);
};

/**
* Fetches all the private notes for a given report
*
* @param {String} reportID
*/
function getReportPrivateNote(reportID) {
if (_.isEmpty(reportID)) {
return;
}
API.read(
'GetReportPrivateNote',
{
reportID,
},
{
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
isLoadingPrivateNotes: true,
},
},
],
successData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
isLoadingPrivateNotes: false,
},
},
],
failureData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`,
value: {
isLoadingPrivateNotes: false,
},
},
],
},
);
}

/**
* Checks if there are any errors in the private notes for a given report
*
* @param {Object} report
* @returns {Boolean} Returns true if there are errors in any of the private notes on the report
*/
function hasErrorInPrivateNotes(report) {
const privateNotes = lodashGet(report, 'privateNotes', {});
return _.some(privateNotes, (privateNote) => !_.isEmpty(privateNote.errors));
}

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

export {
addComment,
addAttachment,
Expand Down Expand Up @@ -1980,4 +2110,8 @@ export {
setLastOpenedPublicRoom,
flagComment,
openLastOpenedPublicRoom,
updatePrivateNotes,
getReportPrivateNote,
clearPrivateNotesError,
hasErrorInPrivateNotes,
};
Loading
Loading