From 81285275e423a7290c42b43c10d93b495484779c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=C5=9Al=C4=99zak?= Date: Fri, 13 Feb 2026 11:40:44 +0100 Subject: [PATCH 1/3] refactor license related modals --- web/src/pages/LocationsPage/LocationsPage.tsx | 13 +-- .../components/LocationsTable.tsx | 25 ++++-- .../pages/PlaygroundPage/PlaygroundPage.tsx | 68 +++++++++----- .../UsersOverviewPage/UsersOverviewPage.tsx | 14 +-- .../pages/UsersOverviewPage/UsersTable.tsx | 33 ++++--- .../SettingsLicenseTab/SettingsLicenseTab.tsx | 6 +- .../SettingsLicenseInfoSection.tsx | 11 ++- .../SettingsLicenseModal.tsx} | 4 +- web/src/routeTree.gen.ts | 42 ++++----- web/src/routes/_authorized.tsx | 10 ++- .../_authorized/_default/locations/index.tsx | 4 - web/src/routes/_authorized/playground.tsx | 6 ++ web/src/routes/playground.tsx | 6 -- web/src/shared/api/types.ts | 2 +- .../components/PageTopBar/PageTopBar.tsx | 1 - .../TopBarLicense/TopBarLicense.tsx | 5 ++ .../TopBarLicense/TopBarLicenseFloating.tsx | 32 +++---- .../modals/LicenseModal/LicenseModal.tsx | 33 +++++++ .../components/modals/LicenseModal/grid.png | Bin 0 -> 9793 bytes .../style.scss | 24 +++-- .../ModalUpgradePlan/ModalUpgradePlan.tsx | 84 ----------------- .../ModalUpgradePlan/assets/business-bg.png | Bin 554341 -> 0 bytes .../ModalUpgradePlan/assets/enterprise-bg.png | Bin 546673 -> 0 bytes .../UpgradePlanModalManager.tsx | 43 --------- .../LicenseExpiredModal.tsx | 85 ++++++++++++++++++ .../modals/license/LicenseModalControls.tsx | 44 +++++++++ .../LimitReachedModal/LimitReachedModal.tsx | 67 ++++++++++++++ .../UpgradeBusinessModal.tsx | 67 ++++++++++++++ .../UpgradeEnterpriseModal.tsx | 67 ++++++++++++++ web/src/shared/defguard-ui | 2 +- .../shared/hooks/modalControls/modalTypes.ts | 28 ++++-- web/src/shared/hooks/modalControls/types.ts | 15 +--- 32 files changed, 572 insertions(+), 269 deletions(-) rename web/src/pages/settings/SettingsIndexPage/tabs/SettingsLicenseTab/modals/{LicenseModal/LicenseModal.tsx => SettingsLicenseModal/SettingsLicenseModal.tsx} (97%) create mode 100644 web/src/routes/_authorized/playground.tsx delete mode 100644 web/src/routes/playground.tsx create mode 100644 web/src/shared/components/modals/LicenseModal/LicenseModal.tsx create mode 100644 web/src/shared/components/modals/LicenseModal/grid.png rename web/src/shared/components/modals/{ModalUpgradePlan => LicenseModal}/style.scss (71%) delete mode 100644 web/src/shared/components/modals/ModalUpgradePlan/ModalUpgradePlan.tsx delete mode 100644 web/src/shared/components/modals/ModalUpgradePlan/assets/business-bg.png delete mode 100644 web/src/shared/components/modals/ModalUpgradePlan/assets/enterprise-bg.png delete mode 100644 web/src/shared/components/modals/UpgradePlanModalManager/UpgradePlanModalManager.tsx create mode 100644 web/src/shared/components/modals/license/LicenseExpiredModal/LicenseExpiredModal.tsx create mode 100644 web/src/shared/components/modals/license/LicenseModalControls.tsx create mode 100644 web/src/shared/components/modals/license/LimitReachedModal/LimitReachedModal.tsx create mode 100644 web/src/shared/components/modals/license/UpgradeBusinessModal/UpgradeBusinessModal.tsx create mode 100644 web/src/shared/components/modals/license/UpgradeEnterpriseModal/UpgradeEnterpriseModal.tsx diff --git a/web/src/pages/LocationsPage/LocationsPage.tsx b/web/src/pages/LocationsPage/LocationsPage.tsx index 7e2d269fe3..57ec0294d4 100644 --- a/web/src/pages/LocationsPage/LocationsPage.tsx +++ b/web/src/pages/LocationsPage/LocationsPage.tsx @@ -1,17 +1,20 @@ -import { useSuspenseQuery } from '@tanstack/react-query'; +import { Suspense } from 'react'; import { Page } from '../../shared/components/Page/Page'; -import { getLocationsQueryOptions } from '../../shared/query'; import { LocationsTable } from './components/LocationsTable'; import { AddLocationModal } from './modals/AddLocationModal/AddLocationModal'; import './style.scss'; +import { TableSkeleton } from '../../shared/components/skeleton/TableSkeleton/TableSkeleton'; +import { TablePageLayout } from '../../shared/layout/TablePageLayout/TablePageLayout'; export const LocationsPage = () => { - const { data: locations } = useSuspenseQuery(getLocationsQueryOptions); - return ( <> - + }> + + + + diff --git a/web/src/pages/LocationsPage/components/LocationsTable.tsx b/web/src/pages/LocationsPage/components/LocationsTable.tsx index a399daea23..fb50206c71 100644 --- a/web/src/pages/LocationsPage/components/LocationsTable.tsx +++ b/web/src/pages/LocationsPage/components/LocationsTable.tsx @@ -1,4 +1,4 @@ -import { useMutation } from '@tanstack/react-query'; +import { useMutation, useSuspenseQuery } from '@tanstack/react-query'; import { useNavigate } from '@tanstack/react-router'; import { createColumnHelper, @@ -27,18 +27,20 @@ import { TableTop } from '../../../shared/defguard-ui/components/table/TableTop/ import { ThemeSpacing, ThemeVariable } from '../../../shared/defguard-ui/types'; import { openModal } from '../../../shared/hooks/modalControls/modalsSubjects'; import { ModalName } from '../../../shared/hooks/modalControls/modalTypes'; +import { + getLicenseInfoQueryOptions, + getLocationsQueryOptions, +} from '../../../shared/query'; import { tableSortingFns } from '../../../shared/utils/dateSortingFn'; import { useGatewayWizardStore } from '../../GatewaySetupPage/useGatewayWizardStore'; -type Props = { - locations: NetworkLocation[]; -}; - type RowData = NetworkLocation; const columnHelper = createColumnHelper(); -export const LocationsTable = ({ locations }: Props) => { +export const LocationsTable = () => { + const { data: locations } = useSuspenseQuery(getLocationsQueryOptions); + const { data: license } = useSuspenseQuery(getLicenseInfoQueryOptions); const navigate = useNavigate(); const [search, setSearch] = useState(''); @@ -66,10 +68,17 @@ export const LocationsTable = ({ locations }: Props) => { iconLeft: 'add-location', testId: 'add-location', onClick: () => { - openModal(ModalName.AddLocation); + if ( + license?.limits && + license.limits.locations.current === license.limits.locations.limit + ) { + openModal(ModalName.LimitReached); + } else { + openModal(ModalName.AddLocation); + } }, }), - [], + [license], ); const columns = useMemo( diff --git a/web/src/pages/PlaygroundPage/PlaygroundPage.tsx b/web/src/pages/PlaygroundPage/PlaygroundPage.tsx index 148f02633c..5fcb2e586c 100644 --- a/web/src/pages/PlaygroundPage/PlaygroundPage.tsx +++ b/web/src/pages/PlaygroundPage/PlaygroundPage.tsx @@ -4,6 +4,7 @@ import { CodeCard } from '../../shared/defguard-ui/components/CodeCard/CodeCard' import { Divider } from '../../shared/defguard-ui/components/Divider/Divider'; import { ThemeSpacing } from '../../shared/defguard-ui/types'; import './style.scss'; +import { useQuery } from '@tanstack/react-query'; import clsx from 'clsx'; import { useMemo, useState } from 'react'; import z from 'zod'; @@ -13,7 +14,6 @@ import { DestinationLabel } from '../../shared/components/DestinationLabel/Desti import { IpAssignmentCard } from '../../shared/components/IpAssignmentCard/IpAssignmentCard'; import { IpAssignmentDeviceSection } from '../../shared/components/IpAssignmentDeviceSection/IpAssignmentDeviceSection'; import { LoadingStep } from '../../shared/components/LoadingStep/LoadingStep'; -import { UpgradePlanModalManager } from '../../shared/components/modals/UpgradePlanModalManager/UpgradePlanModalManager'; import { SelectionSection } from '../../shared/components/SelectionSection/SelectionSection'; import type { SelectionOption, @@ -43,13 +43,15 @@ import { useAppForm } from '../../shared/form'; import { formChangeLogic } from '../../shared/formLogic'; import { openModal } from '../../shared/hooks/modalControls/modalsSubjects'; import { ModalName } from '../../shared/hooks/modalControls/modalTypes'; +import { getLicenseInfoQueryOptions } from '../../shared/query'; import { FoldableRadioSection } from '../FoldableRadioSection/FoldableRadioSection'; import testIconSrc from './assets/actionable-test1.png'; export const PlaygroundPage = () => { return (
- + + @@ -175,27 +177,6 @@ export const PlaygroundPage = () => {
- - -