Skip to content

Commit 8e2b816

Browse files
refactor(web): migrate HITL overlays to base dialog (#35792)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 1f29565 commit 8e2b816

32 files changed

Lines changed: 920 additions & 759 deletions

File tree

eslint-suppressions.json

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1969,11 +1969,6 @@
19691969
"count": 4
19701970
}
19711971
},
1972-
"web/app/components/billing/plan-upgrade-modal/index.tsx": {
1973-
"no-restricted-imports": {
1974-
"count": 1
1975-
}
1976-
},
19771972
"web/app/components/billing/plan/assets/index.tsx": {
19781973
"no-barrel-files/no-barrel-files": {
19791974
"count": 4
@@ -4195,37 +4190,6 @@
41954190
"count": 5
41964191
}
41974192
},
4198-
"web/app/components/workflow/nodes/human-input/components/delivery-method/email-configure-modal.tsx": {
4199-
"no-restricted-imports": {
4200-
"count": 1
4201-
}
4202-
},
4203-
"web/app/components/workflow/nodes/human-input/components/delivery-method/method-item.tsx": {
4204-
"no-restricted-imports": {
4205-
"count": 1
4206-
}
4207-
},
4208-
"web/app/components/workflow/nodes/human-input/components/delivery-method/method-selector.tsx": {
4209-
"no-restricted-imports": {
4210-
"count": 1
4211-
}
4212-
},
4213-
"web/app/components/workflow/nodes/human-input/components/delivery-method/test-email-sender.tsx": {
4214-
"no-restricted-imports": {
4215-
"count": 1
4216-
},
4217-
"ts/no-explicit-any": {
4218-
"count": 2
4219-
},
4220-
"ts/no-non-null-asserted-optional-chain": {
4221-
"count": 1
4222-
}
4223-
},
4224-
"web/app/components/workflow/nodes/human-input/components/delivery-method/upgrade-modal.tsx": {
4225-
"no-restricted-imports": {
4226-
"count": 1
4227-
}
4228-
},
42294193
"web/app/components/workflow/nodes/human-input/components/form-content-preview.tsx": {
42304194
"react/unsupported-syntax": {
42314195
"count": 1
@@ -4250,11 +4214,6 @@
42504214
"count": 2
42514215
}
42524216
},
4253-
"web/app/components/workflow/nodes/human-input/panel.tsx": {
4254-
"no-restricted-imports": {
4255-
"count": 1
4256-
}
4257-
},
42584217
"web/app/components/workflow/nodes/human-input/types.ts": {
42594218
"erasable-syntax-only/enums": {
42604219
"count": 2
@@ -5284,21 +5243,6 @@
52845243
"count": 3
52855244
}
52865245
},
5287-
"web/context/modal-context-provider.tsx": {
5288-
"ts/no-explicit-any": {
5289-
"count": 3
5290-
}
5291-
},
5292-
"web/context/modal-context.test.tsx": {
5293-
"ts/no-explicit-any": {
5294-
"count": 5
5295-
}
5296-
},
5297-
"web/context/modal-context.ts": {
5298-
"ts/no-explicit-any": {
5299-
"count": 2
5300-
}
5301-
},
53025246
"web/context/provider-context-provider.tsx": {
53035247
"ts/no-explicit-any": {
53045248
"count": 1

web/__tests__/billing/billing-integration.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Billing from '@/app/components/billing/billing-page'
99
import { defaultPlan, NUM_INFINITE } from '@/app/components/billing/config'
1010
import HeaderBillingBtn from '@/app/components/billing/header-billing-btn'
1111
import PlanComp from '@/app/components/billing/plan'
12-
import PlanUpgradeModal from '@/app/components/billing/plan-upgrade-modal'
12+
import { PlanUpgradeModal } from '@/app/components/billing/plan-upgrade-modal'
1313
import PriorityLabel from '@/app/components/billing/priority-label'
1414
import TriggerEventsLimitModal from '@/app/components/billing/trigger-events-limit-modal'
1515
import { Plan } from '@/app/components/billing/type'
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
'use client'
2+
3+
import type { ComponentType, ReactNode } from 'react'
4+
import { cn } from '@langgenius/dify-ui/cn'
5+
import { Dialog, DialogContent, DialogDescription, DialogTitle } from '@langgenius/dify-ui/dialog'
6+
import styles from './style.module.css'
7+
8+
type UpgradeModalClassNames = {
9+
content?: string
10+
heroOverlay?: string
11+
body?: string
12+
icon?: string
13+
copy?: string
14+
title?: string
15+
description?: string
16+
footer?: string
17+
}
18+
19+
type UpgradeModalProps = {
20+
open: boolean
21+
onOpenChange?: (open: boolean) => void
22+
Icon?: ComponentType<{ className?: string }>
23+
title: ReactNode
24+
description: ReactNode
25+
extraInfo?: ReactNode
26+
footer: ReactNode
27+
classNames?: UpgradeModalClassNames
28+
}
29+
30+
export function UpgradeModal({
31+
open,
32+
onOpenChange,
33+
Icon,
34+
title,
35+
description,
36+
extraInfo,
37+
footer,
38+
classNames,
39+
}: UpgradeModalProps) {
40+
return (
41+
<Dialog
42+
open={open}
43+
onOpenChange={onOpenChange}
44+
>
45+
<DialogContent className={cn(styles.surface, 'w-[580px] max-w-[480px] overflow-hidden rounded-2xl p-0', classNames?.content)}>
46+
<div className="relative">
47+
<div
48+
aria-hidden
49+
className={cn(styles.heroOverlay, 'pointer-events-none absolute inset-0', classNames?.heroOverlay)}
50+
/>
51+
<div className={cn('px-8 pt-8', classNames?.body)}>
52+
{Icon && (
53+
<div className={cn(styles.icon, 'flex size-12 items-center justify-center rounded-xl shadow-lg backdrop-blur-[5px]', classNames?.icon)}>
54+
<Icon className="size-6 text-text-primary-on-surface" />
55+
</div>
56+
)}
57+
<div className={cn('mt-6 space-y-2', classNames?.copy)}>
58+
<DialogTitle className={cn(styles.highlight, 'title-3xl-semi-bold', classNames?.title)}>
59+
{title}
60+
</DialogTitle>
61+
<DialogDescription className={cn('system-md-regular text-text-tertiary', classNames?.description)}>
62+
{description}
63+
</DialogDescription>
64+
</div>
65+
{extraInfo}
66+
</div>
67+
</div>
68+
69+
<div className={cn('mt-10 mb-8 flex justify-end space-x-2 px-8', classNames?.footer)}>
70+
{footer}
71+
</div>
72+
</DialogContent>
73+
</Dialog>
74+
)
75+
}

web/app/components/billing/plan-upgrade-modal/style.module.css renamed to web/app/components/base/upgrade-modal/style.module.css

File renamed without changes.

web/app/components/billing/plan-upgrade-modal/__tests__/index.spec.tsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,9 @@
11
import { render, screen } from '@testing-library/react'
22
import userEvent from '@testing-library/user-event'
3-
import * as React from 'react'
4-
import PlanUpgradeModal from '../index'
3+
import { PlanUpgradeModal } from '../index'
54

65
const mockSetShowPricingModal = vi.fn()
76

8-
vi.mock('@/app/components/base/modal', () => {
9-
const MockModal = ({ isShow, children }: { isShow: boolean, children: React.ReactNode }) => (
10-
isShow ? <div data-testid="plan-upgrade-modal">{children}</div> : null
11-
)
12-
return {
13-
default: MockModal,
14-
}
15-
})
16-
177
vi.mock('@/context/modal-context', () => ({
188
useModalContext: () => ({
199
setShowPricingModal: mockSetShowPricingModal,
@@ -70,6 +60,16 @@ describe('PlanUpgradeModal', () => {
7060
expect(onClose).toHaveBeenCalledTimes(1)
7161
})
7262

63+
it('should call onClose when dialog requests close', async () => {
64+
const user = userEvent.setup()
65+
const onClose = vi.fn()
66+
renderComponent({ onClose })
67+
68+
await user.keyboard('{Escape}')
69+
70+
expect(onClose).toHaveBeenCalledTimes(1)
71+
})
72+
7373
// Upgrade path uses provided callback over pricing modal
7474
it('should call onUpgrade and onClose when upgrade button is clicked with onUpgrade provided', async () => {
7575
const user = userEvent.setup()
Lines changed: 31 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,32 @@
11
'use client'
2-
import type { FC } from 'react'
2+
import type { ComponentType, ReactNode } from 'react'
33
import { Button } from '@langgenius/dify-ui/button'
4-
import * as React from 'react'
54
import { useCallback } from 'react'
65
import { useTranslation } from 'react-i18next'
7-
import Modal from '@/app/components/base/modal'
6+
import { UpgradeModal } from '@/app/components/base/upgrade-modal'
87
import UpgradeBtn from '@/app/components/billing/upgrade-btn'
98
import { useModalContext } from '@/context/modal-context'
109
import { SquareChecklist } from '../../base/icons/src/vender/other'
11-
import styles from './style.module.css'
1210

1311
type Props = {
14-
Icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>
12+
Icon?: ComponentType<{ className?: string }>
1513
title: string
1614
description: string
17-
extraInfo?: React.ReactNode
15+
extraInfo?: ReactNode
1816
show: boolean
1917
onClose: () => void
2018
onUpgrade?: () => void
2119
}
2220

23-
const PlanUpgradeModal: FC<Props> = ({
21+
export function PlanUpgradeModal({
2422
Icon = SquareChecklist,
2523
title,
2624
description,
2725
extraInfo,
2826
show,
2927
onClose,
3028
onUpgrade,
31-
}) => {
29+
}: Props) {
3230
const { t } = useTranslation()
3331
const { setShowPricingModal } = useModalContext()
3432

@@ -41,51 +39,30 @@ const PlanUpgradeModal: FC<Props> = ({
4139
}, [onClose, onUpgrade, setShowPricingModal])
4240

4341
return (
44-
<Modal
45-
isShow={show}
46-
onClose={onClose}
47-
closable={false}
48-
clickOutsideNotClose
49-
className={`${styles.surface} w-[580px] rounded-2xl p-0!`}
50-
>
51-
<div className="relative">
52-
<div
53-
aria-hidden
54-
className={`${styles.heroOverlay} pointer-events-none absolute inset-0`}
55-
/>
56-
<div className="px-8 pt-8">
57-
<div className={`${styles.icon} flex size-12 items-center justify-center rounded-xl shadow-lg backdrop-blur-[5px]`}>
58-
<Icon className="size-6 text-text-primary-on-surface" />
59-
</div>
60-
<div className="mt-6 space-y-2">
61-
<div className={`${styles.highlight} title-3xl-semi-bold`}>
62-
{title}
63-
</div>
64-
<div className="system-md-regular text-text-tertiary">
65-
{description}
66-
</div>
67-
</div>
68-
{extraInfo}
69-
</div>
70-
</div>
71-
72-
<div className="mt-10 mb-8 flex justify-end space-x-2 px-8">
73-
<Button
74-
onClick={onClose}
75-
>
76-
{t('triggerLimitModal.dismiss', { ns: 'billing' })}
77-
</Button>
78-
<UpgradeBtn
79-
size="custom"
80-
isShort
81-
onClick={handleUpgrade}
82-
className="h-8! rounded-lg! px-2"
83-
labelKey="triggerLimitModal.upgrade"
84-
loc="trigger-events-limit-modal"
85-
/>
86-
</div>
87-
</Modal>
42+
<UpgradeModal
43+
open={show}
44+
onOpenChange={open => !open && onClose()}
45+
Icon={Icon}
46+
title={title}
47+
description={description}
48+
extraInfo={extraInfo}
49+
footer={(
50+
<>
51+
<Button
52+
onClick={onClose}
53+
>
54+
{t('triggerLimitModal.dismiss', { ns: 'billing' })}
55+
</Button>
56+
<UpgradeBtn
57+
size="custom"
58+
isShort
59+
onClick={handleUpgrade}
60+
className="h-8! rounded-lg! px-2"
61+
labelKey="triggerLimitModal.upgrade"
62+
loc="trigger-events-limit-modal"
63+
/>
64+
</>
65+
)}
66+
/>
8867
)
8968
}
90-
91-
export default React.memo(PlanUpgradeModal)

0 commit comments

Comments
 (0)