|
|
@@ -1,14 +1,11 @@
|
|
|
-import { ReactNode, useCallback, useState } from 'react'
|
|
|
+import { ReactNode, useCallback } from 'react'
|
|
|
import { useTranslation } from 'react-i18next'
|
|
|
import Badge from '@/shared/components/badge'
|
|
|
+import Tooltip from '@/shared/components/tooltip'
|
|
|
import { postJSON } from '@/infrastructure/fetch-json'
|
|
|
import { Button } from 'react-bootstrap'
|
|
|
import getMeta from '@/utils/meta'
|
|
|
|
|
|
-export type UserFeatures = {
|
|
|
- [key: string]: boolean
|
|
|
-}
|
|
|
-
|
|
|
type IntegrationLinkingWidgetProps = {
|
|
|
logo: ReactNode
|
|
|
title: string
|
|
|
@@ -17,6 +14,8 @@ type IntegrationLinkingWidgetProps = {
|
|
|
labsEnabled?: boolean
|
|
|
experimentName: string
|
|
|
setErrorMessage: (message: string) => void
|
|
|
+ optedIn: boolean
|
|
|
+ setOptedIn: (optedIn: boolean) => void
|
|
|
}
|
|
|
|
|
|
export function LabsExperimentWidget({
|
|
|
@@ -27,45 +26,47 @@ export function LabsExperimentWidget({
|
|
|
labsEnabled,
|
|
|
experimentName,
|
|
|
setErrorMessage,
|
|
|
+ optedIn,
|
|
|
+ setOptedIn,
|
|
|
}: IntegrationLinkingWidgetProps) {
|
|
|
const { t } = useTranslation()
|
|
|
- const userFeatures = getMeta('ol-features') as UserFeatures
|
|
|
-
|
|
|
- const [enabled, setEnabled] = useState(() => {
|
|
|
- return userFeatures[experimentName] === true
|
|
|
- })
|
|
|
|
|
|
const experimentsErrorMessage = t(
|
|
|
'we_are_unable_to_opt_you_into_this_experiment'
|
|
|
)
|
|
|
|
|
|
+ const allowedExperiments = getMeta('ol-allowedExperiments')
|
|
|
+ const disabled = !allowedExperiments.includes(experimentName) && !optedIn
|
|
|
+
|
|
|
const handleEnable = useCallback(async () => {
|
|
|
try {
|
|
|
const enablePath = `/labs/participate/experiments/${experimentName}/opt-in`
|
|
|
await postJSON(enablePath)
|
|
|
- setEnabled(true)
|
|
|
+ setOptedIn(true)
|
|
|
} catch (err) {
|
|
|
setErrorMessage(experimentsErrorMessage)
|
|
|
}
|
|
|
- }, [experimentName, setErrorMessage, experimentsErrorMessage])
|
|
|
+ }, [experimentName, setErrorMessage, experimentsErrorMessage, setOptedIn])
|
|
|
|
|
|
const handleDisable = useCallback(async () => {
|
|
|
try {
|
|
|
const disablePath = `/labs/participate/experiments/${experimentName}/opt-out`
|
|
|
await postJSON(disablePath)
|
|
|
- setEnabled(false)
|
|
|
+ setOptedIn(false)
|
|
|
} catch (err) {
|
|
|
setErrorMessage(experimentsErrorMessage)
|
|
|
}
|
|
|
- }, [experimentName, setErrorMessage, experimentsErrorMessage])
|
|
|
+ }, [experimentName, setErrorMessage, experimentsErrorMessage, setOptedIn])
|
|
|
|
|
|
return (
|
|
|
- <div className="labs-experiment-widget-container">
|
|
|
+ <div
|
|
|
+ className={`labs-experiment-widget-container ${disabled ? 'disabled-experiment' : ''}`}
|
|
|
+ >
|
|
|
<div className="p-2">{logo}</div>
|
|
|
<div className="description-container">
|
|
|
<div className="title-row">
|
|
|
<h3 className="h4">{title}</h3>
|
|
|
- {enabled && <Badge bsStyle="info">{t('enabled')}</Badge>}
|
|
|
+ {optedIn && <Badge bsStyle="info">{t('enabled')}</Badge>}
|
|
|
</div>
|
|
|
<p className="small">
|
|
|
{description}{' '}
|
|
|
@@ -76,12 +77,16 @@ export function LabsExperimentWidget({
|
|
|
)}
|
|
|
</p>
|
|
|
</div>
|
|
|
+ {disabled && (
|
|
|
+ <div className="disabled-explanation">{t('experiment_full')}</div>
|
|
|
+ )}
|
|
|
<div>
|
|
|
{labsEnabled && (
|
|
|
<ActionButton
|
|
|
- enabled={enabled}
|
|
|
+ optedIn={optedIn}
|
|
|
handleDisable={handleDisable}
|
|
|
handleEnable={handleEnable}
|
|
|
+ disabled={disabled}
|
|
|
/>
|
|
|
)}
|
|
|
</div>
|
|
|
@@ -90,19 +95,21 @@ export function LabsExperimentWidget({
|
|
|
}
|
|
|
|
|
|
type ActionButtonProps = {
|
|
|
- enabled?: boolean
|
|
|
+ optedIn?: boolean
|
|
|
+ disabled?: boolean
|
|
|
handleEnable: () => void
|
|
|
handleDisable: () => void
|
|
|
}
|
|
|
|
|
|
function ActionButton({
|
|
|
- enabled,
|
|
|
+ optedIn,
|
|
|
+ disabled,
|
|
|
handleEnable,
|
|
|
handleDisable,
|
|
|
}: ActionButtonProps) {
|
|
|
const { t } = useTranslation()
|
|
|
|
|
|
- if (enabled) {
|
|
|
+ if (optedIn) {
|
|
|
return (
|
|
|
<Button
|
|
|
bsStyle="secondary"
|
|
|
@@ -112,6 +119,18 @@ function ActionButton({
|
|
|
{t('turn_off')}
|
|
|
</Button>
|
|
|
)
|
|
|
+ } else if (disabled) {
|
|
|
+ return (
|
|
|
+ <Tooltip
|
|
|
+ id="experiment-disabled"
|
|
|
+ description={t('this_experiment_isnt_accepting_new_participants')}
|
|
|
+ overlayProps={{ delay: 0 }}
|
|
|
+ >
|
|
|
+ <Button bsStyle="secondary" className="btn btn-primary" disabled>
|
|
|
+ {t('turn_on')}
|
|
|
+ </Button>
|
|
|
+ </Tooltip>
|
|
|
+ )
|
|
|
} else {
|
|
|
return (
|
|
|
<Button
|