UISettings.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import { useCallback } from 'react';
  2. import { useTranslation } from 'react-i18next';
  3. import { UncontrolledTooltip } from 'reactstrap';
  4. import { updateUserUISettings } from '~/client/services/user-ui-settings';
  5. import { toastError, toastSuccess } from '~/client/util/toastr';
  6. import { useCollapsedContentsOpened, usePreferCollapsedMode, useSidebarMode } from '~/stores/ui';
  7. import styles from './UISettings.module.scss';
  8. const IconWithTooltip = ({
  9. id, label, children, additionalClasses,
  10. }: {
  11. id: string,
  12. label: string,
  13. children: JSX.Element,
  14. additionalClasses: string
  15. }) => (
  16. <>
  17. <div id={id} className={`${additionalClasses != null ? additionalClasses : ''}`}>{children}</div>
  18. <UncontrolledTooltip placement="bottom" fade={false} target={id}>{label}</UncontrolledTooltip>
  19. </>
  20. );
  21. export const UISettings = (): JSX.Element => {
  22. const { t } = useTranslation();
  23. const {
  24. isDockMode, isCollapsedMode,
  25. } = useSidebarMode();
  26. const { mutate: mutatePreferCollapsedMode } = usePreferCollapsedMode();
  27. const { mutate: mutateCollapsedContentsOpened } = useCollapsedContentsOpened();
  28. const toggleCollapsed = useCallback(() => {
  29. mutatePreferCollapsedMode(!isCollapsedMode());
  30. mutateCollapsedContentsOpened(false);
  31. }, [mutatePreferCollapsedMode, isCollapsedMode, mutateCollapsedContentsOpened]);
  32. const updateButtonHandler = useCallback(async() => {
  33. try {
  34. await updateUserUISettings({ preferCollapsedModeByUser: isCollapsedMode() });
  35. toastSuccess(t('toaster.update_successed', { target: t('ui_settings.side_bar_mode.settings'), ns: 'commons' }));
  36. }
  37. catch (err) {
  38. toastError(err);
  39. }
  40. }, [isCollapsedMode, t]);
  41. const renderSidebarModeSwitch = () => {
  42. return (
  43. <>
  44. <div className="d-flex align-items-start">
  45. <div className="d-flex align-items-center">
  46. <IconWithTooltip
  47. id="iwt-sidebar-collapsed"
  48. label="Collapsed"
  49. additionalClasses={styles['grw-sidebar-mode-icon']}
  50. >
  51. <span className="growi-custom-icons fs-6">sidebar-collapsed</span>
  52. </IconWithTooltip>
  53. <div className="form-check form-switch ms-1">
  54. <input
  55. id="swSidebarMode"
  56. className="form-check-input"
  57. type="checkbox"
  58. checked={isDockMode()}
  59. onChange={toggleCollapsed}
  60. />
  61. <label className="form-label form-check-label" htmlFor="swSidebarMode"></label>
  62. </div>
  63. <IconWithTooltip id="iwt-sidebar-dock" label="Dock" additionalClasses={styles['grw-sidebar-mode-icon']}>
  64. <span className="growi-custom-icons fs-6">sidebar-dock</span>
  65. </IconWithTooltip>
  66. </div>
  67. <div className="ms-2">
  68. <label className="form-label form-check-label" htmlFor="swSidebarMode">
  69. {t('ui_settings.side_bar_mode.side_bar_mode_setting')}
  70. </label>
  71. </div>
  72. </div>
  73. <p className="form-text text-muted small">{t('ui_settings.side_bar_mode.description')}</p>
  74. </>
  75. );
  76. };
  77. return (
  78. <>
  79. <h2 className="border-bottom pb- mb-4 fs-4">{t('ui_settings.ui_settings')}</h2>
  80. <div className="row justify-content-center">
  81. <div className="col-md-6">
  82. { renderSidebarModeSwitch() }
  83. <div>
  84. </div>
  85. </div>
  86. </div>
  87. <div className="row my-3">
  88. <div className="offset-4 col-5">
  89. <button data-testid="" type="button" className="btn btn-primary" onClick={updateButtonHandler}>
  90. {t('Update')}
  91. </button>
  92. </div>
  93. </div>
  94. </>
  95. );
  96. };