UserGroupDeleteModal.tsx 5.8 KB

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