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:
parent
a16c271f1f
commit
fa90e4d456
|
@ -1 +1,2 @@
|
||||||
export * from './useAppSelector';
|
export * from './useAppSelector';
|
||||||
|
export * from './usePermissions';
|
||||||
|
|
|
@ -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)));
|
||||||
|
}
|
|
@ -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));
|
||||||
|
|
Loading…
Reference in New Issue