UserGroupDeleteModal.tsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. import React, {
  2. FC, useCallback, useState, useMemo,
  3. } from 'react';
  4. import { TFunctionResult } from 'i18next';
  5. import { useTranslation } from 'react-i18next';
  6. import {
  7. Modal, ModalHeader, ModalBody, ModalFooter,
  8. } from 'reactstrap';
  9. import { IUserGroupHasId } from '~/interfaces/user';
  10. import { CustomWindow } from '~/interfaces/global';
  11. import Xss from '~/services/xss';
  12. /**
  13. * Delete User Group Select component
  14. *
  15. * @export
  16. * @class GrantSelector
  17. * @extends {React.Component}
  18. */
  19. type Props = {
  20. userGroups: IUserGroupHasId[],
  21. deleteUserGroup?: IUserGroupHasId,
  22. onDelete?: (deleteGroupId: string, actionName: string, transferToUserGroupId: string) => Promise<void> | void,
  23. isShow: boolean,
  24. onShow?: (group: IUserGroupHasId) => Promise<void> | void,
  25. onHide?: () => Promise<void> | void,
  26. };
  27. type AvailableOption = {
  28. id: number,
  29. actionForPages: string,
  30. iconClass: string,
  31. styleClass: string,
  32. label: TFunctionResult,
  33. };
  34. // actionName master constants
  35. const actionForPages = {
  36. public: 'public',
  37. delete: 'delete',
  38. transfer: 'transfer',
  39. };
  40. const UserGroupDeleteModal: FC<Props> = (props: Props) => {
  41. const xss: Xss = (window as CustomWindow).xss;
  42. const { t } = useTranslation();
  43. const availableOptions = useMemo<AvailableOption[]>(() => {
  44. return [
  45. {
  46. id: 1,
  47. actionForPages: actionForPages.public,
  48. iconClass: 'icon-people',
  49. styleClass: '',
  50. label: t('admin:user_group_management.delete_modal.publish_pages'),
  51. },
  52. {
  53. id: 2,
  54. actionForPages: actionForPages.delete,
  55. iconClass: 'icon-trash',
  56. styleClass: 'text-danger',
  57. label: t('admin:user_group_management.delete_modal.delete_pages'),
  58. },
  59. {
  60. id: 3,
  61. actionForPages: actionForPages.transfer,
  62. iconClass: 'icon-options',
  63. styleClass: '',
  64. label: t('admin:user_group_management.delete_modal.transfer_pages'),
  65. },
  66. ];
  67. }, []);
  68. /*
  69. * State
  70. */
  71. const [actionName, setActionName] = useState<string>('');
  72. const [transferToUserGroupId, setTransferToUserGroupId] = useState<string>('');
  73. /*
  74. * Function
  75. */
  76. const resetStates = useCallback(() => {
  77. setActionName('');
  78. setTransferToUserGroupId('');
  79. }, []);
  80. const onHide = useCallback(() => {
  81. if (props.onHide == null) {
  82. return;
  83. }
  84. resetStates();
  85. props.onHide();
  86. }, [props.onHide]);
  87. const handleActionChange = useCallback((e) => {
  88. const actionName = e.target.value;
  89. setActionName(actionName);
  90. }, [setActionName]);
  91. const handleGroupChange = useCallback((e) => {
  92. const transferToUserGroupId = e.target.value;
  93. setTransferToUserGroupId(transferToUserGroupId);
  94. }, []);
  95. const handleSubmit = useCallback((e) => {
  96. if (props.onDelete == null || props.deleteUserGroup == null) {
  97. return;
  98. }
  99. e.preventDefault();
  100. props.onDelete(
  101. props.deleteUserGroup._id,
  102. actionName,
  103. transferToUserGroupId,
  104. );
  105. }, [props.onDelete, props.deleteUserGroup, actionName, transferToUserGroupId]);
  106. const renderPageActionSelector = useCallback(() => {
  107. const options = availableOptions.map((opt) => {
  108. const dataContent = `<i class="icon icon-fw ${opt.iconClass} ${opt.styleClass}"></i> <span class="action-name ${opt.styleClass}">${opt.label}</span>`;
  109. return <option key={opt.id} value={opt.actionForPages} data-content={dataContent}>{opt.label}</option>;
  110. });
  111. return (
  112. <select
  113. name="actionName"
  114. className="form-control"
  115. placeholder="select"
  116. value={actionName}
  117. onChange={handleActionChange}
  118. >
  119. <option value="" disabled>{t('admin:user_group_management.delete_modal.dropdown_desc')}</option>
  120. {options}
  121. </select>
  122. );
  123. }, [handleActionChange, actionName, availableOptions]);
  124. const renderGroupSelector = useCallback(() => {
  125. const { deleteUserGroup } = props;
  126. if (deleteUserGroup == null) {
  127. return;
  128. }
  129. const groups = props.userGroups.filter((group) => {
  130. return group._id !== deleteUserGroup._id;
  131. });
  132. const options = groups.map((group) => {
  133. const dataContent = `<i class="icon icon-fw icon-organization"></i> ${xss.process(group.name)}`;
  134. return <option key={group._id} value={group._id} data-content={dataContent}>{xss.process(group.name)}</option>;
  135. });
  136. const defaultOptionText = groups.length === 0 ? t('admin:user_group_management.delete_modal.no_groups')
  137. : t('admin:user_group_management.delete_modal.select_group');
  138. return (
  139. <select
  140. name="transferToUserGroupId"
  141. className={`form-control ${actionName === actionForPages.transfer ? '' : 'd-none'}`}
  142. value={transferToUserGroupId}
  143. onChange={handleGroupChange}
  144. >
  145. <option value="" disabled>{defaultOptionText}</option>
  146. {options}
  147. </select>
  148. );
  149. }, [actionName, transferToUserGroupId, props.userGroups, props.deleteUserGroup]);
  150. const validateForm = useCallback(() => {
  151. let isValid = true;
  152. if (actionName === '') {
  153. isValid = false;
  154. }
  155. else if (actionName === actionForPages.transfer) {
  156. isValid = transferToUserGroupId !== '';
  157. }
  158. return isValid;
  159. }, [actionName, transferToUserGroupId]);
  160. return (
  161. <Modal className="modal-md" isOpen={props.isShow} toggle={onHide}>
  162. <ModalHeader tag="h4" toggle={onHide} className="bg-danger text-light">
  163. <i className="icon icon-fire"></i> {t('admin:user_group_management.delete_modal.header')}
  164. </ModalHeader>
  165. <ModalBody>
  166. <div>
  167. <span className="font-weight-bold">{t('admin:user_group_management.group_name')}</span> : &quot;{props?.deleteUserGroup?.name || ''}&quot;
  168. </div>
  169. <div className="text-danger mt-3">
  170. {t('admin:user_group_management.delete_modal.desc')}
  171. </div>
  172. </ModalBody>
  173. <ModalFooter>
  174. <form className="d-flex justify-content-between w-100" onSubmit={handleSubmit}>
  175. <div className="d-flex form-group mb-0">
  176. {renderPageActionSelector()}
  177. {renderGroupSelector()}
  178. </div>
  179. <button type="submit" value="" className="btn btn-sm btn-danger text-nowrap" disabled={!validateForm()}>
  180. <i className="icon icon-fire"></i> {t('Delete')}
  181. </button>
  182. </form>
  183. </ModalFooter>
  184. </Modal>
  185. );
  186. };
  187. export default UserGroupDeleteModal;