labs-experiments-widget.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import { ReactNode, useCallback } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import OLBadge from '@/shared/components/ol/ol-badge'
  4. import { postJSON } from '@/infrastructure/fetch-json'
  5. import OLButton from '@/shared/components/ol/ol-button'
  6. import getMeta from '@/utils/meta'
  7. import Notification from '../notification'
  8. import { LabsEnableButton } from '@/shared/components/labs/labs-enable-button'
  9. export type LabsExperimentWidgetProps = {
  10. logo: ReactNode
  11. title: string
  12. description: string | ReactNode
  13. optedInDescription?: string | ReactNode
  14. helpPath?: string
  15. labsEnabled?: boolean
  16. experimentName: string
  17. setErrorMessage: (message: string) => void
  18. optedIn: boolean
  19. setOptedIn: (optedIn: boolean) => void
  20. feedbackLink?: string
  21. }
  22. /** @knipignore */
  23. export function LabsExperimentWidget({
  24. logo,
  25. title,
  26. description,
  27. optedInDescription,
  28. helpPath,
  29. labsEnabled,
  30. experimentName,
  31. setErrorMessage,
  32. optedIn,
  33. setOptedIn,
  34. feedbackLink,
  35. }: LabsExperimentWidgetProps) {
  36. const { t } = useTranslation()
  37. const experimentsErrorMessage = t(
  38. 'we_are_unable_to_opt_you_into_this_experiment'
  39. )
  40. const allowedExperiments = getMeta('ol-allowedExperiments')
  41. const disabled = !allowedExperiments.includes(experimentName) && !optedIn
  42. const handleEnable = useCallback(async () => {
  43. try {
  44. const enablePath = `/labs/participate/experiments/${experimentName}/opt-in`
  45. await postJSON(enablePath)
  46. setOptedIn(true)
  47. } catch (err) {
  48. setErrorMessage(experimentsErrorMessage)
  49. }
  50. }, [experimentName, setErrorMessage, experimentsErrorMessage, setOptedIn])
  51. const handleDisable = useCallback(async () => {
  52. try {
  53. const disablePath = `/labs/participate/experiments/${experimentName}/opt-out`
  54. await postJSON(disablePath)
  55. setOptedIn(false)
  56. } catch (err) {
  57. setErrorMessage(experimentsErrorMessage)
  58. }
  59. }, [experimentName, setErrorMessage, experimentsErrorMessage, setOptedIn])
  60. return (
  61. <div
  62. className={`labs-experiment-widget-container ${disabled ? 'disabled-experiment' : ''}`}
  63. >
  64. <div className="experiment-logo-container">{logo}</div>
  65. <div className="description-container">
  66. <div className="title-row">
  67. <h3 className="h4">{title}</h3>
  68. {optedIn && <OLBadge bg="info">{t('enabled')}</OLBadge>}
  69. </div>
  70. <div className="small">
  71. {optedIn && optedInDescription ? optedInDescription : description}{' '}
  72. {helpPath && (
  73. <a href={helpPath} target="_blank" rel="noreferrer">
  74. {t('learn_more')}
  75. </a>
  76. )}
  77. </div>
  78. </div>
  79. <div>
  80. {optedIn && feedbackLink && (
  81. <OLButton
  82. variant="ghost"
  83. href={feedbackLink}
  84. target="_blank"
  85. rel="noreferrer"
  86. >
  87. {t('give_feedback')}
  88. </OLButton>
  89. )}
  90. </div>
  91. <div>
  92. {labsEnabled && (
  93. <LabsEnableButton
  94. optedIn={optedIn}
  95. disabled={disabled}
  96. handleEnable={handleEnable}
  97. handleDisable={handleDisable}
  98. />
  99. )}
  100. </div>
  101. {disabled && (
  102. <>
  103. <div />
  104. <Notification
  105. type="info"
  106. content={t('experiment_full_check_back_soon')}
  107. />
  108. <div />
  109. <div />
  110. </>
  111. )}
  112. </div>
  113. )
  114. }
  115. export default LabsExperimentWidget