CustomizeFunctionSetting.jsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. import React from 'react';
  2. import PropTypes from 'prop-types';
  3. import { withTranslation } from 'react-i18next';
  4. import {
  5. Card, CardBody,
  6. Dropdown, DropdownToggle, DropdownMenu, DropdownItem,
  7. } from 'reactstrap';
  8. import { withUnstatedContainers } from '../../UnstatedUtils';
  9. import { toastSuccess, toastError } from '../../../util/apiNotification';
  10. import AppContainer from '../../../services/AppContainer';
  11. import AdminCustomizeContainer from '../../../services/AdminCustomizeContainer';
  12. import AdminUpdateButtonRow from '../Common/AdminUpdateButtonRow';
  13. import CustomizeFunctionOption from './CustomizeFunctionOption';
  14. class CustomizeFunctionSetting extends React.Component {
  15. constructor(props) {
  16. super(props);
  17. this.state = {
  18. isDropdownOpenS: false, // S
  19. isDropdownOpen: false, // M
  20. isDropdownOpenL: false, // L
  21. isDropdownOpenXL: false, // XL
  22. };
  23. this.onToggleDropdownS = this.onToggleDropdownS.bind(this); // S
  24. this.onToggleDropdown = this.onToggleDropdown.bind(this); // M
  25. this.onToggleDropdownL = this.onToggleDropdownL.bind(this); // L
  26. this.onToggleDropdownXL = this.onToggleDropdownXL.bind(this); // XL
  27. this.onClickSubmit = this.onClickSubmit.bind(this);
  28. }
  29. onToggleDropdownS() {
  30. this.setState({ isDropdownOpenS: !this.state.isDropdownOpenS });
  31. }
  32. onToggleDropdown() {
  33. this.setState({ isDropdownOpen: !this.state.isDropdownOpen });
  34. }
  35. onToggleDropdownL() {
  36. this.setState({ isDropdownOpenL: !this.state.isDropdownOpenL });
  37. }
  38. onToggleDropdownXL() {
  39. this.setState({ isDropdownOpenXL: !this.state.isDropdownOpenXL });
  40. }
  41. async onClickSubmit() {
  42. const { t, adminCustomizeContainer } = this.props;
  43. try {
  44. await adminCustomizeContainer.updateCustomizeFunction();
  45. toastSuccess(t('toaster.update_successed', { target: t('admin:customize_setting.function') }));
  46. }
  47. catch (err) {
  48. toastError(err);
  49. }
  50. }
  51. render() {
  52. const { t, adminCustomizeContainer } = this.props;
  53. return (
  54. <React.Fragment>
  55. <div className="row">
  56. <div className="col-12">
  57. <h2 className="admin-setting-header">{t('admin:customize_setting.function')}</h2>
  58. <Card className="card well my-3">
  59. <CardBody className="px-0 py-2">
  60. {t('admin:customize_setting.function_desc')}
  61. </CardBody>
  62. </Card>
  63. <div className="form-group row">
  64. <div className="offset-md-3 col-md-6 text-left">
  65. <CustomizeFunctionOption
  66. optionId="isEnabledTimeline"
  67. label={t('admin:customize_setting.function_options.timeline')}
  68. isChecked={adminCustomizeContainer.state.isEnabledTimeline}
  69. onChecked={() => { adminCustomizeContainer.switchEnableTimeline() }}
  70. >
  71. <p className="form-text text-muted">
  72. {t('admin:customize_setting.function_options.timeline_desc1')}<br />
  73. {t('admin:customize_setting.function_options.timeline_desc2')}<br />
  74. {t('admin:customize_setting.function_options.timeline_desc3')}
  75. </p>
  76. </CustomizeFunctionOption>
  77. </div>
  78. </div>
  79. <div className="form-group row">
  80. <div className="offset-md-3 col-md-6 text-left">
  81. <CustomizeFunctionOption
  82. optionId="isSavedStatesOfTabChanges"
  83. label={t('admin:customize_setting.function_options.tab_switch')}
  84. isChecked={adminCustomizeContainer.state.isSavedStatesOfTabChanges}
  85. onChecked={() => { adminCustomizeContainer.switchSavedStatesOfTabChanges() }}
  86. >
  87. <p className="form-text text-muted">
  88. {t('admin:customize_setting.function_options.tab_switch_desc1')}<br />
  89. {t('admin:customize_setting.function_options.tab_switch_desc2')}
  90. </p>
  91. </CustomizeFunctionOption>
  92. </div>
  93. </div>
  94. <div className="form-group row">
  95. <div className="offset-md-3 col-md-6 text-left">
  96. <CustomizeFunctionOption
  97. optionId="isEnabledAttachTitleHeader"
  98. label={t('admin:customize_setting.function_options.attach_title_header')}
  99. isChecked={adminCustomizeContainer.state.isEnabledAttachTitleHeader}
  100. onChecked={() => { adminCustomizeContainer.switchEnabledAttachTitleHeader() }}
  101. >
  102. <p className="form-text text-muted">
  103. {t('admin:customize_setting.function_options.attach_title_header_desc')}
  104. </p>
  105. </CustomizeFunctionOption>
  106. </div>
  107. </div>
  108. {/* S: Modal */}
  109. <div className="form-group row">
  110. <div className="offset-md-3 col-md-6 text-left">
  111. <div className="my-0 w-100">
  112. <label>{t('admin:customize_setting.function_options.list_num_desc_in_page_contents_modal')}</label>
  113. </div>
  114. <Dropdown isOpen={this.state.isDropdownOpenS} toggle={this.onToggleDropdownS}>
  115. <DropdownToggle className="text-right col-6" caret>
  116. <span className="float-left">{adminCustomizeContainer.state.pageLimitationS}</span>
  117. </DropdownToggle>
  118. <DropdownMenu className="dropdown-menu" role="menu">
  119. <DropdownItem key={10} role="presentation" onClick={() => { adminCustomizeContainer.switchGroupSPageListLimitation(10) }}>
  120. <a role="menuitem">10</a>
  121. </DropdownItem>
  122. <DropdownItem key={30} role="presentation" onClick={() => { adminCustomizeContainer.switchGroupSPageListLimitation(30) }}>
  123. <a role="menuitem">30</a>
  124. </DropdownItem>
  125. <DropdownItem key={50} role="presentation" onClick={() => { adminCustomizeContainer.switchGroupSPageListLimitation(50) }}>
  126. <a role="menuitem">50</a>
  127. </DropdownItem>
  128. </DropdownMenu>
  129. </Dropdown>
  130. <p className="form-text text-muted">
  131. {t('admin:customize_setting.function_options.all_list_num_desc_in_page_contents_modal')}
  132. </p>
  133. </div>
  134. </div>
  135. {/* M: User Page */}
  136. <div className="form-group row">
  137. <div className="offset-md-3 col-md-6 text-left">
  138. <div className="my-0 w-100">
  139. <label>{t('admin:customize_setting.function_options.list_num_desc_in_user_page')}</label>
  140. </div>
  141. <Dropdown isOpen={this.state.isDropdownOpen} toggle={this.onToggleDropdown}>
  142. <DropdownToggle className="text-right col-6" caret>
  143. <span className="float-left">{adminCustomizeContainer.state.pageListLimitForUserPage}</span>
  144. </DropdownToggle>
  145. <DropdownMenu className="dropdown-menu" role="menu">
  146. <DropdownItem key={10} role="presentation" onClick={() => { adminCustomizeContainer.switchGroupMPageListLimitation(10) }}>
  147. <a role="menuitem">10</a>
  148. </DropdownItem>
  149. <DropdownItem key={30} role="presentation" onClick={() => { adminCustomizeContainer.switchGroupMPageListLimitation(30) }}>
  150. <a role="menuitem">30</a>
  151. </DropdownItem>
  152. <DropdownItem key={50} role="presentation" onClick={() => { adminCustomizeContainer.switchGroupMPageListLimitation(50) }}>
  153. <a role="menuitem">50</a>
  154. </DropdownItem>
  155. </DropdownMenu>
  156. </Dropdown>
  157. <p className="form-text text-muted">
  158. {t('admin:customize_setting.function_options.all_list_num_desc_in_user_page')}
  159. </p>
  160. </div>
  161. </div>
  162. {/* L: Search / Draft Pages */}
  163. <div className="form-group row">
  164. <div className="offset-md-3 col-md-6 text-left">
  165. <div className="my-0 w-100">
  166. <label>{t('admin:customize_setting.function_options.list_num_desc_in_draft_and_search_pages')}</label>
  167. </div>
  168. <Dropdown isOpen={this.state.isDropdownOpenL} toggle={this.onToggleDropdownL}>
  169. <DropdownToggle className="text-right col-6" caret>
  170. <span className="float-left">{adminCustomizeContainer.state.pageLimitationL}</span>
  171. </DropdownToggle>
  172. <DropdownMenu className="dropdown-menu" role="menu">
  173. <DropdownItem key={10} role="presentation" onClick={() => { adminCustomizeContainer.switchGroupLPageListLimitation(10) }}>
  174. <a role="menuitem">10</a>
  175. </DropdownItem>
  176. <DropdownItem key={30} role="presentation" onClick={() => { adminCustomizeContainer.switchGroupLPageListLimitation(30) }}>
  177. <a role="menuitem">30</a>
  178. </DropdownItem>
  179. <DropdownItem key={50} role="presentation" onClick={() => { adminCustomizeContainer.switchGroupLPageListLimitation(50) }}>
  180. <a role="menuitem">50</a>
  181. </DropdownItem>
  182. </DropdownMenu>
  183. </Dropdown>
  184. <p className="form-text text-muted">
  185. {t('admin:customize_setting.function_options.all_list_num_desc_in_draft_and_search_pages')}
  186. </p>
  187. </div>
  188. </div>
  189. {/* XL: NotFound / Trash Pages */}
  190. <div className="form-group row">
  191. <div className="offset-md-3 col-md-6 text-left">
  192. <div className="my-0 w-100">
  193. <label>{t('admin:customize_setting.function_options.list_num_desc_in_notfound_and_trash_pages')}</label>
  194. </div>
  195. <Dropdown isOpen={this.state.isDropdownOpenXL} toggle={this.onToggleDropdownXL}>
  196. <DropdownToggle className="text-right col-6" caret>
  197. <span className="float-left">{adminCustomizeContainer.state.pageLimitationXL}</span>
  198. </DropdownToggle>
  199. <DropdownMenu className="dropdown-menu" role="menu">
  200. <DropdownItem key={10} role="presentation" onClick={() => { adminCustomizeContainer.switchGroupXLPageListLimitation(10) }}>
  201. <a role="menuitem">10</a>
  202. </DropdownItem>
  203. <DropdownItem key={30} role="presentation" onClick={() => { adminCustomizeContainer.switchGroupXLPageListLimitation(30) }}>
  204. <a role="menuitem">30</a>
  205. </DropdownItem>
  206. <DropdownItem key={50} role="presentation" onClick={() => { adminCustomizeContainer.switchGroupXLPageListLimitation(50) }}>
  207. <a role="menuitem">50</a>
  208. </DropdownItem>
  209. </DropdownMenu>
  210. </Dropdown>
  211. <p className="form-text text-muted">
  212. {t('admin:customize_setting.function_options.all_list_num_desc_in_notfound_and_trash_pages')}
  213. </p>
  214. </div>
  215. </div>
  216. <div className="form-group row">
  217. <div className="offset-md-3 col-md-6 text-left">
  218. <CustomizeFunctionOption
  219. optionId="isEnabledStaleNotification"
  220. label={t('admin:customize_setting.function_options.stale_notification')}
  221. isChecked={adminCustomizeContainer.state.isEnabledStaleNotification}
  222. onChecked={() => { adminCustomizeContainer.switchEnableStaleNotification() }}
  223. >
  224. <p className="form-text text-muted">
  225. {t('admin:customize_setting.function_options.stale_notification_desc')}
  226. </p>
  227. </CustomizeFunctionOption>
  228. </div>
  229. </div>
  230. <div className="form-group row">
  231. <div className="offset-md-3 col-md-6 text-left">
  232. <CustomizeFunctionOption
  233. optionId="isAllReplyShown"
  234. label={t('admin:customize_setting.function_options.show_all_reply_comments')}
  235. isChecked={adminCustomizeContainer.state.isAllReplyShown || false}
  236. onChecked={() => { adminCustomizeContainer.switchIsAllReplyShown() }}
  237. >
  238. <p className="form-text text-muted">
  239. {t('admin:customize_setting.function_options.show_all_reply_comments_desc')}
  240. </p>
  241. </CustomizeFunctionOption>
  242. </div>
  243. </div>
  244. <AdminUpdateButtonRow onClick={this.onClickSubmit} disabled={adminCustomizeContainer.state.retrieveError != null} />
  245. </div>
  246. </div>
  247. </React.Fragment>
  248. );
  249. }
  250. }
  251. const CustomizeFunctionSettingWrapper = withUnstatedContainers(CustomizeFunctionSetting, [AppContainer, AdminCustomizeContainer]);
  252. CustomizeFunctionSetting.propTypes = {
  253. t: PropTypes.func.isRequired, // i18next
  254. appContainer: PropTypes.instanceOf(AppContainer).isRequired,
  255. adminCustomizeContainer: PropTypes.instanceOf(AdminCustomizeContainer).isRequired,
  256. };
  257. export default withTranslation()(CustomizeFunctionSettingWrapper);