AdminNavigation.jsx 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /* eslint-disable no-multi-spaces */
  2. /* eslint-disable react/jsx-props-no-multi-spaces */
  3. import React, { useEffect } from 'react';
  4. import PropTypes from 'prop-types';
  5. import { withTranslation } from 'react-i18next';
  6. import urljoin from 'url-join';
  7. import loggerFactory from '@alias/logger';
  8. import AdminHomeContainer from '../../../services/AdminHomeContainer';
  9. import { withUnstatedContainers } from '../../UnstatedUtils';
  10. import { toastError } from '../../../util/apiNotification';
  11. const logger = loggerFactory('growi:admin');
  12. const AdminNavigation = (props) => {
  13. const { t, adminHomeContainer } = props;
  14. const pathname = window.location.pathname;
  15. useEffect(() => {
  16. (async() => {
  17. try {
  18. await adminHomeContainer.retrieveAdminHomeData();
  19. }
  20. catch (err) {
  21. toastError(err);
  22. adminHomeContainer.setState({ retrieveError: err });
  23. logger.error(err);
  24. }
  25. })();
  26. }, [adminHomeContainer]);
  27. // eslint-disable-next-line react/prop-types
  28. const MenuLabel = ({ menu }) => {
  29. switch (menu) {
  30. case 'app': return <><i className="icon-fw icon-settings"></i> { t('App Settings') }</>;
  31. case 'security': return <><i className="icon-fw icon-shield"></i> { t('security_settings') }</>;
  32. case 'markdown': return <><i className="icon-fw icon-note"></i> { t('Markdown Settings') }</>;
  33. case 'customize': return <><i className="icon-fw icon-wrench"></i> { t('Customize') }</>;
  34. case 'importer': return <><i className="icon-fw icon-cloud-upload"></i> { t('Import Data') }</>;
  35. case 'export': return <><i className="icon-fw icon-cloud-download"></i> { t('Export Archive Data') }</>;
  36. case 'notification': return <><i className="icon-fw icon-bell"></i> { t('Notification Settings') }</>;
  37. case 'users': return <><i className="icon-fw icon-user"></i> { t('User_Management') }</>;
  38. case 'user-groups': return <><i className="icon-fw icon-people"></i> { t('UserGroup Management') }</>;
  39. case 'search': return <><i className="icon-fw icon-magnifier"></i> { t('Full Text Search Management') }</>;
  40. case 'cloud': return <><i className="icon-fw icon-share-alt"></i> { t('to_cloud_settings')} </>;
  41. default: return <><i className="icon-fw icon-home"></i> { t('Wiki Management Home Page') }</>;
  42. }
  43. };
  44. const MenuLink = ({
  45. // eslint-disable-next-line react/prop-types
  46. menu, isRoot, isListGroupItems, isActive,
  47. }) => {
  48. const pageTransitionClassName = isListGroupItems
  49. ? 'list-group-item list-group-item-action border-0 round-corner'
  50. : 'dropdown-item px-3 py-2';
  51. return (
  52. <a
  53. href={isRoot ? '/admin' : urljoin('/admin', menu)}
  54. className={`${pageTransitionClassName} ${isActive ? 'active' : ''}`}
  55. >
  56. <MenuLabel menu={menu} />
  57. </a>
  58. );
  59. };
  60. const isActiveMenu = (path) => {
  61. return (pathname.startsWith(urljoin('/admin', path)));
  62. };
  63. const getListGroupItemOrDropdownItemList = (isListGroupItems) => {
  64. return (
  65. <>
  66. <MenuLink menu="home" isListGroupItems isActive={pathname === '/admin'} isRoot />
  67. <MenuLink menu="app" isListGroupItems isActive={isActiveMenu('/app')} />
  68. <MenuLink menu="security" isListGroupItems isActive={isActiveMenu('/security')} />
  69. <MenuLink menu="markdown" isListGroupItems isActive={isActiveMenu('/markdown')} />
  70. <MenuLink menu="customize" isListGroupItems isActive={isActiveMenu('/customize')} />
  71. <MenuLink menu="importer" isListGroupItems isActive={isActiveMenu('/importer')} />
  72. <MenuLink menu="export" isListGroupItems isActive={isActiveMenu('/export')} />
  73. <MenuLink menu="notification" isListGroupItems isActive={isActiveMenu('/notification') || isActiveMenu('/global-notification')} />
  74. <MenuLink menu="users" isListGroupItems isActive={isActiveMenu('/users')} />
  75. <MenuLink menu="user-groups" isListGroupItems isActive={isActiveMenu('/user-groups')} />
  76. <MenuLink menu="search" isListGroupItems isActive={isActiveMenu('/search')} />
  77. {adminHomeContainer.state.envVars?.GROWI_CLOUD_URI != null
  78. && adminHomeContainer.state.envVars?.GROWI_APP_ID_FOR_GROWI_CLOUD != null
  79. && (
  80. <a
  81. href={`${adminHomeContainer.state.envVars?.GROWI_CLOUD_URI}/my/apps/${adminHomeContainer.state.envVars?.GROWI_APP_ID_FOR_GROWI_CLOUD}`}
  82. className="list-group-item list-group-item-action border-0 round-corner"
  83. >
  84. <MenuLabel menu="cloud" />
  85. </a>
  86. )}
  87. </>
  88. );
  89. };
  90. return (
  91. <React.Fragment>
  92. {/* List group */}
  93. <div className="list-group admin-navigation sticky-top d-none d-lg-block">
  94. {getListGroupItemOrDropdownItemList(true)}
  95. </div>
  96. {/* Dropdown */}
  97. <div className="dropdown d-block d-lg-none mb-5">
  98. <button
  99. className="btn btn-outline-primary btn-lg dropdown-toggle col-12 text-right"
  100. type="button"
  101. id="dropdown-admin-navigation"
  102. data-display="static"
  103. data-toggle="dropdown"
  104. aria-haspopup="true"
  105. aria-expanded="false"
  106. >
  107. <span className="float-left">
  108. {pathname === '/admin' && <MenuLabel menu="home" />}
  109. {isActiveMenu('/app') && <MenuLabel menu="app" />}
  110. {isActiveMenu('/security') && <MenuLabel menu="security" />}
  111. {isActiveMenu('/markdown') && <MenuLabel menu="markdown" />}
  112. {isActiveMenu('/customize') && <MenuLabel menu="customize" />}
  113. {isActiveMenu('/importer') && <MenuLabel menu="importer" />}
  114. {isActiveMenu('/export') && <MenuLabel menu="export" />}
  115. {(isActiveMenu('/notification') || isActiveMenu('/global-notification')) && <MenuLabel menu="notification" />}
  116. {isActiveMenu('/users') && <MenuLabel menu="users" />}
  117. {isActiveMenu('/user-groups') && <MenuLabel menu="user-groups" />}
  118. {isActiveMenu('/search') && <MenuLabel menu="search" />}
  119. </span>
  120. </button>
  121. <div className="dropdown-menu" aria-labelledby="dropdown-admin-navigation">
  122. {getListGroupItemOrDropdownItemList(false)}
  123. </div>
  124. </div>
  125. </React.Fragment>
  126. );
  127. };
  128. const AdminNavigationWrapper = withUnstatedContainers(AdminNavigation, [AdminHomeContainer]);
  129. AdminNavigation.propTypes = {
  130. t: PropTypes.func.isRequired, // i18next
  131. adminHomeContainer: PropTypes.instanceOf(AdminHomeContainer).isRequired,
  132. };
  133. export default withTranslation()(AdminNavigationWrapper);