settings-modal-body.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import MaterialIcon from '@/shared/components/material-icon'
  2. import { Nav, NavLink, TabContainer, TabContent } from 'react-bootstrap'
  3. import { SettingsEntry } from '../context/types'
  4. import SettingsTabPane from './settings-tab-pane'
  5. import BetaBadgeIcon from '@/shared/components/beta-badge-icon'
  6. import OLTooltip from '@/shared/components/ol/ol-tooltip'
  7. import { useTranslation } from 'react-i18next'
  8. export const SettingsModalBody = ({
  9. activeTab,
  10. setActiveTab,
  11. settingsTabs,
  12. }: {
  13. activeTab: string | null | undefined
  14. setActiveTab: (tab: string | null | undefined) => void
  15. settingsTabs: SettingsEntry[]
  16. }) => {
  17. return (
  18. <TabContainer
  19. transition={false}
  20. onSelect={setActiveTab}
  21. activeKey={activeTab ?? undefined}
  22. id="ide-settings-tabs"
  23. >
  24. <div className="d-flex flex-row">
  25. <Nav
  26. activeKey={activeTab ?? undefined}
  27. className="d-flex flex-column ide-settings-tab-nav"
  28. >
  29. {settingsTabs.map(entry => (
  30. <SettingsNavLink entry={entry} key={entry.key} />
  31. ))}
  32. </Nav>
  33. <TabContent className="ide-settings-tab-content">
  34. {settingsTabs
  35. .filter(t => 'sections' in t)
  36. .map(tab => (
  37. <SettingsTabPane tab={tab} key={tab.key} />
  38. ))}
  39. </TabContent>
  40. </div>
  41. </TabContainer>
  42. )
  43. }
  44. const SettingsNavLink = ({ entry }: { entry: SettingsEntry }) => {
  45. const { t } = useTranslation()
  46. if ('href' in entry) {
  47. return (
  48. <a
  49. href={entry.href}
  50. target="_blank"
  51. rel="noopener"
  52. className="ide-settings-tab-link ide-settings-tab-link-anchor"
  53. >
  54. <MaterialIcon
  55. className="ide-settings-tab-link-icon"
  56. type={entry.icon}
  57. unfilled
  58. />
  59. <span>{entry.title}</span>
  60. <div className="flex-grow-1" />
  61. <MaterialIcon
  62. type="open_in_new"
  63. className="ide-settings-tab-link-external"
  64. />
  65. </a>
  66. )
  67. } else {
  68. return (
  69. <>
  70. <NavLink
  71. eventKey={entry.key}
  72. className="ide-settings-tab-link ide-settings-tab-link-button"
  73. key={entry.key}
  74. as="button"
  75. >
  76. <MaterialIcon
  77. className="ide-settings-tab-link-icon"
  78. type={entry.icon}
  79. unfilled
  80. />
  81. <span>{entry.title}</span>
  82. <div className="flex-grow-1" />
  83. {entry.key === 'project_notifications' && (
  84. <OLTooltip
  85. id="project-notifications-beta-badge"
  86. description={t('email_notifications_are_currently_in_beta')}
  87. overlayProps={{ placement: 'right', delay: 100 }}
  88. >
  89. <span>
  90. <BetaBadgeIcon />
  91. </span>
  92. </OLTooltip>
  93. )}
  94. </NavLink>
  95. </>
  96. )
  97. }
  98. }