Skip to content

Commit 292f619

Browse files
committed
Add manual refresh to licenses page
1 parent eea56da commit 292f619

File tree

5 files changed

+72
-12
lines changed

5 files changed

+72
-12
lines changed

site/src/api/api.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,10 @@ export const putWorkspaceExtension = async (
808808
})
809809
}
810810

811+
export const refreshEntitlements = async (): Promise<void> => {
812+
await axios.post("/api/v2/licenses/refresh-entitlements")
813+
}
814+
811815
export const getEntitlements = async (): Promise<TypesGen.Entitlements> => {
812816
try {
813817
const response = await axios.get("/api/v2/entitlements")

site/src/pages/DeploySettingsPage/LicensesSettingsPage/LicensesSettingsPage.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,20 @@ import useToggle from "react-use/lib/useToggle"
99
import { pageTitle } from "utils/page"
1010
import { entitlementsMachine } from "xServices/entitlements/entitlementsXService"
1111
import LicensesSettingsPageView from "./LicensesSettingsPageView"
12+
import { getErrorMessage } from "api/errors"
1213

1314
const LicensesSettingsPage: FC = () => {
1415
const queryClient = useQueryClient()
15-
const [entitlementsState] = useMachine(entitlementsMachine)
16-
const { entitlements } = entitlementsState.context
16+
const [entitlementsState, sendEvent] = useMachine(entitlementsMachine)
17+
const { entitlements, getEntitlementsError } = entitlementsState.context
1718
const [searchParams, setSearchParams] = useSearchParams()
1819
const success = searchParams.get("success")
1920
const [confettiOn, toggleConfettiOn] = useToggle(false)
21+
if (getEntitlementsError) {
22+
displayError(
23+
getErrorMessage(getEntitlementsError, "Failed to fetch entitlements"),
24+
)
25+
}
2026

2127
const { mutate: removeLicenseApi, isLoading: isRemovingLicense } =
2228
useMutation(removeLicense, {
@@ -58,6 +64,10 @@ const LicensesSettingsPage: FC = () => {
5864
licenses={licenses}
5965
isRemovingLicense={isRemovingLicense}
6066
removeLicense={(licenseId: number) => removeLicenseApi(licenseId)}
67+
refreshEntitlements={() => {
68+
const x = sendEvent("REFRESH")
69+
return !x.context.getEntitlementsError
70+
}}
6171
/>
6272
</>
6373
)

site/src/pages/DeploySettingsPage/LicensesSettingsPage/LicensesSettingsPageView.tsx

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Button from "@mui/material/Button"
22
import { makeStyles, useTheme } from "@mui/styles"
33
import Skeleton from "@mui/material/Skeleton"
44
import AddIcon from "@mui/icons-material/AddOutlined"
5+
import RefreshIcon from "@mui/icons-material/Refresh"
56
import { GetLicensesResponse } from "api/api"
67
import { Header } from "components/DeploySettingsLayout/Header"
78
import { LicenseCard } from "components/LicenseCard/LicenseCard"
@@ -11,6 +12,7 @@ import Confetti from "react-confetti"
1112
import { Link } from "react-router-dom"
1213
import useWindowSize from "react-use/lib/useWindowSize"
1314
import MuiLink from "@mui/material/Link"
15+
import { displaySuccess } from "components/GlobalSnackbar/utils"
1416

1517
type Props = {
1618
showConfetti: boolean
@@ -20,6 +22,7 @@ type Props = {
2022
licenses?: GetLicensesResponse[]
2123
isRemovingLicense: boolean
2224
removeLicense: (licenseId: number) => void
25+
refreshEntitlements?: () => boolean
2326
}
2427

2528
const LicensesSettingsPageView: FC<Props> = ({
@@ -30,6 +33,7 @@ const LicensesSettingsPageView: FC<Props> = ({
3033
licenses,
3134
isRemovingLicense,
3235
removeLicense,
36+
refreshEntitlements,
3337
}) => {
3438
const styles = useStyles()
3539
const { width, height } = useWindowSize()
@@ -55,13 +59,27 @@ const LicensesSettingsPageView: FC<Props> = ({
5559
description="Manage licenses to unlock Enterprise features."
5660
/>
5761

58-
<Button
59-
component={Link}
60-
to="/deployment/licenses/add"
61-
startIcon={<AddIcon />}
62-
>
63-
Add a license
64-
</Button>
62+
<Stack direction="row" spacing={2}>
63+
<Button
64+
component={Link}
65+
to="/deployment/licenses/add"
66+
startIcon={<AddIcon />}
67+
>
68+
Add a license
69+
</Button>
70+
<Button
71+
onClick={() => {
72+
if (refreshEntitlements) {
73+
if (refreshEntitlements()) {
74+
displaySuccess("Successfully refreshed licenses")
75+
}
76+
}
77+
}}
78+
startIcon={<RefreshIcon />}
79+
>
80+
Refresh
81+
</Button>
82+
</Stack>
6583
</Stack>
6684

6785
{isLoading && <Skeleton variant="rectangular" height={200} />}

site/src/xServices/deploymentStats/deploymentStatsMachine.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { assign, createMachine } from "xstate"
44

55
export const deploymentStatsMachine = createMachine(
66
{
7+
/** @xstate-layout N4IgpgJg5mDOIC5QTABwDYHsCeBbMAdgC4DKRAhkbALLkDGAFgJYFgB0sFVAxBJq2xYA3TAGt2KDDnzEylGvWYDO8hMMx1KTfgG0ADAF19BxKFSZYTItoKmQAD0QBWAMwuANCGyIATAHYATgBfIM9JLDxCUi4FRhZ2FR4wACdkzGS2DEoAM3TcNnDpKLkqWjjlGLUCEU1rXUNjO3NLOtskB0QAvU9vBAAWVxCwtAiZaPkypXYmCHQwbgAlAFEAGQB5AEEAEUb25qsbO0cEAEY9AA4exDOANhDQkAJMFHh2wsjZGMn4posD-iOiD6Piup3ObCcQxA7zGJViUw4MV+LUO7WOfT03S81xOLihMOKX0U8UEszAyP+bVAxxc5z6oJ8AT6EPuQSAA */
78
id: "deploymentStatsMachine",
89
predictableActionArguments: true,
910

site/src/xServices/entitlements/entitlementsXService.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export type EntitlementsContext = {
99

1010
export const entitlementsMachine = createMachine(
1111
{
12+
/** @xstate-layout N4IgpgJg5mDOIC5RgHYBcCWaA2YC2qasAsgIYDGAFhimAHQBOYAZk7JQMQQD2tdNAN24Brek1ZxKAUXRZcBdLADaABgC6iUAAdusLBl6aQAD0QAWAGwAOOgGYAjACYArABoQAT0SOA7AE46C0czP2cVHzNIlRV7HwBfOPdCOXxCEgpqPnE2TjAGBm4GOi1sUjRmQrxGFhyZTBxUxVUNJBAdPUxDVtMESxsHF3cvBFtbAKcQsIiomPjE8FkGhSIyKhp6GDRMFCg6lOXYLl56QRENsDQ9pbTmo3b9LtAe2wtnOmcBi1Hos0c-Hx8Q0QVnsdBCfj8Vh8UKsYVscySi3kaVWmXOWxouyRjSIHDyBSKJTKFQYVU2V2RTXUd10DxQRmer3en2+Kl+-0BnkQsTM7yCZimkTM0ViCUR9UpKwy634EFwHAASlIAGJKgDKAAlbq17p16d1uZCgb1HBZ3n54fZIrCgrZHGKFhKcek1nx8YVFSr1VrqTraXqjMN7KE6CoLT4rWYbY4HJyev5QabnBYzA4LX5XmYEvMUNwIHAjMlropUesaR0DPqnogALRR401s3RaKORwqWyw2Ehe3zIuSl1o6oSdjlukMxDwlR0HwWAFsiz-PwqZz-Y0r3m2AXhaGhPxmHzOB1952lvibbZYp0HUcBg0m42wuwp5wfeHP9s98X7FHSvgYOVgDelbjggKjGiENgrpa1rJjGn6Ot+Ja-vQsAAK7kOQcDwH6FaPCYiBQXQSYpmmYyZsa9gqI4oYDM49gWMGPimrOR7Ygcp70O6DBAXhPSEcRqbBmRzhmBRIZhtBUawbG2ZxEAA */
1213
id: "entitlementsMachine",
1314
predictableActionArguments: true,
1415
tsTypes: {} as import("./entitlementsXService.typegen").Typegen0,
@@ -22,13 +23,27 @@ export const entitlementsMachine = createMachine(
2223
},
2324
initial: "gettingEntitlements",
2425
states: {
26+
refresh: {
27+
invoke: {
28+
id: "refreshEntitlements",
29+
src: "refreshEntitlements",
30+
onDone: {
31+
target: "gettingEntitlements",
32+
},
33+
onError: {
34+
target: "error",
35+
actions: ["assignGetEntitlementsError"],
36+
},
37+
},
38+
entry: "clearGetEntitlementsError",
39+
},
2540
gettingEntitlements: {
2641
entry: "clearGetEntitlementsError",
2742
invoke: {
2843
id: "getEntitlements",
2944
src: "getEntitlements",
3045
onDone: {
31-
target: "success",
46+
target: "idle",
3247
actions: ["assignEntitlements"],
3348
},
3449
onError: {
@@ -37,11 +52,18 @@ export const entitlementsMachine = createMachine(
3752
},
3853
},
3954
},
55+
idle: {
56+
on: {
57+
REFRESH: "refresh"
58+
}
59+
},
4060
success: {
4161
type: "final",
4262
},
4363
error: {
44-
type: "final",
64+
on: {
65+
REFRESH: "refresh"
66+
}
4567
},
4668
},
4769
},
@@ -51,13 +73,18 @@ export const entitlementsMachine = createMachine(
5173
entitlements: (_, event) => event.data,
5274
}),
5375
assignGetEntitlementsError: assign({
54-
getEntitlementsError: (_, event) => event.data,
76+
getEntitlementsError: (_, event) => {
77+
return event.data
78+
},
5579
}),
5680
clearGetEntitlementsError: assign({
5781
getEntitlementsError: (_) => undefined,
5882
}),
5983
},
6084
services: {
85+
refreshEntitlements: async () => {
86+
return API.refreshEntitlements()
87+
},
6188
getEntitlements: async () => {
6289
// Entitlements is injected by the Coder server into the HTML document.
6390
const entitlements = document.querySelector(

0 commit comments

Comments
 (0)