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 all 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
6 changes: 4 additions & 2 deletions src/ROUTES.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,13 @@ export default {
VALIDATE_LOGIN_WITH_VALIDATE_CODE: 'v/:accountID/:validateCode',
ENABLE_PAYMENTS: 'enable-payments',
WORKSPACE_NEW: 'workspace/new',
WORKSPACE_CARD: ':policyID/card',
WORKSPACE: 'workspace',
WORKSPACE_CARD: ':policyID/card',
WORKSPACE_PEOPLE: ':policyID/people',
getWorkspaceCardRoute: policyID => `workspace/${policyID}/card`,
WORKSPACE_INVITE: 'workspace/:policyID/invite',
getWorkspacePeopleRoute: policyID => `workspace/${policyID}/people`,
getWorkspaceInviteRoute: policyID => `workspace/${policyID}/invite`,
WORKSPACE_INVITE: 'workspace/:policyID/invite',
REQUEST_CALL: 'request-call',

/**
Expand Down
10 changes: 9 additions & 1 deletion src/components/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ const propTypes = {
/** Whether we should use the success theme color */
success: PropTypes.bool,

/** Whether we should use the danger theme color */
danger: PropTypes.bool,

/** Optional content component to replace all inner contents of button */
ContentComponent: PropTypes.func,

Expand All @@ -55,6 +58,7 @@ const defaultProps = {
style: [],
textStyles: [],
success: false,
danger: false,
ContentComponent: undefined,
shouldRemoveRightBorderRadius: false,
shouldRemoveLeftBorderRadius: false,
Expand All @@ -79,6 +83,7 @@ const Button = (props) => {
styles.buttonText,
props.large && styles.buttonLargeText,
props.success && styles.buttonSuccessText,
props.danger && styles.buttonDangerText,
...props.textStyles,
]}
>
Expand All @@ -102,8 +107,11 @@ const Button = (props) => {
styles.button,
props.large ? styles.buttonLarge : undefined,
props.success ? styles.buttonSuccess : undefined,
props.isDisabled ? styles.buttonDisable : undefined,
props.danger ? styles.buttonDanger : undefined,
(props.isDisabled && props.danger) ? styles.buttonDangerDisabled : undefined,
(props.isDisabled && !props.danger) ? styles.buttonDisable : undefined,
(props.success && hovered) ? styles.buttonSuccessHovered : undefined,
(props.danger && hovered) ? styles.buttonDangerHovered : undefined,
marcaaron marked this conversation as resolved.
Show resolved Hide resolved
props.shouldRemoveRightBorderRadius ? styles.noRightBorderRadius : undefined,
props.shouldRemoveLeftBorderRadius ? styles.noLeftBorderRadius : undefined,
]}
Expand Down
5 changes: 5 additions & 0 deletions src/components/ConfirmModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ const propTypes = {
/** Modal content text */
prompt: PropTypes.string,

/** Is the action destructive */
danger: PropTypes.bool,

...withLocalizePropTypes,

...windowDimensionsPropTypes,
Expand All @@ -41,6 +44,7 @@ const defaultProps = {
confirmText: '',
cancelText: '',
prompt: '',
danger: false,
};

const ConfirmModal = props => (
Expand All @@ -63,6 +67,7 @@ const ConfirmModal = props => (

<Button
success
danger={props.danger}
style={[styles.mt4]}
onPress={props.onConfirm}
text={props.confirmText || props.translate('common.yes')}
Expand Down
8 changes: 8 additions & 0 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export default {
whatThis: 'What\'s this?',
iAcceptThe: 'I accept the ',
passwordCannotBeBlank: 'Password cannot be blank',
remove: 'Remove',
admin: 'Admin',
dateFormat: 'YYYY-MM-DD',
send: 'Send',
notifications: 'Notifications',
Expand Down Expand Up @@ -434,6 +436,12 @@ export default {
getStarted: 'Get started!',
genericFailureMessage: 'An error occurred creating the workspace, please try again.',
},
people: {
assignee: 'Assignee',
genericFailureMessage: 'An error occurred removing a user from the workspace, please try again.',
removeMembersPrompt: 'Are you sure you want to remove the selected people from your workspace?',
removeMembersTitle: 'Remove Members',
},
marcaaron marked this conversation as resolved.
Show resolved Hide resolved
card: {
addEmail: 'Add Email',
tagline: 'The Smartest corporate card in the room.',
Expand Down
8 changes: 8 additions & 0 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export default {
whatThis: '¿Qué es esto?',
iAcceptThe: 'Acepto los ',
passwordCannotBeBlank: 'La contraseña no puede estar vacía',
remove: 'Eliminar',
admin: 'Administrador',
dateFormat: 'AAAA-MM-DD',
send: 'Enviar',
notifications: 'Notificaciones',
Expand Down Expand Up @@ -366,6 +368,12 @@ export default {
getStarted: '¡Empezar!',
genericFailureMessage: 'Se ha producido un error al intentar crear el Workspace. Por favor, inténtalo de nuevo.',
},
people: {
assignee: 'Persona asignada',
genericFailureMessage: 'Se ha producido un error al intentar eliminar a un usuario del espacio de trabajo. Por favor inténtalo más tarde.',
removeMembersPrompt: '¿Estás seguro que quieres eliminar a las personas seleccionadas de tu espacio de trabajo?',
removeMembersTitle: 'Eliminar miembros',
},
card: {
addEmail: 'Agregar correo electrónico',
tagline: 'La tarjeta corporativa más inteligente de la habitación.',
Expand Down
13 changes: 13 additions & 0 deletions src/libs/API.js
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,18 @@ function Policy_Create(parameters) {
return Network.post(commandName, parameters);
}

/**
* @param {Object} parameters
* @param {String} parameters.policyID
* @param {Array} parameters.emailList
* @returns {Promise}
*/
function Policy_Employees_Remove(parameters) {
const commandName = 'Policy_Employees_Remove';
requireParameters(['policyID', 'emailList'], parameters, commandName);
return Network.post(commandName, parameters);
}

/**
* @param {Object} parameters
* @param {String} parameters.taskID
Expand Down Expand Up @@ -1038,4 +1050,5 @@ export {
GetPreferredCurrency,
GetCurrencyList,
Policy_Create,
Policy_Employees_Remove,
};
1 change: 1 addition & 0 deletions src/libs/Navigation/AppNavigator/AuthScreens.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ class AuthScreens extends React.Component {
cardStyle: {...styles.fullscreenCard},
cardStyleInterpolator: props => modalCardStyleInterpolator(this.props.isSmallScreenWidth, true, props),
cardOverlayEnabled: false,
isFullScreenModal: true,
};

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
// Screens
import BaseDrawerNavigator from './BaseDrawerNavigator';
import WorkspaceCardPage from '../../../pages/workspace/WorkspaceCardPage';
import WorkspacePeoplePage from '../../../pages/workspace/WorkspacePeoplePage';
import WorkspaceSidebar from '../../../pages/workspace/WorkspaceSidebar';

const WorkspaceSettingsDrawerNavigator = () => (
Expand All @@ -15,6 +16,11 @@ const WorkspaceSettingsDrawerNavigator = () => (
component: WorkspaceCardPage,
initialParams: {},
},
{
name: 'WorkspacePeople',
component: WorkspacePeoplePage,
initialParams: {},
},
]}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const CustomRootStackNavigator = ({
const {state, navigation, descriptors} = useNavigationBuilder(StackRouter, {
children,
});
const isDisplayingModal = Boolean(_.find(descriptors, descriptor => descriptor.options.isModal));
const topScreen = _.last(_.values(descriptors));
const isDisplayingModal = Boolean(topScreen.options.isModal);
const isDisplayingFullScreenModal = Boolean(topScreen.options.isFullScreenModal);
return (
<>
<StackView
Expand All @@ -27,7 +29,7 @@ const CustomRootStackNavigator = ({
{/* We need to superimpose a clickaway handler when showing modals so that they can be dismissed. Capturing
press events on the cardOverlay element in react-navigation is not yet supported on web */}
<ClickAwayHandler
isDisplayingModal={isDisplayingModal}
isDisplayingModal={isDisplayingModal && !isDisplayingFullScreenModal}
/>
</>
);
Expand Down
1 change: 1 addition & 0 deletions src/libs/Navigation/linkingConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export default {
path: ROUTES.WORKSPACE,
screens: {
WorkspaceCard: ROUTES.WORKSPACE_CARD,
WorkspacePeople: ROUTES.WORKSPACE_PEOPLE,
},
},

Expand Down
44 changes: 43 additions & 1 deletion src/libs/actions/Policy.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import _ from 'underscore';
import Onyx from 'react-native-onyx';
import {
GetPolicySummaryList, GetPolicyList, Policy_Employees_Merge, Policy_Create,
GetPolicySummaryList, GetPolicyList, Policy_Employees_Merge, Policy_Create, Policy_Employees_Remove,
} from '../API';
import ONYXKEYS from '../../ONYXKEYS';
import {formatPersonalDetails} from './PersonalDetails';
Expand Down Expand Up @@ -91,6 +91,47 @@ function getPolicyList() {
});
}

/**
* Remove the passed members from the policy employeeList
*
* @param {Array} members
* @param {String} policyID
*/
function removeMembers(members, policyID) {
// In case user selects only themselves (admin), their email will be filtered out and the members
// array passed will be empty, prevent the funtion from proceeding in that case as there is noone to remove
if (members.length === 0) {
return;
}

const key = `${ONYXKEYS.COLLECTION.POLICY}${policyID}`;

// Make a shallow copy to preserve original data and remove the members
const policy = _.clone(allPolicies[key]);
policy.employeeList = _.without(policy.employeeList, ...members);

// Optimistically remove the members from the policy
Onyx.set(key, policy);

// Make the API call to merge the login into the policy
Policy_Employees_Remove({
emailList: members,
policyID,
})
.then((data) => {
if (data.jsonCode === 200) {
return;
}
const policyDataWithMembersRemoved = _.clone(allPolicies[key]);
policyDataWithMembersRemoved.employeeList = [...policyDataWithMembersRemoved.employeeList, ...members];
Onyx.set(key, policyDataWithMembersRemoved);

// Show the user feedback that the removal failed
console.error(data.message);
Growl.show(translateLocal('workspace.people.genericFailureMessage'), CONST.GROWL.ERROR, 5000);
});
}

/**
* Merges the passed in login into the specified policy
*
Expand Down Expand Up @@ -165,6 +206,7 @@ function create(name) {
export {
getPolicySummaries,
getPolicyList,
removeMembers,
invite,
create,
};
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
Loading