settingsNavigation.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import {cloneElement, Component} from 'react';
  2. import styled from '@emotion/styled';
  3. import * as Sentry from '@sentry/react';
  4. import {NAV_GROUP_LABELS} from 'sentry/components/nav/constants';
  5. import {SecondaryNav} from 'sentry/components/nav/secondary';
  6. import {PrimaryNavGroup} from 'sentry/components/nav/types';
  7. import {space} from 'sentry/styles/space';
  8. import SettingsNavigationGroup from 'sentry/views/settings/components/settingsNavigationGroup';
  9. import SettingsNavigationGroupDeprecated from 'sentry/views/settings/components/settingsNavigationGroupDeprecated';
  10. import type {NavigationProps, NavigationSection} from 'sentry/views/settings/types';
  11. type DefaultProps = {
  12. /**
  13. * Additional navigation configuration driven by hooks
  14. */
  15. hookConfigs: NavigationSection[];
  16. /**
  17. * Additional navigation elements driven from hooks
  18. */
  19. hooks: React.ReactElement[];
  20. /**
  21. * How far from the top of the page should the navigation be when stickied.
  22. */
  23. stickyTop: string;
  24. };
  25. type Props = DefaultProps &
  26. NavigationProps & {
  27. /**
  28. * The configuration for this navigation panel
  29. */
  30. navigationObjects: NavigationSection[];
  31. };
  32. function SettingsSecondaryNavigation({
  33. navigationObjects,
  34. hookConfigs,
  35. hooks,
  36. ...otherProps
  37. }: Props) {
  38. const navWithHooks = navigationObjects.concat(hookConfigs);
  39. return (
  40. <SecondaryNav group={PrimaryNavGroup.SETTINGS}>
  41. <SecondaryNav.Header>
  42. {NAV_GROUP_LABELS[PrimaryNavGroup.SETTINGS]}
  43. </SecondaryNav.Header>
  44. <SecondaryNav.Body>
  45. {navWithHooks.map(config => (
  46. <SettingsNavigationGroup key={config.name} {...otherProps} {...config} />
  47. ))}
  48. {hooks.map((Hook, i) => cloneElement(Hook, {key: `hook-${i}`}))}
  49. </SecondaryNav.Body>
  50. </SecondaryNav>
  51. );
  52. }
  53. class SettingsNavigation extends Component<Props> {
  54. static defaultProps: DefaultProps = {
  55. hooks: [],
  56. hookConfigs: [],
  57. stickyTop: '69px',
  58. };
  59. componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
  60. Sentry.withScope(scope => {
  61. Object.keys(errorInfo).forEach(key => {
  62. // @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
  63. scope.setExtra(key, errorInfo[key]);
  64. });
  65. scope.setExtra('url', window.location.href);
  66. Sentry.captureException(error);
  67. });
  68. }
  69. render() {
  70. const {navigationObjects, hooks, hookConfigs, stickyTop, ...otherProps} = this.props;
  71. const navWithHooks = navigationObjects.concat(hookConfigs);
  72. if (this.props.organization?.features.includes('navigation-sidebar-v2')) {
  73. return (
  74. <SettingsSecondaryNavigation
  75. navigationObjects={navigationObjects}
  76. hooks={hooks}
  77. hookConfigs={hookConfigs}
  78. stickyTop={stickyTop}
  79. {...otherProps}
  80. />
  81. );
  82. }
  83. return (
  84. <PositionStickyWrapper stickyTop={stickyTop}>
  85. {navWithHooks.map(config => (
  86. <SettingsNavigationGroupDeprecated
  87. key={config.name}
  88. {...otherProps}
  89. {...config}
  90. />
  91. ))}
  92. {hooks.map((Hook, i) => cloneElement(Hook, {key: `hook-${i}`}))}
  93. </PositionStickyWrapper>
  94. );
  95. }
  96. }
  97. const PositionStickyWrapper = styled('div')<{stickyTop: string}>`
  98. padding: ${space(4)};
  99. padding-right: ${space(2)};
  100. @media (min-width: ${p => p.theme.breakpoints.small}) {
  101. position: sticky;
  102. top: ${p => p.stickyTop};
  103. overflow: scroll;
  104. -ms-overflow-style: none;
  105. scrollbar-width: none;
  106. &::-webkit-scrollbar {
  107. display: none;
  108. }
  109. }
  110. `;
  111. export default SettingsNavigation;