Skip to content

Commit 12f7507

Browse files
add temporary refresh license button
1 parent 420d441 commit 12f7507

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

packages/web/src/app/(app)/settings/license/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { OrgRole } from "@sourcebot/db";
33
import { ActivationCodeCard } from "./activationCodeCard";
44
import { PurchaseButton } from "./purchaseButton";
55
import { ManageSubscriptionButton } from "./manageSubscriptionButton";
6+
import { RefreshLicenseButton } from "./refreshLicenseButton";
67
import { SettingsCard } from "../components/settingsCard";
78
import { getEntitlements } from "@/lib/entitlements";
89

@@ -26,6 +27,7 @@ export default authenticatedPage(async ({ prisma, org }) => {
2627
<div className="flex gap-3">
2728
<PurchaseButton />
2829
{license && <ManageSubscriptionButton />}
30+
{license && <RefreshLicenseButton />}
2931
</div>
3032
</div>
3133
);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"use client";
2+
3+
import { useState, useCallback } from "react";
4+
import { LoadingButton } from "@/components/ui/loading-button";
5+
import { refreshLicense } from "@/ee/features/lighthouse/actions";
6+
import { isServiceError } from "@/lib/utils";
7+
import { useToast } from "@/components/hooks/use-toast";
8+
import { useRouter } from "next/navigation";
9+
10+
export function RefreshLicenseButton() {
11+
const [isLoading, setIsLoading] = useState(false);
12+
const { toast } = useToast();
13+
const router = useRouter();
14+
15+
const handleClick = useCallback(() => {
16+
setIsLoading(true);
17+
18+
refreshLicense()
19+
.then((response) => {
20+
if (isServiceError(response)) {
21+
toast({
22+
description: `Failed to refresh license: ${response.message}`,
23+
variant: "destructive",
24+
});
25+
} else {
26+
toast({
27+
description: "License refreshed successfully.",
28+
});
29+
router.refresh();
30+
}
31+
})
32+
.finally(() => {
33+
setIsLoading(false);
34+
});
35+
}, [router, toast]);
36+
37+
return (
38+
<LoadingButton
39+
variant="outline"
40+
onClick={handleClick}
41+
loading={isLoading}
42+
>
43+
Refresh license
44+
</LoadingButton>
45+
);
46+
}

packages/web/src/ee/features/lighthouse/actions.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,36 @@ export const activateLicense = async (activationCode: string): Promise<{ success
5656
)
5757
);
5858

59+
export const refreshLicense = async (): Promise<{ success: boolean } | ServiceError> => sew(() =>
60+
withAuth(async ({ org, role, prisma }) =>
61+
withMinimumOrgRole(role, OrgRole.OWNER, async () => {
62+
const existing = await prisma.license.findUnique({
63+
where: { orgId: org.id },
64+
});
65+
66+
if (!existing) {
67+
return {
68+
statusCode: StatusCodes.NOT_FOUND,
69+
errorCode: ErrorCode.NOT_FOUND,
70+
message: "No license found.",
71+
} satisfies ServiceError;
72+
}
73+
74+
try {
75+
await syncWithLighthouse(org.id);
76+
} catch {
77+
return {
78+
statusCode: StatusCodes.BAD_GATEWAY,
79+
errorCode: ErrorCode.UNEXPECTED_ERROR,
80+
message: "Failed to refresh license. Please try again.",
81+
} satisfies ServiceError;
82+
}
83+
84+
return { success: true };
85+
})
86+
)
87+
);
88+
5989
export const createCheckoutSession = async (successUrl: string, cancelUrl: string): Promise<{ url: string } | ServiceError> => sew(() =>
6090
withAuth(async ({ user, org, role, prisma }) =>
6191
withMinimumOrgRole(role, OrgRole.OWNER, async () => {

0 commit comments

Comments
 (0)