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

Report Details and Settings for User Created Policy Rooms #7028

Merged
merged 68 commits into from
Jan 12, 2022
Merged
Show file tree
Hide file tree
Changes from 67 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
43379fd
Add skeleton for Policy Rooms Details Page items
Jan 4, 2022
1be77c7
Add report settings route
Jan 4, 2022
06b5357
Add copy for leaving a chat room
Jan 4, 2022
82918f0
Use SignOut icon for leaving the room
Jan 5, 2022
df53b7c
Use placeholders for functionality that will come in later issues
Jan 5, 2022
4311da5
Allow us to properly see when there are 0 other members in a policy room
Jan 5, 2022
a842885
Add routes for report settings
Jan 5, 2022
8581def
Merge branch 'main' of github.com:Expensify/App into amal-policy-room…
Jan 5, 2022
d5eac97
Rename SignOut to Exit to be more universally used
Jan 5, 2022
a20785a
Fix alphabetical ordering
Jan 5, 2022
1b7ef56
Remove typo extra line
Jan 5, 2022
bddeb9e
Create skeleton SettingsPage
Jan 5, 2022
e3962db
Fix imports
Jan 5, 2022
9f10475
Fix spacing
Jan 5, 2022
f556532
Add onyx props and definitions
Jan 5, 2022
75e9fc4
Add Report Settings to modal stack
Jan 5, 2022
5ed8498
lint fixes for space styling and imports
Jan 5, 2022
bcb5e99
Fix blank menu items for default rooms
Jan 6, 2022
0459d03
Move Notification Preferences to Report Settings Page for UCPRs
Jan 6, 2022
7dee263
Add route propTypes to new component
Jan 6, 2022
f5815da
Create Notification Preferences component
Jan 6, 2022
775cc93
Use NotificationPreferences component and remove redundant code
Jan 6, 2022
7933796
Fix style and use correct imports
Jan 6, 2022
84da563
Add title into component
Jan 6, 2022
4db2921
Add description in notification preferences and reorganize translation
Jan 6, 2022
f10df0c
Fix weird margins for SettingsPage
Jan 6, 2022
bbd1d4d
Add spanish translation for notification preferences
Jan 6, 2022
7faba99
Merge branch 'main' of github.com:Expensify/App into amal-policy-room…
Jan 6, 2022
aae68ad
Remove unneeded Notification Preferences
Jan 7, 2022
747b705
Move NotificationPrefences to Settings and set up view
Jan 7, 2022
440a8a7
Disable rename for defaultRooms and archived rooms
Jan 7, 2022
f5edbbd
Add in report name and prevent renaming for default and archived rooms
Jan 7, 2022
d127b85
Rework into class component to use room name changing
Jan 7, 2022
c591f0d
Rework room name renaming to work like in NewRoomPage
Jan 7, 2022
82912cc
Use substring instead of deprecated substr
Jan 7, 2022
d55a47c
Include policy details to correctly display Workspace Name
Jan 7, 2022
86ccf4e
Style fix
Jan 7, 2022
61bca31
Add visibility information
Jan 7, 2022
066ff33
Add visibility to simplifiedReportData so it can be used
Jan 7, 2022
9e1aabd
Add rest of visibility information to Settings component
Jan 7, 2022
776050a
Fix report visibility description and style
Jan 7, 2022
cde74ff
Lint style fix
Jan 7, 2022
bfe3e1d
Allow Buttons to have custom styles on the OpacityView to configure h…
Jan 7, 2022
a11bd00
Add styles for inner part of button in ReportSettingsPage
Jan 7, 2022
6454645
Merge branch 'main' of github.com:Expensify/App into amal-policy-room…
Jan 7, 2022
877c733
Add context to how report visibility is being used
Jan 7, 2022
b07962e
Move propTypes to appropriate location
Jan 7, 2022
f3b0b26
Remove unused values
Jan 7, 2022
39c2a5e
Remove unsued View and reorganize styles
Jan 7, 2022
5e10c08
Add RoomNameInput component to consolidate room naming component
Jan 7, 2022
763af4a
Use new RoomNameInput component
Jan 7, 2022
fb11343
Make RoomNameInput functional with the ReportSettingsPage
Jan 7, 2022
04fc0cc
lint fixes/ cleaning up unused code
Jan 7, 2022
a8b8fe3
Make RoomNameInput work with WorkspaceNewRoomPage
Jan 8, 2022
18552c1
lint import
Jan 8, 2022
a9e062d
Make this work with actual policies and room names
Jan 8, 2022
6ae4a2b
Better error checking with bubbling up to the top
Jan 8, 2022
2946b30
Fix error checking cases
Jan 8, 2022
1554534
Fix error when nothing is changed in RoomSettingsPage
Jan 8, 2022
61af6c8
Clean up Onyx Props and comments
Jan 8, 2022
ea6832c
Use styles to capitalize instead to better futureproof
Jan 11, 2022
698ae3f
Merge branch 'main' of github.com:Expensify/App into amal-policy-room…
Jan 11, 2022
ede4c29
Remove unneeded extra newlines
Jan 11, 2022
2130aff
Use ternary to simplify error logic
Jan 11, 2022
730cb46
Keep originalRoomName out of state to avoid react/no-access-state-in-…
Jan 11, 2022
9a03719
Use return early style instead and clear up comments
Jan 11, 2022
4545fb7
Merge branch 'main' of github.com:Expensify/App into amal-policy-room…
Jan 11, 2022
6ddfd43
Rename buttonStyles to innerStyles
Jan 11, 2022
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
File renamed without changes
2 changes: 2 additions & 0 deletions src/ROUTES.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ export default {
) => `r/${reportID}/participants/details?login=${encodeURIComponent(login)}`,
REPORT_WITH_ID_DETAILS: 'r/:reportID/details',
getReportDetailsRoute: reportID => `r/${reportID}/details`,
REPORT_SETTINGS: 'r/:reportID/settings',
getReportSettingsRoute: reportID => `r/${reportID}/settings`,
LOGIN_WITH_SHORT_LIVED_TOKEN: 'transition',
VALIDATE_LOGIN: 'v/:accountID/:validateCode',
GET_ASSISTANCE: 'get-assistance/:taskID',
Expand Down
7 changes: 6 additions & 1 deletion src/components/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,15 @@ const propTypes = {
/** Call the onPress function when Enter key is pressed */
pressOnEnter: PropTypes.bool,

/** Additional styles to add after local styles */
/** Additional styles to add after local styles. Applied to Pressable portion of button */
style: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.object),
PropTypes.object,
]),

/** Additional button styles. Specific to the OpacityView of button */
buttonStyles: PropTypes.arrayOf(PropTypes.object),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could name this something like innerStyles, but I figured buttonStyles makes more sense here. I realized that there's no way to put in a custom height/padding for buttons because the styles prop actually only affects the container/Pressable portion of the button, not the inner view.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems odd to me because we pass button.styles directly to the OpacityView as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do pass the styles.button but not the styles itself. That only happens now with this line.

The additionalStyles are getting added to the Pressable part only.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think containerStyles and innerStyles makes a bit more sense here, but maybe I'm not entirely understanding your reasoning.

The Pressable is the container, and the OpacityView is the inner component. If I was looking at this component for the first time I think this makes more sense than additionalStyles and buttonStyles, since the whole component is called Button.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes a lot of sense to me. Container styles really is the most accurate way to describe that for button. I think I wanted to avoid renaming the existing "styles" prop, but it isn't too difficult to see where <Button is referenced and just change the name there.

/** Additional text styles */
textStyles: PropTypes.arrayOf(PropTypes.object),

Expand Down Expand Up @@ -82,6 +85,7 @@ const defaultProps = {
onPressOut: () => {},
pressOnEnter: false,
style: [],
buttonStyles: [],
textStyles: [],
success: false,
danger: false,
Expand Down Expand Up @@ -195,6 +199,7 @@ class Button extends Component {
(this.props.danger && hovered) ? styles.buttonDangerHovered : undefined,
this.props.shouldRemoveRightBorderRadius ? styles.noRightBorderRadius : undefined,
this.props.shouldRemoveLeftBorderRadius ? styles.noLeftBorderRadius : undefined,
...this.props.buttonStyles,
]}
>
{this.renderContent()}
Expand Down
4 changes: 2 additions & 2 deletions src/components/Icon/Expensicons.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import DownArrow from '../../../assets/images/down.svg';
import Download from '../../../assets/images/download.svg';
import Emoji from '../../../assets/images/emoji.svg';
import Exclamation from '../../../assets/images/exclamation.svg';
import Exit from '../../../assets/images/exit.svg';
import Eye from '../../../assets/images/eye.svg';
import EyeDisabled from '../../../assets/images/eye-disabled.svg';
import ExpensifyCard from '../../../assets/images/expensifycard.svg';
Expand Down Expand Up @@ -58,7 +59,6 @@ import Receipt from '../../../assets/images/receipt.svg';
import ReceiptSearch from '../../../assets/images/receipt-search.svg';
import RotateLeft from '../../../assets/images/rotate-left.svg';
import Send from '../../../assets/images/send.svg';
import SignOut from '../../../assets/images/sign-out.svg';
import Sync from '../../../assets/images/sync.svg';
import Transfer from '../../../assets/images/transfer.svg';
import ThreeDots from '../../../assets/images/three-dots.svg';
Expand Down Expand Up @@ -95,6 +95,7 @@ export {
Download,
Emoji,
Exclamation,
Exit,
Eye,
EyeDisabled,
ExpensifyCard,
Expand Down Expand Up @@ -131,7 +132,6 @@ export {
ReceiptSearch,
RotateLeft,
Send,
SignOut,
Sync,
Transfer,
ThreeDots,
Expand Down
151 changes: 151 additions & 0 deletions src/components/RoomNameInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import _ from 'underscore';
import {withOnyx} from 'react-native-onyx';
import CONST from '../CONST';
import ONYXKEYS from '../ONYXKEYS';
import styles from '../styles/styles';
import compose from '../libs/compose';
import withLocalize, {withLocalizePropTypes} from './withLocalize';
import withFullPolicy, {fullPolicyDefaultProps, fullPolicyPropTypes} from '../pages/workspace/withFullPolicy';

import TextInputWithPrefix from './TextInputWithPrefix';

const propTypes = {
/** Callback to execute when the text input is modified correctly */
onChangeText: PropTypes.func,

/** Callback to execute when an error gets found/cleared/modified */
onChangeError: PropTypes.func,

/** Initial room name to show in input field. This should include the '#' already prefixed to the name */
initialValue: PropTypes.string,

/** Whether we should show the input as disabled */
disabled: PropTypes.bool,

/** ID of policy whose room names we should be checking for duplicates */
policyID: PropTypes.string,

...withLocalizePropTypes,
...fullPolicyPropTypes,

/* Onyx Props */

/** All reports shared with the user */
reports: PropTypes.shape({
/** The report name */
reportName: PropTypes.string,

/** ID of the report */
reportID: PropTypes.number,
}).isRequired,

/** The policies which the user has access to and which the report could be tied to */
policies: PropTypes.shape({
/** The policy name */
name: PropTypes.string,

/** ID of the policy */
id: PropTypes.string,
}).isRequired,
};

const defaultProps = {
onChangeText: () => {},
onChangeError: () => {},
initialValue: '',
disabled: false,
policyID: '',
...fullPolicyDefaultProps,
};

class RoomNameInput extends Component {
constructor(props) {
super(props);
this.state = {
roomName: props.initialValue,
error: '',
};

this.originalRoomName = props.initialValue;

this.checkAndModifyRoomName = this.checkAndModifyRoomName.bind(this);
}

componentDidUpdate(prevProps, prevState) {
// As we are modifying the text input, we'll bubble up any changes/errors so the parent component can see it
if (prevState.roomName !== this.state.roomName) {
this.props.onChangeText(this.state.roomName);
}
if (prevState.error !== this.state.error) {
this.props.onChangeError(this.state.error);
}
}

/**
* Modifies the room name to follow our conventions:
* - Max length 80 characters
* - Cannot not include space or special characters, and we automatically apply an underscore for spaces
* - Must be lowercase
* Also checks to see if this room name already exists, and displays an error message if so.
* @param {String} roomName
*
*/
checkAndModifyRoomName(roomName) {
const modifiedRoomNameWithoutHash = roomName.substring(1)
.replace(/ /g, '_')
.replace(/[^a-zA-Z\d_]/g, '')
.substring(0, CONST.REPORT.MAX_ROOM_NAME_LENGTH)
.toLowerCase();
const finalRoomName = `#${modifiedRoomNameWithoutHash}`;

const isExistingRoomName = _.some(
_.values(this.props.reports),
report => report && report.policyID === this.props.policyID && report.reportName === finalRoomName,
);

// We error if the room name already exists. We don't care if it matches the original name provided in this
// component because then we are not changing the room's name.
const error = isExistingRoomName && finalRoomName !== this.originalRoomName
? this.props.translate('newRoomPage.roomAlreadyExists')
: '';

this.setState({
roomName: finalRoomName,
error,
});
}

render() {
return (
<TextInputWithPrefix
disabled={this.props.disabled}
label={this.props.translate('newRoomPage.roomName')}
prefixCharacter="#"
placeholder={this.props.translate('newRoomPage.social')}
containerStyles={[styles.mb5]}
onChangeText={roomName => this.checkAndModifyRoomName(roomName)}
value={this.state.roomName.substring(1)}
errorText={this.state.error}
autoCapitalize="none"
/>
);
}
}

RoomNameInput.propTypes = propTypes;
RoomNameInput.defaultProps = defaultProps;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra newline

export default compose(
withLocalize,
withFullPolicy,
withOnyx({
reports: {
key: ONYXKEYS.COLLECTION.REPORT,
},
policies: {
key: ONYXKEYS.COLLECTION.POLICY,
},
}),
)(RoomNameInput);
6 changes: 4 additions & 2 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export default {
transferBalance: 'Transfer Balance',
cantFindAddress: 'Can\'t find your address? ',
enterManually: 'Enter it manually',
leaveRoom: 'Leave room',
},
attachmentPicker: {
cameraPermissionRequired: 'Camera permission required',
Expand Down Expand Up @@ -213,8 +214,9 @@ export default {
other: 'Unexpected error, please try again later',
},
},
reportDetailsPage: {
notificationPreferencesDescription: 'Notify me about new messages',
notificationPreferences: {
description: 'How often should we notify you when there are new messages to catch up on in this room?',
label: 'Notify me about new messages',
always: 'Always',
daily: 'Daily',
mute: 'Mute',
Expand Down
6 changes: 4 additions & 2 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export default {
transferBalance: 'Transferencia de saldo',
cantFindAddress: '¿No encuentras tu dirección? ',
enterManually: 'Ingresar manualmente',
leaveRoom: 'Salir de la sala de chat',
},
attachmentPicker: {
cameraPermissionRequired: 'Se necesita permiso para usar la cámara',
Expand Down Expand Up @@ -213,8 +214,9 @@ export default {
other: 'Error inesperado, por favor inténtalo más tarde',
},
},
reportDetailsPage: {
notificationPreferencesDescription: 'Avisar sobre nuevos mensajes',
notificationPreferences: {
description: '¿Con qué frecuencia podemos notificarle si haya nuevos mensajes en esta sala de chat?',
label: 'Avisar sobre nuevos mensajes',
always: 'Siempre',
daily: 'Cada día',
mute: 'Nunca',
Expand Down
6 changes: 6 additions & 0 deletions src/libs/Navigation/AppNavigator/AuthScreens.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,12 @@ class AuthScreens extends React.Component {
component={ModalStackNavigators.ReportDetailsModalStackNavigator}
listeners={modalScreenListeners}
/>
<RootStack.Screen
name="Report_Settings"
options={modalScreenOptions}
component={ModalStackNavigators.ReportSettingsModalStackNavigator}
listeners={modalScreenListeners}
/>
<RootStack.Screen
name="Participants"
options={modalScreenOptions}
Expand Down
7 changes: 7 additions & 0 deletions src/libs/Navigation/AppNavigator/ModalStackNavigators.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import CONST from '../../../CONST';
import AddDebitCardPage from '../../../pages/settings/Payments/AddDebitCardPage';
import TransferBalancePage from '../../../pages/settings/Payments/TransferBalancePage';
import ChooseTransferAccountPage from '../../../pages/settings/Payments/ChooseTransferAccountPage';
import ReportSettingsPage from '../../../pages/ReportSettingsPage';

const defaultSubRouteOptions = {
cardStyle: styles.navigationScreenCardStyle,
Expand Down Expand Up @@ -141,6 +142,11 @@ const ReportDetailsModalStackNavigator = createModalStackNavigator([{
name: 'Report_Details_Root',
}]);

const ReportSettingsModalStackNavigator = createModalStackNavigator([{
Component: ReportSettingsPage,
name: 'Report_Settings_Root',
}]);

const ReportParticipantsModalStackNavigator = createModalStackNavigator([
{
Component: ReportParticipantsPage,
Expand Down Expand Up @@ -310,6 +316,7 @@ export {
IOUDetailsModalStackNavigator,
DetailsModalStackNavigator,
ReportDetailsModalStackNavigator,
ReportSettingsModalStackNavigator,
ReportParticipantsModalStackNavigator,
SearchModalStackNavigator,
NewGroupModalStackNavigator,
Expand Down
5 changes: 5 additions & 0 deletions src/libs/Navigation/linkingConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ export default {
Report_Details_Root: ROUTES.REPORT_WITH_ID_DETAILS,
},
},
Report_Settings: {
screens: {
Report_Settings_Root: ROUTES.REPORT_SETTINGS,
},
},
NewGroup: {
screens: {
NewGroup_Root: ROUTES.NEW_GROUP,
Expand Down
4 changes: 4 additions & 0 deletions src/libs/actions/Report.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ function getSimplifiedReportObject(report) {
// Used for archived rooms, will store the policy name that the room used to belong to.
const oldPolicyName = lodashGet(report, ['reportNameValuePairs', 'oldPolicyName'], '');

// Used for User Created Policy Rooms, will denote how access to a chat room is given among workspace members
const visibility = lodashGet(report, ['reportNameValuePairs', 'visibility']);

return {
reportID: report.reportID,
reportName,
Expand All @@ -217,6 +220,7 @@ function getSimplifiedReportObject(report) {
stateNum: report.state,
statusNum: report.status,
oldPolicyName,
visibility,
};
}

Expand Down
Loading