Skip to content

Commit

Permalink
refactor: add permission management and display condition
Browse files Browse the repository at this point in the history
  • Loading branch information
lme-axelor committed Dec 11, 2024
1 parent 1f4bca0 commit 241ea28
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 110 deletions.
1 change: 1 addition & 0 deletions packages/apps/hr/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export {searchExpenseType as searchExpenseTypeApi} from './expense-type-api';
export {searchKilometricAllowParam as searchKilometricAllowParamApi} from './kilometric-allow-param-api';
export {
cancelLeave as cancelLeaveApi,
deleteLeave as deleteLeaveApi,
fetchLeave as fetchLeaveApi,
fetchLeaveById as fetchLeaveByIdApi,
fetchLeaveReason as fetchLeaveReasonApi,
Expand Down
12 changes: 12 additions & 0 deletions packages/apps/hr/src/api/leave-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,15 @@ export async function rejectLeave({leaveRequestId, version, groundForRefusal}) {
description: 'reject leave',
});
}

export async function deleteLeave({leaveRequestId}) {
return getActionApi().send({
url: `ws/rest/com.axelor.apps.hr.db.LeaveRequest/${leaveRequestId}`,
method: 'delete',
description: 'delete leave request',
matchers: {
modelName: 'com.axelor.apps.hr.db.LeaveRequest',
id: leaveRequestId,
},
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import React from 'react';
import {useTranslator, useTypes} from '@axelor/aos-mobile-core';
import React, {useMemo} from 'react';
import {
usePermitted,
useSelector,
useTranslator,
useTypes,
} from '@axelor/aos-mobile-core';
import {ActionCard} from '@axelor/aos-mobile-ui';
import {LeaveCard} from '../../atoms';
import {Leave} from '../../../types';

interface LeaveActionCardProps {
mode: number;
Expand All @@ -39,26 +43,47 @@ const LeaveActionCard = ({
}: LeaveActionCardProps) => {
const I18n = useTranslator();
const {LeaveRequest} = useTypes();
const {readonly} = usePermitted({
modelName: 'com.axelor.apps.hr.db.LeaveRequest',
});

const {user} = useSelector((state: any) => state.user);

const userCanValidate = useMemo(() => {
return (
(user.employee?.hrManager ||
leave.employee?.managerUser?.id === user.id) &&
leave.statusSelect === LeaveRequest?.statusSelect.WaitingValidation
);
}, [LeaveRequest?.statusSelect.WaitingValidation, leave, user]);

const isDefaultDisplay = useMemo(() => {
return (
readonly ||
(!userCanValidate &&
leave.statusSelect !== LeaveRequest?.statusSelect.Draft)
);
}, [LeaveRequest?.statusSelect, readonly, leave, userCanValidate]);

return (
<ActionCard
translator={I18n.t}
actionList={[
{
iconName: 'send-fill',
helper: I18n.t('Hr_Send'),
onPress: onSend,
hidden:
mode === Leave.mode.leavesToValidate ||
leave.statusSelect !== LeaveRequest?.statusSelect.Draft,
},
{
iconName: 'check-lg',
helper: I18n.t('Hr_Validate'),
onPress: onValidate,
hidden: mode === Leave.mode.myLeaves,
},
]}>
actionList={
!isDefaultDisplay && [
{
iconName: 'send-fill',
helper: I18n.t('Hr_Send'),
onPress: onSend,
hidden: leave.statusSelect !== LeaveRequest?.statusSelect.Draft,
},
{
iconName: 'check-lg',
helper: I18n.t('Hr_Validate'),
onPress: onValidate,
hidden: leave.statusSelect === LeaveRequest?.statusSelect.Draft,
},
]
}>
<LeaveCard
mode={mode}
statusSelect={leave.statusSelect}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,84 +20,87 @@ import React, {useCallback, useMemo, useState} from 'react';
import {StyleSheet, View} from 'react-native';
import {
useDispatch,
useNavigation,
usePermitted,
useSelector,
useTranslator,
useTypes,
} from '@axelor/aos-mobile-core';
import {Button, useThemeColor} from '@axelor/aos-mobile-ui';
import {
cancelLeave,
deleteLeave,
sendLeave,
validateLeave,
} from '../../../features/leaveSlice';
import {LeaveRefusalPopup} from '../../templates';

interface LeaveDetailsButtonsProps {
statusSelect: number;
leaveId: number;
leaveVersion: number;
leaveRequest: any;
}

const LeaveDetailsButtons = ({
statusSelect,
leaveId,
leaveVersion,
leaveRequest,
}: LeaveDetailsButtonsProps) => {
const I18n = useTranslator();
const Colors = useThemeColor();
const navigation = useNavigation();
const dispatch = useDispatch();

const {LeaveRequest} = useTypes();
const {canDelete, readonly} = usePermitted({
modelName: 'com.axelor.apps.hr.db.LeaveRequest',
});

const [refusalPopupIsOpen, setRefusalPopupIsOpen] = useState(false);

const {user} = useSelector(state => state.user);

const leaveRequestParams = useMemo(
() => ({
leaveRequestId: leaveId,
version: leaveVersion,
leaveRequestId: leaveRequest.id,
version: leaveRequest.version,
user: user,
userId: user.id,
}),
[leaveId, leaveVersion],
[leaveRequest, user],
);

const sendLeaveAPI = useCallback(() => {
dispatch(
(sendLeave as any)({
...leaveRequestParams,
userId: user?.id,
}),
);
}, [dispatch, leaveRequestParams, user?.id]);
dispatch((sendLeave as any)(leaveRequestParams));
}, [dispatch, leaveRequestParams]);

const validateLeaveAPI = useCallback(() => {
dispatch(
(validateLeave as any)({
...leaveRequestParams,
user: user,
}),
);
}, [dispatch, leaveRequestParams, user]);
dispatch((validateLeave as any)(leaveRequestParams));
}, [dispatch, leaveRequestParams]);

const cancelLeaveAPI = useCallback(() => {
dispatch(
(cancelLeave as any)({
...leaveRequestParams,
userId: user?.id,
}),
);
}, [dispatch, leaveRequestParams, user?.id]);
dispatch((cancelLeave as any)(leaveRequestParams));
}, [dispatch, leaveRequestParams]);

const deleteLeaveAPI = useCallback(() => {
dispatch((deleteLeave as any)(leaveRequestParams));
navigation.pop();
}, [dispatch, leaveRequestParams, navigation]);

if (readonly) {
return null;
}

if (statusSelect === LeaveRequest?.statusSelect.Draft) {
return (
<View style={styles.container}>
<Button
title={I18n.t('Hr_Cancel')}
onPress={cancelLeaveAPI}
width="45%"
color={Colors.errorColor}
iconName="trash3-fill"
/>
{canDelete && (
<Button
title={I18n.t('Hr_Delete')}
onPress={deleteLeaveAPI}
width="45%"
color={Colors.errorColor}
iconName="trash3-fill"
/>
)}
<Button
title={I18n.t('Hr_Send')}
onPress={sendLeaveAPI}
Expand All @@ -109,26 +112,42 @@ const LeaveDetailsButtons = ({
}

if (statusSelect === LeaveRequest?.statusSelect.WaitingValidation) {
if (
user?.employee?.hrManager ||
leaveRequest.employee?.managerUser?.id === user.id
) {
return (
<View style={styles.container}>
<Button
title={I18n.t('Hr_Refuse')}
onPress={() => setRefusalPopupIsOpen(true)}
width="45%"
color={Colors.errorColor}
iconName="x-lg"
/>
<Button
title={I18n.t('Hr_Validate')}
onPress={validateLeaveAPI}
width="45%"
iconName="check-lg"
/>
<LeaveRefusalPopup
isOpen={refusalPopupIsOpen}
leaveId={leaveRequest.id}
leaveVersion={leaveRequest.version}
handleClose={() => setRefusalPopupIsOpen(false)}
/>
</View>
);
}

return (
<View style={styles.container}>
<Button
title={I18n.t('Hr_Refuse')}
onPress={() => setRefusalPopupIsOpen(true)}
width="45%"
title={I18n.t('Hr_Cancel')}
onPress={cancelLeaveAPI}
color={Colors.errorColor}
iconName="x-lg"
/>
<Button
title={I18n.t('Hr_Validate')}
onPress={validateLeaveAPI}
width="45%"
iconName="check-lg"
/>
<LeaveRefusalPopup
isOpen={refusalPopupIsOpen}
leaveId={leaveId}
leaveVersion={leaveVersion}
onCancel={() => setRefusalPopupIsOpen(false)}
iconName="trash3-fill"
/>
</View>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,37 +25,39 @@ interface LeaveRefusalPopupProps {
isOpen: boolean;
leaveId: number;
leaveVersion: number;
onCancel: () => void;
handleClose: () => void;
}

const LeaveRefusalPopup = ({
isOpen,
leaveId,
leaveVersion,
onCancel,
handleClose,
}: LeaveRefusalPopupProps) => {
const dispatch = useDispatch();

const {user} = useSelector(state => state.user);

const rejectLeaveAPI = useCallback(
(refusalMessage: string) => {
handleClose();
dispatch(
(rejectLeave as any)({
leaveRequestId: leaveId,
version: leaveVersion,
user: user,
userId: user.id,
groundForRefusal: refusalMessage,
}),
);
},
[dispatch, leaveId, leaveVersion, user],
[dispatch, handleClose, leaveId, leaveVersion, user],
);

return (
<RefusalPopup
isOpen={isOpen}
onCancel={onCancel}
onCancel={handleClose}
onValidate={rejectLeaveAPI}
/>
);
Expand Down
1 change: 1 addition & 0 deletions packages/apps/hr/src/features/asyncFunctions-index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export {
} from './kilometricAllowParamSlice';
export {
cancelLeave,
deleteLeave,
fetchLeave,
fetchLeaveById,
fetchLeaveReason,
Expand Down
Loading

0 comments on commit 241ea28

Please sign in to comment.