UserGroupDeleteModal.tsx 6.1 KB

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