UserGroupModal.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import type { FC } from 'react';
  2. import React, {
  3. useState, useEffect, useCallback, useMemo,
  4. } from 'react';
  5. import type { Ref, IUserGroup, IUserGroupHasId } from '@growi/core';
  6. import { useTranslation } from 'next-i18next';
  7. import {
  8. Modal, ModalHeader, ModalBody, ModalFooter,
  9. } from 'reactstrap';
  10. type Props = {
  11. userGroup?: IUserGroupHasId,
  12. buttonLabel?: string,
  13. onClickSubmit?: (userGroupData: Partial<IUserGroupHasId>) => Promise<IUserGroupHasId | void>
  14. isShow?: boolean
  15. onHide?: () => Promise<void> | void
  16. isExternalGroup?: boolean
  17. };
  18. const UserGroupModalSubstance: FC<Props> = (props: Props) => {
  19. const { t } = useTranslation('admin');
  20. const {
  21. userGroup, buttonLabel, onClickSubmit, onHide, isExternalGroup = false,
  22. } = props;
  23. /*
  24. * State
  25. */
  26. const [currentName, setName] = useState('');
  27. const [currentDescription, setDescription] = useState('');
  28. const [currentParent, setParent] = useState<Ref<IUserGroup> | null>(null);
  29. /*
  30. * Function
  31. */
  32. const onChangeNameHandler = useCallback((e) => {
  33. setName(e.target.value);
  34. }, []);
  35. const onChangeDescriptionHandler = useCallback((e) => {
  36. setDescription(e.target.value);
  37. }, []);
  38. // Memoized user group data for submission
  39. const userGroupData = useMemo(() => ({
  40. _id: userGroup?._id,
  41. name: currentName,
  42. description: currentDescription,
  43. parent: currentParent,
  44. }), [userGroup?._id, currentName, currentDescription, currentParent]);
  45. const onSubmitHandler = useCallback(async(e) => {
  46. e.preventDefault(); // no reload
  47. if (onClickSubmit == null) {
  48. return;
  49. }
  50. await onClickSubmit(userGroupData);
  51. }, [onClickSubmit, userGroupData]);
  52. // componentDidMount
  53. useEffect(() => {
  54. if (userGroup != null) {
  55. setName(userGroup.name);
  56. setDescription(userGroup.description);
  57. setParent(userGroup.parent);
  58. }
  59. }, [userGroup]);
  60. return (
  61. <form onSubmit={onSubmitHandler}>
  62. <ModalHeader tag="h4" toggle={onHide}>
  63. {t('user_group_management.basic_info')}
  64. </ModalHeader>
  65. <ModalBody>
  66. <div>
  67. <label htmlFor="name" className="form-label">
  68. {t('user_group_management.group_name')}
  69. </label>
  70. <input
  71. className="form-control"
  72. type="text"
  73. name="name"
  74. placeholder={t('user_group_management.group_example')}
  75. value={currentName}
  76. onChange={onChangeNameHandler}
  77. required
  78. disabled={isExternalGroup}
  79. />
  80. </div>
  81. <div>
  82. <label htmlFor="description" className="form-label">
  83. {t('Description')}
  84. </label>
  85. <textarea className="form-control" name="description" value={currentDescription} onChange={onChangeDescriptionHandler} />
  86. {isExternalGroup && (
  87. <p className="form-text text-muted">
  88. <small>
  89. {t('external_user_group.description_form_detail')}
  90. </small>
  91. </p>
  92. )}
  93. </div>
  94. {/* TODO 90732: Add a drop-down to show selectable parents */}
  95. {/* TODO 85462: Add a note that "if you change the parent, the offspring will also be moved together */}
  96. </ModalBody>
  97. <ModalFooter>
  98. <div>
  99. <button type="submit" className="btn btn-primary">
  100. {buttonLabel}
  101. </button>
  102. </div>
  103. </ModalFooter>
  104. </form>
  105. );
  106. };
  107. export const UserGroupModal: FC<Props> = (props: Props) => {
  108. const { isShow, onHide } = props;
  109. return (
  110. <Modal className="modal-md" isOpen={isShow} toggle={onHide}>
  111. {isShow && (
  112. <UserGroupModalSubstance {...props} />
  113. )}
  114. </Modal>
  115. );
  116. };