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 a Settings page to configure people in workspace #3681

Merged
merged 62 commits into from
Jun 30, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
69868e7
Add a new route
mountiny Jun 18, 2021
95a834d
Update languages
mountiny Jun 20, 2021
8a9643f
Revert merge changes
mountiny Jun 21, 2021
943464e
Align the buttons to left
mountiny Jun 21, 2021
5563a86
Add button danger style option
mountiny Jun 21, 2021
9f323e7
Update Button component to have danger option
mountiny Jun 21, 2021
211baa1
Add the list of employees in the workspace
mountiny Jun 21, 2021
e866365
Update admin badge style
mountiny Jun 23, 2021
d23fc1a
Revert: Refactor the pages so the settings is a standalone page
mountiny Jun 23, 2021
4cc5dc7
Update the features after refactor
mountiny Jun 23, 2021
2ae6261
Remove Rajat's components
mountiny Jun 23, 2021
db6d80f
Use simply FlatList and add disabled danger button colour
mountiny Jun 23, 2021
064f181
Add Policy member removal functionality
mountiny Jun 23, 2021
08d4ef2
Merge main into the branch to get up-to-date changes
mountiny Jun 24, 2021
9d05861
Fix two merge conflict errors
mountiny Jun 24, 2021
826fcfd
Fix issue with undefined key
mountiny Jun 24, 2021
3f04d48
Fixing JS linting errors
mountiny Jun 24, 2021
a8703e2
Fix js lint
mountiny Jun 24, 2021
cc28cbe
Fix js lint 2
mountiny Jun 24, 2021
6f7e4b9
Update the texts
mountiny Jun 24, 2021
4032415
Remove the admin email from list of members to remove to prevent erro…
mountiny Jun 24, 2021
83f43a4
Add responsive styles and make remove button in modal red
mountiny Jun 25, 2021
f9a0f61
Capitalize modal title
mountiny Jun 25, 2021
5333835
Remove debugging line
mountiny Jun 25, 2021
7d3a123
Improving the styles on smaller screen
mountiny Jun 25, 2021
ebd3533
Update the responsive styles and remove the tagline
mountiny Jun 25, 2021
f289841
Add translation keys to es.js
mountiny Jun 26, 2021
e7f7422
Make the remove request parameters required
mountiny Jun 26, 2021
3c19e68
Update one comment
mountiny Jun 26, 2021
86461f2
Merge main into vit-settingsPageToConfigureWorkspace
mountiny Jun 28, 2021
00a6450
Revert debugging changes and update remove request call error handling
mountiny Jun 28, 2021
79039c0
Remove unnecessary funtion bindings
mountiny Jun 29, 2021
7bcddf3
Fix JSDoc formatting
mountiny Jun 29, 2021
0f153ca
Refactor the toggleUser function
mountiny Jun 29, 2021
8aced19
Remove fragment and use underscore contains
mountiny Jun 29, 2021
3d9c712
Remove unnecessary props for FlatList
mountiny Jun 29, 2021
baa2dfd
Update responsive design breakpoint to work well in the modal
mountiny Jun 29, 2021
2c30a9d
Fix js linting errors
mountiny Jun 29, 2021
905c06d
Fix grammar mistake
mountiny Jun 29, 2021
9f28a4e
Refactor user toggling logic
mountiny Jun 29, 2021
181d7ad
Change the Confirm modal button props
mountiny Jun 30, 2021
6bfa5ff
Remove placeholder ModalStackNavigator
mountiny Jun 30, 2021
4cb15d1
Update Remove members error handling and remove unnecessary translations
mountiny Jun 30, 2021
6c1f968
Refactor data manipulationin WorkspacePeoplePage
mountiny Jun 30, 2021
099457e
Merge main into this branch
mountiny Jun 30, 2021
1a8b58c
Remove the pressable area on fullscreen modal
mountiny Jun 30, 2021
42ed986
Fix JSDoc typo and render FlatList unconditionally
mountiny Jun 30, 2021
a5d731e
Add spanish translations
mountiny Jun 30, 2021
180501f
Update finalized Spanish translations
mountiny Jun 30, 2021
8590f20
Fix route. Add back button press
marcaaron Jun 30, 2021
8695e19
remove isModal
marcaaron Jun 30, 2021
c6aaa2f
Fix up click away handler issues
marcaaron Jun 30, 2021
7920b12
use white background
marcaaron Jun 30, 2021
b8b98ad
get route params from whichever route we can. they might be out of or…
marcaaron Jun 30, 2021
b70b419
clean up styles some more
marcaaron Jun 30, 2021
78615f7
remove buttonRow
marcaaron Jun 30, 2021
91e0d45
clean up badge style
marcaaron Jun 30, 2021
1ec0ea9
remove sms domain
marcaaron Jun 30, 2021
181625e
Make entire row touchable
marcaaron Jun 30, 2021
ce20252
fix bug discovered on android due to null policy
marcaaron Jun 30, 2021
10d70ae
Update border width to be 1px
mountiny Jun 30, 2021
3eb5818
Update Spanish translation
mountiny Jun 30, 2021
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
2 changes: 1 addition & 1 deletion src/pages/home/sidebar/optionPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const optionPropTypes = PropTypes.shape({
participantsList: PropTypes.arrayOf(participantPropTypes),

// The array URLs of the person's avatar
icon: PropTypes.arrayOf(PropTypes.string),
icons: PropTypes.arrayOf(PropTypes.string),
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice 👍🏾


// Descriptive text to be displayed besides selection element
descriptiveText: PropTypes.string,
Expand Down
2 changes: 1 addition & 1 deletion src/pages/settings/InitialPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ const InitialSettingsPage = ({

// Add free policies (workspaces) to the list of menu items
const menuItems = _.chain(policies)
.filter(policy => policy.type === CONST.POLICY.TYPE.FREE && policy.role === CONST.POLICY.ROLE.ADMIN)
.filter(policy => policy && policy.type === CONST.POLICY.TYPE.FREE && policy.role === CONST.POLICY.ROLE.ADMIN)
.map(policy => ({
title: policy.name,
icon: Building,
Expand Down
191 changes: 64 additions & 127 deletions src/pages/workspace/WorkspacePeoplePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import React from 'react';
import _ from 'underscore';
import lodashGet from 'lodash/get';
import {
View, FlatList, ScrollView,
View, FlatList, TouchableOpacity,
} from 'react-native';
import PropTypes from 'prop-types';
import {withOnyx} from 'react-native-onyx';
import Str from 'expensify-common/lib/str';
import styles from '../../styles/styles';
import ONYXKEYS from '../../ONYXKEYS';
import HeaderWithCloseButton from '../../components/HeaderWithCloseButton';
Expand All @@ -14,14 +15,14 @@ import ScreenWrapper from '../../components/ScreenWrapper';
import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
import compose from '../../libs/compose';
import {removeMembers} from '../../libs/actions/Policy';
import Avatar from '../../components/Avatar';
import Button from '../../components/Button';
import Checkbox from '../../components/Checkbox';
import Text from '../../components/Text';
import ROUTES from '../../ROUTES';
import ConfirmModal from '../../components/ConfirmModal';
import personalDetailsPropType from '../personalDetailsPropType';
import withWindowDimensions, {windowDimensionsPropTypes} from '../../components/withWindowDimensions';
import OptionRow from '../home/sidebar/OptionRow';

const propTypes = {
...withLocalizePropTypes,
Expand Down Expand Up @@ -63,7 +64,6 @@ class WorkspacePeoplePage extends React.Component {
};

this.renderItem = this.renderItem.bind(this);
this.renderHeader = this.renderHeader.bind(this);
this.addUser = this.addUser.bind(this);
this.removeUser = this.removeUser.bind(this);
this.askForConfirmationToRemove = this.askForConfirmationToRemove.bind(this);
Expand Down Expand Up @@ -166,120 +166,46 @@ class WorkspacePeoplePage extends React.Component {
item,
}) {
return (
<View style={[styles.peopleRow]}>
<View style={[styles.peopleRowCell, styles.peopleCheckbox]}>
<TouchableOpacity
style={[styles.peopleRow]}
onPress={() => this.toggleUser(item.login)}
activeOpacity={0.7}
>
<View style={[styles.peopleRowCell]}>
<Checkbox
isChecked={_.contains(this.state.selectedEmployees, item.login)}
onPress={() => this.toggleUser(item.login)}
/>
</View>
{
this.props.windowWidth < 1100 ? (
<View style={[styles.peopleRowCell, styles.mobileAvatarWithName]}>
<View style={[styles.avatarWithName]}>
<Avatar
imageStyles={[styles.mr2, styles.mobileAvatarWithName]}
source={item.avatar}
/>
<View
style={[
styles.dFlex,
styles.flexColumn,
styles.justifyContentCenter,
styles.overflowHidden,
styles.mobilePeopleName,
]}
>
<Text style={[styles.textStrong, styles.peopleMobileAssigneeText]}>
{item.displayName}
</Text>
<Text
style={[
styles.textLabel,
styles.colorMuted,
styles.peopleMobileAssigneeText,
]}
>
{item.login}
</Text>
</View>
</View>
</View>
) : (
<>
<View style={[styles.peopleRowCell, styles.flex4]}>
<View style={[styles.avatarWithName]}>
<Avatar
imageStyles={[styles.mr2]}
source={item.avatar}
/>
<Text style={[styles.textStrong]}>
{item.displayName}
</Text>
</View>
</View>
<View style={[styles.peopleRowCell, styles.flex4]}>
<Text style={[styles.textLabel, styles.colorMuted]}>
{item.login}
</Text>
</View>
</>
)
}
<View
style={[
styles.peopleRowCell,
styles.peopleBadgesContainer,
this.props.windowWidth < 1100 ? styles.peopleBadgesMobile : styles.peopleBadgesContainerDesktop,
]}
>
{
this.props.session.email === item.login && (
<View>
<View style={[styles.peopleBadge]}>
<Text style={[styles.peopleBadgeText]}>
Admin
</Text>
</View>
</View>
)
}
</View>
</View>
);
}

renderHeader() {
const policyEmployeeList = lodashGet(this.props, 'policy.employeeList', []);
return (
<View style={[styles.peopleRow, styles.peopleHeaderRow]}>
<View style={[styles.peopleRowCell, styles.peopleCheckbox]}>
<Checkbox
isChecked={this.state.selectedEmployees.length === policyEmployeeList.length}
onPress={() => this.toggleAllUsers()}
<View style={styles.flex1}>
<OptionRow
forceTextUnreadStyle
disableRowInteractivity
option={{
text: Str.removeSMSDomain(item.displayName),
alternateText: Str.removeSMSDomain(item.login),
participantsList: [item],
icons: [item.avatar],
keyForList: item.login,
}}
/>
</View>
<View style={[styles.peopleRowCell, styles.flex4]}>
<Text style={[styles.textStrong]}>
{this.props.translate('workspace.people.assignee')}
</Text>
</View>
{
this.props.windowWidth >= 1100 && (
<View style={[styles.peopleRowCell, styles.flex4]}>
<Text style={[styles.textStrong]}>
{this.props.translate('common.email')}
{this.props.session.email === item.login && (
<View style={styles.peopleRowCell}>
<View style={[styles.badge, styles.peopleBadge]}>
<Text style={[styles.peopleBadgeText]}>
Admin
</Text>
</View>
)
}
<View style={[styles.peopleRowCell, styles.flex1]} />
</View>
</View>
)}
</TouchableOpacity>
);
}

render() {
const data = _.chain(lodashGet(this.props, 'policy.employeeList', []))
const policyEmployeeList = lodashGet(this.props, 'policy.employeeList', []);
const data = _.chain(policyEmployeeList)
.map(email => this.props.personalDetails[email])
.filter()
.value();
Expand All @@ -301,31 +227,42 @@ class WorkspacePeoplePage extends React.Component {
confirmText={this.props.translate('common.remove')}
cancelText={this.props.translate('common.cancel')}
/>
<ScrollView style={[styles.settingsPageBackground]} bounces={false}>
<View style={styles.pageWrapper}>
<View style={styles.buttonRow}>
<Button
success
text={this.props.translate('common.invite')}
onPress={() => this.inviteUser()}
/>
<Button
danger
style={[styles.ml2]}
isDisabled={this.state.selectedEmployees.length === 0}
text={this.props.translate('common.remove')}
onPress={this.askForConfirmationToRemove}
/>
</View>
<View style={[styles.w100, styles.mt4]}>
<FlatList
ListHeaderComponent={this.renderHeader()}
renderItem={this.renderItem}
data={data}
/>
<View style={styles.pageWrapper}>
<View style={[styles.w100, styles.flexRow]}>
<Button
success
text={this.props.translate('common.invite')}
onPress={() => this.inviteUser()}
/>
<Button
danger
style={[styles.ml2]}
isDisabled={this.state.selectedEmployees.length === 0}
text={this.props.translate('common.remove')}
onPress={this.askForConfirmationToRemove}
/>
</View>
<View style={[styles.w100, styles.mt4]}>
<View style={[styles.peopleRow]}>
<View style={[styles.peopleRowCell]}>
<Checkbox
isChecked={this.state.selectedEmployees.length === policyEmployeeList.length}
onPress={() => this.toggleAllUsers()}
/>
</View>
<View style={[styles.peopleRowCell, styles.flex1]}>
<Text style={[styles.textStrong, styles.textUppercase, styles.ph5]}>
{this.props.translate('workspace.people.assignee')}
</Text>
</View>
</View>
<FlatList
renderItem={this.renderItem}
data={data}
keyExtractor={item => item.login}
/>
</View>
</ScrollView>
</View>
</ScreenWrapper>
);
}
Expand Down
5 changes: 3 additions & 2 deletions src/pages/workspace/WorkspaceSidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,9 @@ export default compose(
withOnyx({
policy: {
key: (props) => {
const state = props.navigation.getState();
const policyID = lodashGet(state, ['routes', 0, 'params', 'policyID']);
const routes = lodashGet(props.navigation.getState(), 'routes', []);
const routeWithPolicyIDParam = _.find(routes, route => route.params && route.params.policyID);
const policyID = lodashGet(routeWithPolicyIDParam, ['params', 'policyID']);
return `${ONYXKEYS.COLLECTION.POLICY}${policyID}`;
},
},
Expand Down
75 changes: 3 additions & 72 deletions src/styles/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ const styles = {
borderRadius: variables.componentBorderRadiusNormal,
height: variables.componentSizeNormal,
justifyContent: 'center',
paddingHorizontal: 12,
...spacing.ph3,
},

buttonText: {
Expand Down Expand Up @@ -1716,83 +1716,22 @@ const styles = {
minHeight: 150,
},

textFull: {
width: '100%',
},

buttonRow: {
display: 'flex',
width: '100%',
justifyContent: 'flex-start',
flexDirection: 'row',
},

peopleRow: {
display: 'flex',
width: '100%',
flexDirection: 'row',
justifyContent: 'space-between',
borderBottomWidth: 2,
borderColor: themeColors.border,
paddingVertical: 16,
},

peopleHeaderRow: {
textTransform: 'uppercase',
fontWeight: '700',
...spacing.pv2,
},

peopleRowCell: {
display: 'flex',
flexDirection: 'column',
padding: spacing.p4,
alignItems: 'flex-start',
justifyContent: 'center',
},

peopleCheckbox: {
minWidth: 36,
},

avatarWithName: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
width: '100%',
},

mobileAvatarWithName: {
flex: '0 1 auto',
},

mobilePeopleName: {
flex: '0 1 auto',
overflow: 'hidden',
},

peopleBadgesContainer: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-end',
},

peopleBadgesContainerDesktop: {
flex: '1 1 0',
},

peopleBadgesMobile: {
flex: '1 1 auto',
paddingLeft: 20,
},

peopleBadge: {
backgroundColor: themeColors.icon,
borderRadius: 14,
height: variables.iconSizeNormal,
flexDirection: 'row',
paddingHorizontal: 12,
alignItems: 'center',
...spacing.ph3,
},

peopleBadgeText: {
Expand All @@ -1801,14 +1740,6 @@ const styles = {
lineHeight: 16,
...whiteSpace.noWrap,
},

peopleMobileAssigneeText: {
paddingVertical: 2,
textOverflow: 'ellipsis',
whiteSpace: 'noWrap',
overflow: 'hidden',
flexGrow: '0 1 auto',
},
};

const baseCodeTagStyles = {
Expand Down
Loading