Chore: Hooks - create usePermissions (#4190)

* Chore: Hooks - create custom hook usePermissions

* minor tweak

* Change usage of usePermissiosn on LivechatEditView

* Create getPermissionsSelector

* Simplify selector

* Simplify userRoles

* First render with permissions array length of false

* Move roles state closer to each other

* useSubscription (not working, but looking cool)

* at least it's working now

* working

* cleanup

* solve ts return

* Change it to useSubscriptionRoles only and check for diff on the state

* Remove IAppState

* Minor tweak to work properly useSubscriptionRoles

Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
Reinaldo Neto 2022-06-13 17:36:54 -03:00 committed by GitHub
parent a16c271f1f
commit fa90e4d456
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 26 deletions

View File

@ -1 +1,2 @@
export * from './useAppSelector'; export * from './useAppSelector';
export * from './usePermissions';

View File

@ -0,0 +1,53 @@
import { useState, useEffect } from 'react';
import { dequal } from 'dequal';
import { Subscription } from 'rxjs';
import { createSelector } from 'reselect';
import { shallowEqual } from 'react-redux';
import { TSupportedPermissions } from '../../reducers/permissions';
import { IApplicationState, TSubscriptionModel } from '../../definitions';
import { getUserSelector } from '../../selectors/login';
import { useAppSelector } from './useAppSelector';
import { getSubscriptionByRoomId } from '../database/services/Subscription';
const getPermissionsSelector = createSelector(
[(state: IApplicationState) => state.permissions, (_state: any, permissionsArray: TSupportedPermissions[]) => permissionsArray],
(permissions, permissionsArray) => permissionsArray.map(p => permissions[p])
);
const useSubscriptionRoles = (rid?: string): TSubscriptionModel['roles'] => {
const [subscriptionRoles, setSubscriptionRoles] = useState<TSubscriptionModel['roles']>([]);
useEffect(() => {
if (!rid) {
return;
}
let subSubscription: Subscription;
getSubscriptionByRoomId(rid).then(sub => {
if (!sub) {
return;
}
const observable = sub.observe();
subSubscription = observable.subscribe(s => {
if (!dequal(subscriptionRoles, s.roles)) {
setSubscriptionRoles(s.roles);
}
});
});
return () => {
if (subSubscription && subSubscription?.unsubscribe) subSubscription.unsubscribe();
};
}, [subscriptionRoles]);
return subscriptionRoles;
};
export function usePermissions(permissions: TSupportedPermissions[], rid?: string): boolean[] {
const userRoles = useAppSelector(state => getUserSelector(state).roles || [], shallowEqual);
const permissionsRedux = useAppSelector(state => getPermissionsSelector(state, permissions), shallowEqual);
const subscriptionRoles = useSubscriptionRoles(rid);
const mergedRoles = [...new Set([...(subscriptionRoles || []), ...userRoles])];
return permissionsRedux.map(permission => (permission ?? []).some(r => mergedRoles.includes(r)));
}

View File

@ -21,8 +21,8 @@ import { ICustomFields, IInputsRefs, TParams, ITitle, ILivechat } from '../defin
import { IApplicationState, IUser } from '../definitions'; import { IApplicationState, IUser } from '../definitions';
import { ChatsStackParamList } from '../stacks/types'; import { ChatsStackParamList } from '../stacks/types';
import sharedStyles from './Styles'; import sharedStyles from './Styles';
import { hasPermission } from '../lib/methods/helpers';
import { Services } from '../lib/services'; import { Services } from '../lib/services';
import { usePermissions } from '../lib/hooks';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
@ -55,17 +55,9 @@ interface ILivechatEditViewProps {
const Title = ({ title, theme }: ITitle) => const Title = ({ title, theme }: ITitle) =>
title ? <Text style={[styles.title, { color: themes[theme].titleText }]}>{title}</Text> : null; title ? <Text style={[styles.title, { color: themes[theme].titleText }]}>{title}</Text> : null;
const LivechatEditView = ({ const LivechatEditView = ({ user, navigation, route, theme }: ILivechatEditViewProps) => {
user,
navigation,
route,
theme,
editOmnichannelContact,
editLivechatRoomCustomfields
}: ILivechatEditViewProps) => {
const [customFields, setCustomFields] = useState<ICustomFields>({}); const [customFields, setCustomFields] = useState<ICustomFields>({});
const [availableUserTags, setAvailableUserTags] = useState<string[]>([]); const [availableUserTags, setAvailableUserTags] = useState<string[]>([]);
const [permissions, setPermissions] = useState<boolean[]>([]);
const params = {} as TParams; const params = {} as TParams;
const inputs = {} as IInputsRefs; const inputs = {} as IInputsRefs;
@ -73,6 +65,11 @@ const LivechatEditView = ({
const livechat = (route.params?.room ?? {}) as ILivechat; const livechat = (route.params?.room ?? {}) as ILivechat;
const visitor = route.params?.roomUser ?? {}; const visitor = route.params?.roomUser ?? {};
const [editOmnichannelContactPermission, editLivechatRoomCustomFieldsPermission] = usePermissions(
['edit-omnichannel-contact', 'edit-livechat-room-customfields'],
livechat.rid
);
const getCustomFields = async () => { const getCustomFields = async () => {
const result = await Services.getCustomFields(); const result = await Services.getCustomFields();
if (result.success && result.customFields?.length) { if (result.success && result.customFields?.length) {
@ -171,18 +168,12 @@ const LivechatEditView = ({
params[key] = text; params[key] = text;
}; };
const getPermissions = async () => {
const permissionsArray = await hasPermission([editOmnichannelContact, editLivechatRoomCustomfields], livechat.rid);
setPermissions(permissionsArray);
};
useEffect(() => { useEffect(() => {
navigation.setOptions({ navigation.setOptions({
title: I18n.t('Edit') title: I18n.t('Edit')
}); });
handleGetAgentDepartments(); handleGetAgentDepartments();
getCustomFields(); getCustomFields();
getPermissions();
}, []); }, []);
return ( return (
@ -201,7 +192,7 @@ const LivechatEditView = ({
inputs.name?.focus(); inputs.name?.focus();
}} }}
theme={theme} theme={theme}
editable={!!permissions[0]} editable={!!editOmnichannelContactPermission}
/> />
<FormTextInput <FormTextInput
label={I18n.t('Email')} label={I18n.t('Email')}
@ -214,7 +205,7 @@ const LivechatEditView = ({
inputs.phone?.focus(); inputs.phone?.focus();
}} }}
theme={theme} theme={theme}
editable={!!permissions[0]} editable={!!editOmnichannelContactPermission}
/> />
<FormTextInput <FormTextInput
label={I18n.t('Phone')} label={I18n.t('Phone')}
@ -233,7 +224,7 @@ const LivechatEditView = ({
} }
}} }}
theme={theme} theme={theme}
editable={!!permissions[0]} editable={!!editOmnichannelContactPermission}
/> />
{Object.entries(customFields?.visitor || {}).map(([key, value], index, array) => ( {Object.entries(customFields?.visitor || {}).map(([key, value], index, array) => (
<FormTextInput <FormTextInput
@ -250,7 +241,7 @@ const LivechatEditView = ({
inputs.topic?.focus(); inputs.topic?.focus();
}} }}
theme={theme} theme={theme}
editable={!!permissions[0]} editable={!!editOmnichannelContactPermission}
/> />
))} ))}
<Title title={I18n.t('Conversation')} theme={theme} /> <Title title={I18n.t('Conversation')} theme={theme} />
@ -262,7 +253,7 @@ const LivechatEditView = ({
defaultValue={livechat?.topic} defaultValue={livechat?.topic}
onChangeText={text => onChangeText('topic', text)} onChangeText={text => onChangeText('topic', text)}
theme={theme} theme={theme}
editable={!!permissions[1]} editable={!!editLivechatRoomCustomFieldsPermission}
/> />
<Text style={[styles.label, { color: themes[theme].titleText }]}>{I18n.t('Tags')}</Text> <Text style={[styles.label, { color: themes[theme].titleText }]}>{I18n.t('Tags')}</Text>
@ -275,7 +266,7 @@ const LivechatEditView = ({
value={tagParamSelected} value={tagParamSelected}
context={BlockContext.FORM} context={BlockContext.FORM}
multiselect multiselect
disabled={!permissions[1]} disabled={!editLivechatRoomCustomFieldsPermission}
inputStyle={styles.multiSelect} inputStyle={styles.multiSelect}
/> />
@ -294,7 +285,7 @@ const LivechatEditView = ({
submit(); submit();
}} }}
theme={theme} theme={theme}
editable={!!permissions[1]} editable={!!editLivechatRoomCustomFieldsPermission}
/> />
))} ))}
@ -307,9 +298,7 @@ const LivechatEditView = ({
const mapStateToProps = (state: IApplicationState) => ({ const mapStateToProps = (state: IApplicationState) => ({
server: state.server.server, server: state.server.server,
user: getUserSelector(state), user: getUserSelector(state)
editOmnichannelContact: state.permissions['edit-omnichannel-contact'],
editLivechatRoomCustomfields: state.permissions['edit-livechat-room-customfields']
}); });
export default connect(mapStateToProps)(withTheme(LivechatEditView)); export default connect(mapStateToProps)(withTheme(LivechatEditView));