AdminNavigation.jsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /* eslint-disable no-multi-spaces */
  2. /* eslint-disable react/jsx-props-no-multi-spaces */
  3. import React from 'react';
  4. import PropTypes from 'prop-types';
  5. import { withTranslation } from 'react-i18next';
  6. import urljoin from 'url-join';
  7. import { pathUtils } from 'growi-commons';
  8. const AdminNavigation = (props) => {
  9. const { t } = props;
  10. const pathname = window.location.pathname;
  11. // eslint-disable-next-line react/prop-types
  12. const MenuLabel = ({ menu }) => {
  13. switch (menu) {
  14. case 'app': return <><i className="icon-fw icon-settings"></i> { t('App Settings') }</>;
  15. case 'security': return <><i className="icon-fw icon-shield"></i> { t('security_settings') }</>;
  16. case 'markdown': return <><i className="icon-fw icon-note"></i> { t('Markdown Settings') }</>;
  17. case 'customize': return <><i className="icon-fw icon-wrench"></i> { t('Customize') }</>;
  18. case 'importer': return <><i className="icon-fw icon-cloud-upload"></i> { t('Import Data') }</>;
  19. case 'export': return <><i className="icon-fw icon-cloud-download"></i> { t('Export Archive Data') }</>;
  20. case 'notification': return <><i className="icon-fw icon-bell"></i> { t('External_Notification')}</>;
  21. case 'slack-integration-legacy': return <><i className="fa fa-slack mr-2"></i> { t('Legacy_Slack_Integration')}</>;
  22. case 'slack-integration': return <><i className="fa fa-slack mr-2"></i> { t('slack_integration') }</>;
  23. case 'users': return <><i className="icon-fw icon-user"></i> { t('User_Management') }</>;
  24. case 'user-groups': return <><i className="icon-fw icon-people"></i> { t('UserGroup Management') }</>;
  25. case 'search': return <><i className="icon-fw icon-magnifier"></i> { t('Full Text Search Management') }</>;
  26. default: return <><i className="icon-fw icon-home"></i> { t('Wiki Management Home Page') }</>;
  27. }
  28. };
  29. const MenuLink = ({
  30. // eslint-disable-next-line react/prop-types
  31. menu, isRoot, isListGroupItems, isActive,
  32. }) => {
  33. const pageTransitionClassName = isListGroupItems
  34. ? 'list-group-item list-group-item-action border-0 round-corner'
  35. : 'dropdown-item px-3 py-2';
  36. return (
  37. <a
  38. href={isRoot ? '/admin' : urljoin('/admin', menu)}
  39. className={`${pageTransitionClassName} ${isActive ? 'active' : ''}`}
  40. >
  41. <MenuLabel menu={menu} />
  42. </a>
  43. );
  44. };
  45. const isActiveMenu = (path) => {
  46. const basisPath = pathUtils.normalizePath(urljoin('/admin', path));
  47. const basisParentPath = pathUtils.addTrailingSlash(basisPath);
  48. return (
  49. pathname === basisPath
  50. || pathname.startsWith(basisParentPath)
  51. );
  52. };
  53. const getListGroupItemOrDropdownItemList = (isListGroupItems) => {
  54. return (
  55. <>
  56. <MenuLink menu="home" isListGroupItems isActive={pathname === '/admin'} isRoot />
  57. <MenuLink menu="app" isListGroupItems isActive={isActiveMenu('/app')} />
  58. <MenuLink menu="security" isListGroupItems isActive={isActiveMenu('/security')} />
  59. <MenuLink menu="markdown" isListGroupItems isActive={isActiveMenu('/markdown')} />
  60. <MenuLink menu="customize" isListGroupItems isActive={isActiveMenu('/customize')} />
  61. <MenuLink menu="importer" isListGroupItems isActive={isActiveMenu('/importer')} />
  62. <MenuLink menu="export" isListGroupItems isActive={isActiveMenu('/export')} />
  63. <MenuLink menu="notification" isListGroupItems isActive={isActiveMenu('/notification') || isActiveMenu('/global-notification')} />
  64. <MenuLink menu="slack-integration" isListGroupItems isActive={isActiveMenu('/slack-integration')} />
  65. <MenuLink menu="slack-integration-legacy" isListGroupItems isActive={isActiveMenu('/slack-integration-legacy')} />
  66. <MenuLink menu="users" isListGroupItems isActive={isActiveMenu('/users')} />
  67. <MenuLink menu="user-groups" isListGroupItems isActive={isActiveMenu('/user-groups')} />
  68. <MenuLink menu="search" isListGroupItems isActive={isActiveMenu('/search')} />
  69. </>
  70. );
  71. };
  72. return (
  73. <React.Fragment>
  74. {/* List group */}
  75. <div className="list-group admin-navigation sticky-top d-none d-lg-block">
  76. {getListGroupItemOrDropdownItemList(true)}
  77. </div>
  78. {/* Dropdown */}
  79. <div className="dropdown d-block d-lg-none mb-5">
  80. <button
  81. className="btn btn-outline-primary btn-lg dropdown-toggle col-12 text-right"
  82. type="button"
  83. id="dropdown-admin-navigation"
  84. data-display="static"
  85. data-toggle="dropdown"
  86. aria-haspopup="true"
  87. aria-expanded="false"
  88. >
  89. <span className="float-left">
  90. {pathname === '/admin' && <MenuLabel menu="home" />}
  91. {isActiveMenu('/app') && <MenuLabel menu="app" />}
  92. {isActiveMenu('/security') && <MenuLabel menu="security" />}
  93. {isActiveMenu('/markdown') && <MenuLabel menu="markdown" />}
  94. {isActiveMenu('/customize') && <MenuLabel menu="customize" />}
  95. {isActiveMenu('/importer') && <MenuLabel menu="importer" />}
  96. {isActiveMenu('/export') && <MenuLabel menu="export" />}
  97. {(isActiveMenu('/notification') || isActiveMenu('/global-notification')) && <MenuLabel menu="notification" />}
  98. {isActiveMenu('/slack-integration') && <MenuLabel menu="slack-integration" />}
  99. {isActiveMenu('/users') && <MenuLabel menu="users" />}
  100. {isActiveMenu('/user-groups') && <MenuLabel menu="user-groups" />}
  101. {isActiveMenu('/search') && <MenuLabel menu="search" />}
  102. </span>
  103. </button>
  104. <div className="dropdown-menu" aria-labelledby="dropdown-admin-navigation">
  105. {getListGroupItemOrDropdownItemList(false)}
  106. </div>
  107. </div>
  108. </React.Fragment>
  109. );
  110. };
  111. AdminNavigation.propTypes = {
  112. t: PropTypes.func.isRequired, // i18next
  113. };
  114. export default withTranslation()(AdminNavigation);