| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- import { useCallback, useState, ReactNode } from 'react'
- import { useTranslation } from 'react-i18next'
- import OLBadge from '@/features/ui/components/ol/ol-badge'
- import getMeta from '../../../../utils/meta'
- import { sendMB } from '../../../../infrastructure/event-tracking'
- import OLButton from '@/features/ui/components/ol/ol-button'
- import OLModal, {
- OLModalBody,
- OLModalFooter,
- OLModalHeader,
- OLModalTitle,
- } from '@/features/ui/components/ol/ol-modal'
- function trackUpgradeClick(integration: string) {
- sendMB('settings-upgrade-click', { integration })
- }
- function trackLinkingClick(integration: string) {
- sendMB('link-integration-click', { integration, location: 'Settings' })
- }
- type IntegrationLinkingWidgetProps = {
- id: string
- logo: ReactNode
- title: string
- description: string
- helpPath: string
- hasFeature?: boolean
- statusIndicator?: ReactNode
- linked?: boolean
- linkPath: string
- unlinkPath: string
- unlinkConfirmationTitle: string
- unlinkConfirmationText: string
- disabled?: boolean
- }
- export function IntegrationLinkingWidget({
- id,
- logo,
- title,
- description,
- helpPath,
- hasFeature,
- statusIndicator,
- linked,
- linkPath,
- unlinkPath,
- unlinkConfirmationTitle,
- unlinkConfirmationText,
- disabled,
- }: IntegrationLinkingWidgetProps) {
- const { t } = useTranslation()
- const [showModal, setShowModal] = useState(false)
- const handleUnlinkClick = useCallback(() => {
- setShowModal(true)
- }, [])
- const handleModalHide = useCallback(() => {
- setShowModal(false)
- }, [])
- return (
- <div className="settings-widget-container">
- <div>{logo}</div>
- <div className="description-container">
- <div className="title-row">
- <h4 id={id}>{title}</h4>
- {!hasFeature && <OLBadge bg="info">{t('premium_feature')}</OLBadge>}
- </div>
- <p className="small">
- {description}{' '}
- <a
- href={helpPath}
- target="_blank"
- rel="noreferrer"
- aria-label={t('learn_more_about', { integrationName: title })}
- >
- {t('learn_more')}
- </a>
- </p>
- {hasFeature && statusIndicator}
- </div>
- <div>
- <ActionButton
- titleId={id}
- integration={title}
- hasFeature={hasFeature}
- linked={linked}
- handleUnlinkClick={handleUnlinkClick}
- linkPath={linkPath}
- disabled={disabled}
- />
- </div>
- <UnlinkConfirmationModal
- integration={title}
- show={showModal}
- title={unlinkConfirmationTitle}
- content={unlinkConfirmationText}
- unlinkPath={unlinkPath}
- handleHide={handleModalHide}
- />
- </div>
- )
- }
- type ActionButtonProps = {
- integration: string
- hasFeature?: boolean
- linked?: boolean
- handleUnlinkClick: () => void
- linkPath: string
- disabled?: boolean
- titleId: string
- }
- function ActionButton({
- hasFeature,
- linked,
- handleUnlinkClick,
- linkPath,
- disabled,
- integration,
- titleId,
- }: ActionButtonProps) {
- const { t } = useTranslation()
- const linkTextId = `${titleId}-link`
- if (!hasFeature) {
- return (
- <OLButton
- variant="primary"
- href="/user/subscription/plans"
- onClick={() => trackUpgradeClick(integration)}
- aria-labelledby={`${titleId} ${linkTextId}`}
- >
- <span id={linkTextId} className="text-capitalize">
- {t('upgrade')}
- </span>
- </OLButton>
- )
- } else if (linked) {
- return (
- <OLButton
- variant="danger-ghost"
- onClick={handleUnlinkClick}
- disabled={disabled}
- >
- {t('unlink')}
- </OLButton>
- )
- } else {
- return (
- <>
- {disabled ? (
- <OLButton disabled variant="secondary" className="text-capitalize">
- {t('link')}
- </OLButton>
- ) : (
- <OLButton
- variant="secondary"
- href={linkPath}
- className="text-capitalize"
- onClick={() => trackLinkingClick(integration)}
- >
- {t('link')}
- </OLButton>
- )}
- </>
- )
- }
- }
- type UnlinkConfirmModalProps = {
- show: boolean
- title: string
- integration: string
- content: string
- unlinkPath: string
- handleHide: () => void
- }
- function UnlinkConfirmationModal({
- show,
- title,
- integration,
- content,
- unlinkPath,
- handleHide,
- }: UnlinkConfirmModalProps) {
- const { t } = useTranslation()
- const handleCancel = (event: React.MouseEvent<HTMLButtonElement>) => {
- event.preventDefault()
- handleHide()
- }
- const handleConfirm = () => {
- sendMB('unlink-integration-click', {
- integration,
- })
- }
- return (
- <OLModal show={show} onHide={handleHide}>
- <OLModalHeader closeButton>
- <OLModalTitle>{title}</OLModalTitle>
- </OLModalHeader>
- <OLModalBody>
- <p>{content}</p>
- </OLModalBody>
- <OLModalFooter>
- <form action={unlinkPath} method="POST" className="form-inline">
- <input type="hidden" name="_csrf" value={getMeta('ol-csrfToken')} />
- <OLButton variant="secondary" onClick={handleCancel}>
- {t('cancel')}
- </OLButton>
- <OLButton
- type="submit"
- variant="danger-ghost"
- onClick={handleConfirm}
- >
- {t('unlink')}
- </OLButton>
- </form>
- </OLModalFooter>
- </OLModal>
- )
- }
|