MCPcopy Create free account
hub / github.com/bytebase/bytebase / FeatureModal

Function FeatureModal

frontend/src/react/components/ui/feature-modal.tsx:45–178  ·  view source on GitHub ↗
({ open, feature, instance, onOpenChange }: Props)

Source from the content-addressed store, hash-verified

43 * - Required plan equals FREE → trial-for-days line.
44 */
45export function FeatureModal({ open, feature, instance, onOpenChange }: Props) {
46 const { t } = useTranslation();
47 const { showTrial, trialingDays } = useSubscriptionState();
48 const hasPermission = hasWorkspacePermissionV2("bb.settings.set");
49
50 const resolvedFeature = feature ?? PlanFeature.FEATURE_UNSPECIFIED;
51 const instanceMissingLicense = useAppStore((state) =>
52 state.instanceMissingLicense(resolvedFeature, instance)
53 );
54 const requiredPlan = useAppStore((state) =>
55 state.getMinimumRequiredPlan(resolvedFeature)
56 );
57
58 if (!feature) {
59 return null;
60 }
61
62 const featureKey = PlanFeature[feature].split(".").join("-");
63 const title = instanceMissingLicense
64 ? t("subscription.instance-assignment.require-license")
65 : t("subscription.disabled-feature");
66
67 const close = () => onOpenChange(false);
68
69 const confirmLabel = instanceMissingLicense
70 ? t("subscription.instance-assignment.assign-license")
71 : t("common.learn-more");
72
73 const handleConfirm = () => {
74 if (instanceMissingLicense) {
75 void router.push({
76 name: INSTANCE_ROUTE_DASHBOARD,
77 query: {
78 assignLicense: "1",
79 instances: instance?.name,
80 },
81 });
82 } else {
83 void router.push(autoSubscriptionRoute());
84 }
85 close();
86 };
87
88 const requiredPlanLabel = t(
89 `subscription.plan.${planLabel[requiredPlan] ?? "enterprise"}.title`
90 );
91 const startTrialLabel = hasPermission
92 ? t("subscription.trial-for-days", { days: trialingDays })
93 : t("subscription.contact-to-upgrade");
94
95 return (
96 <Dialog open={open} onOpenChange={onOpenChange}>
97 <DialogContent className="max-w-2xl">
98 <div>
99 <div className="flex items-center justify-between border-b pb-2 mb-4">
100 <DialogTitle className="text-base font-medium">{title}</DialogTitle>
101 {/* Vue's BBModal had a built-in X close affordance; the React
102 Dialog primitive does not, so render one explicitly so

Callers

nothing calls this directly

Calls 6

useSubscriptionStateFunction · 0.90
hasWorkspacePermissionV2Function · 0.90
openMethod · 0.80
closeFunction · 0.70
useAppStoreFunction · 0.50
tFunction · 0.50

Tested by

no test coverage detected