diff --git a/site/package.json b/site/package.json index 5989e0cae1047..ba14145a284a0 100644 --- a/site/package.json +++ b/site/package.json @@ -170,10 +170,9 @@ "vite-plugin-turbosnap": "1.0.2" }, "browserslist": [ - "chrome 66", - "firefox 63", - "edge 79", - "safari 15.4" + "chrome 110", + "firefox 111", + "safari 16.0" ], "resolutions": { "optionator": "0.9.3", diff --git a/site/src/AppRouter.tsx b/site/src/AppRouter.tsx index 0ec595975f6b6..95b0f15e47f7b 100644 --- a/site/src/AppRouter.tsx +++ b/site/src/AppRouter.tsx @@ -5,8 +5,8 @@ import { BrowserRouter as Router, Navigate, } from "react-router-dom"; +import { DashboardLayout } from "./modules/dashboard/DashboardLayout"; import { RequireAuth } from "./contexts/auth/RequireAuth"; -import { DashboardLayout } from "./components/Dashboard/DashboardLayout"; import { FullScreenLoader } from "./components/Loader/FullScreenLoader"; import AuditPage from "./pages/AuditPage/AuditPage"; import { DeploySettingsLayout } from "./pages/DeploySettingsPage/DeploySettingsLayout"; diff --git a/site/src/components/WorkspaceStatusBadge/DormantDeletionText.tsx b/site/src/components/WorkspaceStatusBadge/DormantDeletionText.tsx index 924fc59cb47d9..3d5e5a3ed5bd4 100644 --- a/site/src/components/WorkspaceStatusBadge/DormantDeletionText.tsx +++ b/site/src/components/WorkspaceStatusBadge/DormantDeletionText.tsx @@ -1,7 +1,7 @@ import { type FC } from "react"; import type { Workspace } from "api/typesGenerated"; import { displayDormantDeletion } from "utils/dormant"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "modules/dashboard/useDashboard"; interface DormantDeletionTextProps { workspace: Workspace; diff --git a/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.stories.tsx b/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.stories.tsx index 691532de06849..ec86e1099f7d8 100644 --- a/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.stories.tsx +++ b/site/src/components/WorkspaceStatusBadge/WorkspaceStatusBadge.stories.tsx @@ -15,7 +15,7 @@ import { MockAppearanceConfig, } from "testHelpers/entities"; import { WorkspaceStatusBadge } from "./WorkspaceStatusBadge"; -import { DashboardProviderContext } from "components/Dashboard/DashboardProvider"; +import { DashboardContext } from "modules/dashboard/DashboardProvider"; import type { Meta, StoryObj } from "@storybook/react"; const MockedAppearance = { @@ -29,7 +29,7 @@ const meta: Meta = { component: WorkspaceStatusBadge, decorators: [ (Story) => ( - = { }} > - + ), ], }; diff --git a/site/src/contexts/auth/RequireAuth.tsx b/site/src/contexts/auth/RequireAuth.tsx index c6ea2cc519a3c..55b78c2a8cfe7 100644 --- a/site/src/contexts/auth/RequireAuth.tsx +++ b/site/src/contexts/auth/RequireAuth.tsx @@ -4,7 +4,7 @@ import { Outlet, Navigate, useLocation } from "react-router-dom"; import { embedRedirect } from "utils/redirect"; import { isApiError } from "api/errors"; import { ProxyProvider } from "contexts/ProxyContext"; -import { DashboardProvider } from "components/Dashboard/DashboardProvider"; +import { DashboardProvider } from "modules/dashboard/DashboardProvider"; import { FullScreenLoader } from "components/Loader/FullScreenLoader"; import { useAuth } from "./useAuth"; diff --git a/site/src/hooks/index.ts b/site/src/hooks/index.ts index 40147df532412..852e4463f3d96 100644 --- a/site/src/hooks/index.ts +++ b/site/src/hooks/index.ts @@ -1,6 +1,5 @@ export * from "./useClickable"; export * from "./useClickableTableRow"; export * from "./useClipboard"; -export * from "./useFeatureVisibility"; export * from "./usePagination"; export * from "./useTab"; diff --git a/site/src/components/Dashboard/DashboardLayout.test.tsx b/site/src/modules/dashboard/DashboardLayout.test.tsx similarity index 100% rename from site/src/components/Dashboard/DashboardLayout.test.tsx rename to site/src/modules/dashboard/DashboardLayout.test.tsx diff --git a/site/src/components/Dashboard/DashboardLayout.tsx b/site/src/modules/dashboard/DashboardLayout.tsx similarity index 95% rename from site/src/components/Dashboard/DashboardLayout.tsx rename to site/src/modules/dashboard/DashboardLayout.tsx index af4cb9a0cb5e5..6bf30a22a3e1e 100644 --- a/site/src/components/Dashboard/DashboardLayout.tsx +++ b/site/src/modules/dashboard/DashboardLayout.tsx @@ -4,10 +4,10 @@ import Button from "@mui/material/Button"; import InfoOutlined from "@mui/icons-material/InfoOutlined"; import { type FC, type HTMLAttributes, Suspense } from "react"; import { Outlet } from "react-router-dom"; +import { LicenseBanner } from "modules/dashboard/LicenseBanner/LicenseBanner"; +import { ServiceBanner } from "modules/dashboard/ServiceBanner/ServiceBanner"; import { usePermissions } from "contexts/auth/usePermissions"; -import { LicenseBanner } from "components/Dashboard/LicenseBanner/LicenseBanner"; import { Loader } from "components/Loader/Loader"; -import { ServiceBanner } from "components/Dashboard/ServiceBanner/ServiceBanner"; import { dashboardContentBottomPadding } from "theme/constants"; import { docs } from "utils/docs"; import { Navbar } from "./Navbar/Navbar"; diff --git a/site/src/components/Dashboard/DashboardProvider.tsx b/site/src/modules/dashboard/DashboardProvider.tsx similarity index 81% rename from site/src/components/Dashboard/DashboardProvider.tsx rename to site/src/modules/dashboard/DashboardProvider.tsx index 7fcefb173eccf..fcd84f8d2d152 100644 --- a/site/src/components/Dashboard/DashboardProvider.tsx +++ b/site/src/modules/dashboard/DashboardProvider.tsx @@ -14,7 +14,6 @@ import { type PropsWithChildren, createContext, useCallback, - useContext, useState, } from "react"; import { appearance } from "api/queries/appearance"; @@ -27,16 +26,16 @@ interface Appearance { setPreview: (config: AppearanceConfig) => void; } -interface DashboardProviderValue { +export interface DashboardValue { buildInfo: BuildInfoResponse; entitlements: Entitlements; experiments: Experiments; appearance: Appearance; } -export const DashboardProviderContext = createContext< - DashboardProviderValue | undefined ->(undefined); +export const DashboardContext = createContext( + undefined, +); export const DashboardProvider: FC = ({ children }) => { const buildInfoQuery = useQuery(buildInfo()); @@ -83,7 +82,7 @@ export const DashboardProvider: FC = ({ children }) => { } return ( - = ({ children }) => { }} > {children} - + ); }; - -export const useDashboard = (): DashboardProviderValue => { - const context = useContext(DashboardProviderContext); - - if (!context) { - throw new Error( - "useDashboard only can be used inside of DashboardProvider", - ); - } - - return context; -}; - -export const useIsWorkspaceActionsEnabled = (): boolean => { - const { entitlements } = useDashboard(); - return entitlements.features["advanced_template_scheduling"].enabled; -}; diff --git a/site/src/components/Dashboard/DeploymentBanner/DeploymentBanner.tsx b/site/src/modules/dashboard/DeploymentBanner/DeploymentBanner.tsx similarity index 100% rename from site/src/components/Dashboard/DeploymentBanner/DeploymentBanner.tsx rename to site/src/modules/dashboard/DeploymentBanner/DeploymentBanner.tsx diff --git a/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.stories.tsx b/site/src/modules/dashboard/DeploymentBanner/DeploymentBannerView.stories.tsx similarity index 100% rename from site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.stories.tsx rename to site/src/modules/dashboard/DeploymentBanner/DeploymentBannerView.stories.tsx diff --git a/site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx b/site/src/modules/dashboard/DeploymentBanner/DeploymentBannerView.tsx similarity index 100% rename from site/src/components/Dashboard/DeploymentBanner/DeploymentBannerView.tsx rename to site/src/modules/dashboard/DeploymentBanner/DeploymentBannerView.tsx diff --git a/site/src/components/Dashboard/LicenseBanner/LicenseBanner.tsx b/site/src/modules/dashboard/LicenseBanner/LicenseBanner.tsx similarity index 83% rename from site/src/components/Dashboard/LicenseBanner/LicenseBanner.tsx rename to site/src/modules/dashboard/LicenseBanner/LicenseBanner.tsx index 6702c3c2bc8d4..1acba81f52043 100644 --- a/site/src/components/Dashboard/LicenseBanner/LicenseBanner.tsx +++ b/site/src/modules/dashboard/LicenseBanner/LicenseBanner.tsx @@ -1,5 +1,5 @@ import { type FC } from "react"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { LicenseBannerView } from "./LicenseBannerView"; export const LicenseBanner: FC = () => { diff --git a/site/src/components/Dashboard/LicenseBanner/LicenseBannerView.stories.tsx b/site/src/modules/dashboard/LicenseBanner/LicenseBannerView.stories.tsx similarity index 100% rename from site/src/components/Dashboard/LicenseBanner/LicenseBannerView.stories.tsx rename to site/src/modules/dashboard/LicenseBanner/LicenseBannerView.stories.tsx diff --git a/site/src/components/Dashboard/LicenseBanner/LicenseBannerView.tsx b/site/src/modules/dashboard/LicenseBanner/LicenseBannerView.tsx similarity index 100% rename from site/src/components/Dashboard/LicenseBanner/LicenseBannerView.tsx rename to site/src/modules/dashboard/LicenseBanner/LicenseBannerView.tsx diff --git a/site/src/components/Dashboard/Navbar/Navbar.test.tsx b/site/src/modules/dashboard/Navbar/Navbar.test.tsx similarity index 100% rename from site/src/components/Dashboard/Navbar/Navbar.test.tsx rename to site/src/modules/dashboard/Navbar/Navbar.test.tsx diff --git a/site/src/components/Dashboard/Navbar/Navbar.tsx b/site/src/modules/dashboard/Navbar/Navbar.tsx similarity index 90% rename from site/src/components/Dashboard/Navbar/Navbar.tsx rename to site/src/modules/dashboard/Navbar/Navbar.tsx index bd0f0705e73ef..3e618bbc876f8 100644 --- a/site/src/components/Dashboard/Navbar/Navbar.tsx +++ b/site/src/modules/dashboard/Navbar/Navbar.tsx @@ -3,8 +3,8 @@ import { useAuth } from "contexts/auth/useAuth"; import { useMe } from "contexts/auth/useMe"; import { usePermissions } from "contexts/auth/usePermissions"; import { useProxy } from "contexts/ProxyContext"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; -import { useFeatureVisibility } from "hooks/useFeatureVisibility"; +import { useDashboard } from "modules/dashboard/useDashboard"; +import { useFeatureVisibility } from "../useFeatureVisibility"; import { NavbarView } from "./NavbarView"; export const Navbar: FC = () => { diff --git a/site/src/components/Dashboard/Navbar/NavbarView.stories.tsx b/site/src/modules/dashboard/Navbar/NavbarView.stories.tsx similarity index 100% rename from site/src/components/Dashboard/Navbar/NavbarView.stories.tsx rename to site/src/modules/dashboard/Navbar/NavbarView.stories.tsx diff --git a/site/src/components/Dashboard/Navbar/NavbarView.test.tsx b/site/src/modules/dashboard/Navbar/NavbarView.test.tsx similarity index 100% rename from site/src/components/Dashboard/Navbar/NavbarView.test.tsx rename to site/src/modules/dashboard/Navbar/NavbarView.test.tsx diff --git a/site/src/components/Dashboard/Navbar/NavbarView.tsx b/site/src/modules/dashboard/Navbar/NavbarView.tsx similarity index 100% rename from site/src/components/Dashboard/Navbar/NavbarView.tsx rename to site/src/modules/dashboard/Navbar/NavbarView.tsx diff --git a/site/src/components/Dashboard/Navbar/UserDropdown/UserDropdown.stories.tsx b/site/src/modules/dashboard/Navbar/UserDropdown/UserDropdown.stories.tsx similarity index 100% rename from site/src/components/Dashboard/Navbar/UserDropdown/UserDropdown.stories.tsx rename to site/src/modules/dashboard/Navbar/UserDropdown/UserDropdown.stories.tsx diff --git a/site/src/components/Dashboard/Navbar/UserDropdown/UserDropdown.tsx b/site/src/modules/dashboard/Navbar/UserDropdown/UserDropdown.tsx similarity index 100% rename from site/src/components/Dashboard/Navbar/UserDropdown/UserDropdown.tsx rename to site/src/modules/dashboard/Navbar/UserDropdown/UserDropdown.tsx diff --git a/site/src/components/Dashboard/Navbar/UserDropdown/UserDropdownContent.test.tsx b/site/src/modules/dashboard/Navbar/UserDropdown/UserDropdownContent.test.tsx similarity index 100% rename from site/src/components/Dashboard/Navbar/UserDropdown/UserDropdownContent.test.tsx rename to site/src/modules/dashboard/Navbar/UserDropdown/UserDropdownContent.test.tsx diff --git a/site/src/components/Dashboard/Navbar/UserDropdown/UserDropdownContent.tsx b/site/src/modules/dashboard/Navbar/UserDropdown/UserDropdownContent.tsx similarity index 100% rename from site/src/components/Dashboard/Navbar/UserDropdown/UserDropdownContent.tsx rename to site/src/modules/dashboard/Navbar/UserDropdown/UserDropdownContent.tsx diff --git a/site/src/components/Dashboard/ServiceBanner/ServiceBanner.tsx b/site/src/modules/dashboard/ServiceBanner/ServiceBanner.tsx similarity index 87% rename from site/src/components/Dashboard/ServiceBanner/ServiceBanner.tsx rename to site/src/modules/dashboard/ServiceBanner/ServiceBanner.tsx index 1c03dbd88fcbc..94e350b89eb2c 100644 --- a/site/src/components/Dashboard/ServiceBanner/ServiceBanner.tsx +++ b/site/src/modules/dashboard/ServiceBanner/ServiceBanner.tsx @@ -1,5 +1,5 @@ import { type FC } from "react"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { ServiceBannerView } from "./ServiceBannerView"; export const ServiceBanner: FC = () => { diff --git a/site/src/components/Dashboard/ServiceBanner/ServiceBannerView.stories.tsx b/site/src/modules/dashboard/ServiceBanner/ServiceBannerView.stories.tsx similarity index 100% rename from site/src/components/Dashboard/ServiceBanner/ServiceBannerView.stories.tsx rename to site/src/modules/dashboard/ServiceBanner/ServiceBannerView.stories.tsx diff --git a/site/src/components/Dashboard/ServiceBanner/ServiceBannerView.tsx b/site/src/modules/dashboard/ServiceBanner/ServiceBannerView.tsx similarity index 100% rename from site/src/components/Dashboard/ServiceBanner/ServiceBannerView.tsx rename to site/src/modules/dashboard/ServiceBanner/ServiceBannerView.tsx diff --git a/site/src/modules/dashboard/useDashboard.ts b/site/src/modules/dashboard/useDashboard.ts new file mode 100644 index 0000000000000..9bb71613d2157 --- /dev/null +++ b/site/src/modules/dashboard/useDashboard.ts @@ -0,0 +1,14 @@ +import { useContext } from "react"; +import { DashboardContext, type DashboardValue } from "./DashboardProvider"; + +export const useDashboard = (): DashboardValue => { + const context = useContext(DashboardContext); + + if (!context) { + throw new Error( + "useDashboard only can be used inside of DashboardProvider", + ); + } + + return context; +}; diff --git a/site/src/hooks/useFeatureVisibility.ts b/site/src/modules/dashboard/useFeatureVisibility.ts similarity index 79% rename from site/src/hooks/useFeatureVisibility.ts rename to site/src/modules/dashboard/useFeatureVisibility.ts index 00e491a6e303d..a43111639e0cb 100644 --- a/site/src/hooks/useFeatureVisibility.ts +++ b/site/src/modules/dashboard/useFeatureVisibility.ts @@ -1,5 +1,5 @@ import { FeatureName } from "api/typesGenerated"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "./useDashboard"; import { selectFeatureVisibility } from "utils/entitlements"; export const useFeatureVisibility = (): Record => { diff --git a/site/src/components/Dashboard/useUpdateCheck.test.tsx b/site/src/modules/dashboard/useUpdateCheck.test.tsx similarity index 100% rename from site/src/components/Dashboard/useUpdateCheck.test.tsx rename to site/src/modules/dashboard/useUpdateCheck.test.tsx index b689f39d4252e..dec292346e57b 100644 --- a/site/src/components/Dashboard/useUpdateCheck.test.tsx +++ b/site/src/modules/dashboard/useUpdateCheck.test.tsx @@ -1,10 +1,10 @@ import { act, renderHook, waitFor } from "@testing-library/react"; -import { useUpdateCheck } from "./useUpdateCheck"; -import { QueryClient, QueryClientProvider } from "react-query"; import { type FC, type PropsWithChildren } from "react"; +import { QueryClient, QueryClientProvider } from "react-query"; import { rest } from "msw"; import { MockUpdateCheck } from "testHelpers/entities"; import { server } from "testHelpers/server"; +import { useUpdateCheck } from "./useUpdateCheck"; const createWrapper = (): FC => { const queryClient = new QueryClient(); diff --git a/site/src/components/Dashboard/useUpdateCheck.ts b/site/src/modules/dashboard/useUpdateCheck.ts similarity index 100% rename from site/src/components/Dashboard/useUpdateCheck.ts rename to site/src/modules/dashboard/useUpdateCheck.ts diff --git a/site/src/pages/AuditPage/AuditPage.tsx b/site/src/pages/AuditPage/AuditPage.tsx index 80f9cce869eb2..f9785379f4451 100644 --- a/site/src/pages/AuditPage/AuditPage.tsx +++ b/site/src/pages/AuditPage/AuditPage.tsx @@ -1,15 +1,15 @@ -import { isNonInitialPage } from "components/PaginationWidget/utils"; -import { useFeatureVisibility } from "hooks/useFeatureVisibility"; -import { FC } from "react"; +import { type FC } from "react"; import { Helmet } from "react-helmet-async"; import { useSearchParams } from "react-router-dom"; +import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; import { pageTitle } from "utils/page"; -import { AuditPageView } from "./AuditPageView"; +import { paginatedAudits } from "api/queries/audits"; +import { usePaginatedQuery } from "hooks/usePaginatedQuery"; import { useUserFilterMenu } from "components/Filter/UserFilter"; +import { isNonInitialPage } from "components/PaginationWidget/utils"; import { useFilter } from "components/Filter/filter"; import { useActionFilterMenu, useResourceTypeFilterMenu } from "./AuditFilter"; -import { usePaginatedQuery } from "hooks/usePaginatedQuery"; -import { paginatedAudits } from "api/queries/audits"; +import { AuditPageView } from "./AuditPageView"; const AuditPage: FC = () => { const { audit_log: isAuditLogVisible } = useFeatureVisibility(); diff --git a/site/src/pages/CreateTemplatePage/DuplicateTemplateView.tsx b/site/src/pages/CreateTemplatePage/DuplicateTemplateView.tsx index 8d3d70cb00cba..3a96ce6b9b571 100644 --- a/site/src/pages/CreateTemplatePage/DuplicateTemplateView.tsx +++ b/site/src/pages/CreateTemplatePage/DuplicateTemplateView.tsx @@ -10,9 +10,9 @@ import { createTemplate, } from "api/queries/templates"; import { useOrganizationId } from "contexts/auth/useOrganizationId"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Loader } from "components/Loader/Loader"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; import { CreateTemplateForm } from "./CreateTemplateForm"; import { firstVersionFromFile, getFormPermissions, newTemplate } from "./utils"; diff --git a/site/src/pages/CreateTemplatePage/ImportStarterTemplateView.tsx b/site/src/pages/CreateTemplatePage/ImportStarterTemplateView.tsx index 32c2308eded09..9ab04ab7044e8 100644 --- a/site/src/pages/CreateTemplatePage/ImportStarterTemplateView.tsx +++ b/site/src/pages/CreateTemplatePage/ImportStarterTemplateView.tsx @@ -9,9 +9,9 @@ import { templateVersionVariables, } from "api/queries/templates"; import { useOrganizationId } from "contexts/auth/useOrganizationId"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Loader } from "components/Loader/Loader"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; import { CreateTemplateForm } from "./CreateTemplateForm"; import { firstVersionFromExample, diff --git a/site/src/pages/CreateTemplatePage/UploadTemplateView.tsx b/site/src/pages/CreateTemplatePage/UploadTemplateView.tsx index 5bd807d4d2267..e6f4e918ec3ac 100644 --- a/site/src/pages/CreateTemplatePage/UploadTemplateView.tsx +++ b/site/src/pages/CreateTemplatePage/UploadTemplateView.tsx @@ -8,7 +8,7 @@ import { } from "api/queries/templates"; import { uploadFile } from "api/queries/files"; import { useOrganizationId } from "contexts/auth/useOrganizationId"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { CreateTemplateForm } from "./CreateTemplateForm"; import { firstVersionFromFile, getFormPermissions, newTemplate } from "./utils"; diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx index 439dc69f31763..fe5bd57fc42ca 100644 --- a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx @@ -1,13 +1,13 @@ -import { UpdateAppearanceConfig } from "api/typesGenerated"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; -import { FC } from "react"; +import { type FC } from "react"; import { Helmet } from "react-helmet-async"; -import { pageTitle } from "utils/page"; -import { AppearanceSettingsPageView } from "./AppearanceSettingsPageView"; import { useMutation, useQueryClient } from "react-query"; +import type { UpdateAppearanceConfig } from "api/typesGenerated"; +import { useDashboard } from "modules/dashboard/useDashboard"; +import { pageTitle } from "utils/page"; import { updateAppearance } from "api/queries/appearance"; import { getErrorMessage } from "api/errors"; import { displayError, displaySuccess } from "components/GlobalSnackbar/utils"; +import { AppearanceSettingsPageView } from "./AppearanceSettingsPageView"; // ServiceBanner is unlike the other Deployment Settings pages because it // implements a form, whereas the others are read-only. We make this diff --git a/site/src/pages/DeploySettingsPage/OAuth2AppsSettingsPage/OAuth2AppsSettingsPage.tsx b/site/src/pages/DeploySettingsPage/OAuth2AppsSettingsPage/OAuth2AppsSettingsPage.tsx index 6e2035f2f9107..5f2aeb2cf3ab3 100644 --- a/site/src/pages/DeploySettingsPage/OAuth2AppsSettingsPage/OAuth2AppsSettingsPage.tsx +++ b/site/src/pages/DeploySettingsPage/OAuth2AppsSettingsPage/OAuth2AppsSettingsPage.tsx @@ -1,8 +1,8 @@ +import { type FC } from "react"; +import { Helmet } from "react-helmet-async"; import { useQuery } from "react-query"; import { getApps } from "api/queries/oauth2"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; -import { FC } from "react"; -import { Helmet } from "react-helmet-async"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { pageTitle } from "utils/page"; import OAuth2AppsSettingsPageView from "./OAuth2AppsSettingsPageView"; diff --git a/site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPage.tsx b/site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPage.tsx index ece84c7e685bc..520e8a6b25060 100644 --- a/site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPage.tsx +++ b/site/src/pages/DeploySettingsPage/ObservabilitySettingsPage/ObservabilitySettingsPage.tsx @@ -1,7 +1,7 @@ import { type FC } from "react"; import { Helmet } from "react-helmet-async"; import { pageTitle } from "utils/page"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { useDeploySettings } from "../DeploySettingsLayout"; import { ObservabilitySettingsPageView } from "./ObservabilitySettingsPageView"; diff --git a/site/src/pages/DeploySettingsPage/SecuritySettingsPage/SecuritySettingsPage.tsx b/site/src/pages/DeploySettingsPage/SecuritySettingsPage/SecuritySettingsPage.tsx index 020af05f45a4f..e82f00a4b4a2e 100644 --- a/site/src/pages/DeploySettingsPage/SecuritySettingsPage/SecuritySettingsPage.tsx +++ b/site/src/pages/DeploySettingsPage/SecuritySettingsPage/SecuritySettingsPage.tsx @@ -1,7 +1,7 @@ import { type FC } from "react"; import { Helmet } from "react-helmet-async"; import { pageTitle } from "utils/page"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { SecuritySettingsPageView } from "./SecuritySettingsPageView"; import { useDeploySettings } from "../DeploySettingsLayout"; diff --git a/site/src/pages/GroupsPage/GroupsPage.tsx b/site/src/pages/GroupsPage/GroupsPage.tsx index 281c702e0c3ba..bb809ca1d2eaf 100644 --- a/site/src/pages/GroupsPage/GroupsPage.tsx +++ b/site/src/pages/GroupsPage/GroupsPage.tsx @@ -5,9 +5,9 @@ import { getErrorMessage } from "api/errors"; import { groups } from "api/queries/groups"; import { useOrganizationId } from "contexts/auth/useOrganizationId"; import { usePermissions } from "contexts/auth/usePermissions"; -import { useFeatureVisibility } from "hooks/useFeatureVisibility"; -import { pageTitle } from "utils/page"; +import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; import { displayError } from "components/GlobalSnackbar/utils"; +import { pageTitle } from "utils/page"; import GroupsPageView from "./GroupsPageView"; export const GroupsPage: FC = () => { diff --git a/site/src/pages/HealthPage/AccessURLPage.stories.tsx b/site/src/pages/HealthPage/AccessURLPage.stories.tsx index 31ed1e32a2961..1fddaa03acb5a 100644 --- a/site/src/pages/HealthPage/AccessURLPage.stories.tsx +++ b/site/src/pages/HealthPage/AccessURLPage.stories.tsx @@ -13,4 +13,6 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Default: Story = {}; +const Example: Story = {}; + +export { Example as AccessURL }; diff --git a/site/src/pages/HealthPage/DERPPage.stories.tsx b/site/src/pages/HealthPage/DERPPage.stories.tsx index 8e87d3c03b2fb..194552361f568 100644 --- a/site/src/pages/HealthPage/DERPPage.stories.tsx +++ b/site/src/pages/HealthPage/DERPPage.stories.tsx @@ -13,4 +13,6 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Default: Story = {}; +const Example: Story = {}; + +export { Example as DERP }; diff --git a/site/src/pages/HealthPage/DERPRegionPage.stories.tsx b/site/src/pages/HealthPage/DERPRegionPage.stories.tsx index 6305c2eecc7b1..d462403be0c26 100644 --- a/site/src/pages/HealthPage/DERPRegionPage.stories.tsx +++ b/site/src/pages/HealthPage/DERPRegionPage.stories.tsx @@ -18,4 +18,6 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Default: Story = {}; +const Example: Story = {}; + +export { Example as DERPRegion }; diff --git a/site/src/pages/HealthPage/DatabasePage.stories.tsx b/site/src/pages/HealthPage/DatabasePage.stories.tsx index b250dbce68afe..f2ec5c5d0cf57 100644 --- a/site/src/pages/HealthPage/DatabasePage.stories.tsx +++ b/site/src/pages/HealthPage/DatabasePage.stories.tsx @@ -13,4 +13,6 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Default: Story = {}; +const Example: Story = {}; + +export { Example as Database }; diff --git a/site/src/pages/HealthPage/HealthLayout.tsx b/site/src/pages/HealthPage/HealthLayout.tsx index 0aef42e457991..df8b6fa166bca 100644 --- a/site/src/pages/HealthPage/HealthLayout.tsx +++ b/site/src/pages/HealthPage/HealthLayout.tsx @@ -1,24 +1,25 @@ -import { useMutation, useQuery, useQueryClient } from "react-query"; -import { Loader } from "components/Loader/Loader"; -import { Helmet } from "react-helmet-async"; -import { pageTitle } from "utils/page"; -import { createDayString } from "utils/createDayString"; -import { DashboardFullPage } from "components/Dashboard/DashboardLayout"; -import ReplayIcon from "@mui/icons-material/Replay"; -import { health, refreshHealth } from "api/queries/debug"; -import { useTheme } from "@mui/material/styles"; import IconButton from "@mui/material/IconButton"; import Tooltip from "@mui/material/Tooltip"; import CircularProgress from "@mui/material/CircularProgress"; +import ReplayIcon from "@mui/icons-material/Replay"; +import NotificationsOffOutlined from "@mui/icons-material/NotificationsOffOutlined"; +import { cx } from "@emotion/css"; +import { useTheme } from "@emotion/react"; +import { type FC, Suspense } from "react"; +import { Helmet } from "react-helmet-async"; +import { useMutation, useQuery, useQueryClient } from "react-query"; import { NavLink, Outlet } from "react-router-dom"; -import { css } from "@emotion/css"; import kebabCase from "lodash/fp/kebabCase"; -import { Suspense } from "react"; +import { health, refreshHealth } from "api/queries/debug"; +import type { HealthSeverity } from "api/typesGenerated"; +import { type ClassName, useClassName } from "hooks/useClassName"; +import { pageTitle } from "utils/page"; +import { createDayString } from "utils/createDayString"; +import { DashboardFullPage } from "modules/dashboard/DashboardLayout"; +import { Loader } from "components/Loader/Loader"; import { HealthIcon } from "./Content"; -import { HealthSeverity } from "api/typesGenerated"; -import NotificationsOffOutlined from "@mui/icons-material/NotificationsOffOutlined"; -export function HealthLayout() { +export const HealthLayout: FC = () => { const theme = useTheme(); const queryClient = useQueryClient(); const { data: healthStatus } = useQuery({ @@ -38,6 +39,9 @@ export function HealthLayout() { } as const; const visibleSections = filterVisibleSections(sections); + const link = useClassName(classNames.link, []); + const activeLink = useClassName(classNames.activeLink, []); + return ( <> @@ -162,31 +166,7 @@ export function HealthLayout() { key={key} to={`/health/${kebabCase(key)}`} className={({ isActive }) => - css({ - background: isActive - ? theme.palette.action.hover - : "none", - pointerEvents: isActive ? "none" : "auto", - color: isActive - ? theme.palette.text.primary - : theme.palette.text.secondary, - border: "none", - fontSize: 14, - width: "100%", - display: "flex", - alignItems: "center", - gap: 12, - textAlign: "left", - height: 36, - padding: "0 24px", - cursor: "pointer", - textDecoration: "none", - - "&:hover": { - background: theme.palette.action.hover, - color: theme.palette.text.primary, - }, - }) + cx([link, isActive && activeLink]) } > ); -} +}; const filterVisibleSections = (sections: T) => { return Object.keys(sections).reduce( @@ -240,3 +220,35 @@ const filterVisibleSections = (sections: T) => { {} as Partial, ); }; + +const classNames = { + link: (css, theme) => + css({ + background: "none", + pointerEvents: "auto", + color: theme.palette.text.secondary, + border: "none", + fontSize: 14, + width: "100%", + display: "flex", + alignItems: "center", + gap: 12, + textAlign: "left", + height: 36, + padding: "0 24px", + cursor: "pointer", + textDecoration: "none", + + "&:hover": { + background: theme.palette.action.hover, + color: theme.palette.text.primary, + }, + }), + + activeLink: (css, theme) => + css({ + background: theme.palette.action.hover, + pointerEvents: "none", + color: theme.palette.text.primary, + }), +} satisfies Record; diff --git a/site/src/pages/HealthPage/ProvisionerDaemonsPage.stories.tsx b/site/src/pages/HealthPage/ProvisionerDaemonsPage.stories.tsx index 7117aa886967e..b80a20c1ed159 100644 --- a/site/src/pages/HealthPage/ProvisionerDaemonsPage.stories.tsx +++ b/site/src/pages/HealthPage/ProvisionerDaemonsPage.stories.tsx @@ -13,4 +13,6 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Default: Story = {}; +const Example: Story = {}; + +export { Example as ProvisionerDaemons }; diff --git a/site/src/pages/HealthPage/WebsocketPage.stories.tsx b/site/src/pages/HealthPage/WebsocketPage.stories.tsx index 896bc7126ca95..4eba44bc48b58 100644 --- a/site/src/pages/HealthPage/WebsocketPage.stories.tsx +++ b/site/src/pages/HealthPage/WebsocketPage.stories.tsx @@ -13,4 +13,6 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Default: Story = {}; +const Example: Story = {}; + +export { Example as Websocket }; diff --git a/site/src/pages/HealthPage/WorkspaceProxyPage.stories.tsx b/site/src/pages/HealthPage/WorkspaceProxyPage.stories.tsx index 446bf1ea6f9f0..92e031014079a 100644 --- a/site/src/pages/HealthPage/WorkspaceProxyPage.stories.tsx +++ b/site/src/pages/HealthPage/WorkspaceProxyPage.stories.tsx @@ -13,4 +13,6 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Default: Story = {}; +const Example: Story = {}; + +export { Example as WorkspaceProxy }; diff --git a/site/src/pages/HealthPage/storybook.tsx b/site/src/pages/HealthPage/storybook.tsx index 886402af3a1bf..776e5f3e8fb03 100644 --- a/site/src/pages/HealthPage/storybook.tsx +++ b/site/src/pages/HealthPage/storybook.tsx @@ -14,7 +14,7 @@ import { MockHealthSettings, } from "testHelpers/entities"; import { HEALTH_QUERY_KEY, HEALTH_QUERY_SETTINGS_KEY } from "api/queries/debug"; -import { DashboardProvider } from "components/Dashboard/DashboardProvider"; +import { DashboardProvider } from "modules/dashboard/DashboardProvider"; import { HealthLayout } from "./HealthLayout"; type MetaOptions = { @@ -25,7 +25,7 @@ type MetaOptions = { export const generateMeta = ({ element, path, params }: MetaOptions): Meta => { return { - render: HealthLayout, + component: HealthLayout, parameters: { chromatic, layout: "fullscreen", diff --git a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.tsx b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.tsx index adc760e4bcebc..572b788aacbab 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateGeneralSettingsPage/TemplateSettingsPage.tsx @@ -2,12 +2,12 @@ import { type FC } from "react"; import { Helmet } from "react-helmet-async"; import { useMutation, useQueryClient } from "react-query"; import { useNavigate, useParams } from "react-router-dom"; -import { pageTitle } from "utils/page"; import { updateTemplateMeta } from "api/api"; import type { UpdateTemplateMeta } from "api/typesGenerated"; import { templateByNameKey } from "api/queries/templates"; import { useOrganizationId } from "contexts/auth/useOrganizationId"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "modules/dashboard/useDashboard"; +import { pageTitle } from "utils/page"; import { displaySuccess } from "components/GlobalSnackbar/utils"; import { useTemplateSettings } from "../TemplateSettingsLayout"; import { TemplateSettingsPageView } from "./TemplateSettingsPageView"; diff --git a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx index 264259270e293..f7173ff0d67cf 100644 --- a/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplatePermissionsPage/TemplatePermissionsPage.tsx @@ -8,16 +8,14 @@ import { setGroupRole, setUserRole, templateACL } from "api/queries/templates"; import { Paywall } from "components/Paywall/Paywall"; import { Stack } from "components/Stack/Stack"; import { displaySuccess } from "components/GlobalSnackbar/utils"; -import { useFeatureVisibility } from "hooks/useFeatureVisibility"; import { useOrganizationId } from "contexts/auth/useOrganizationId"; +import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; import { pageTitle } from "utils/page"; import { docs } from "utils/docs"; import { useTemplateSettings } from "../TemplateSettingsLayout"; import { TemplatePermissionsPageView } from "./TemplatePermissionsPageView"; -export const TemplatePermissionsPage: FC< - React.PropsWithChildren -> = () => { +export const TemplatePermissionsPage: FC = () => { const organizationId = useOrganizationId(); const { template, permissions } = useTemplateSettings(); const { template_rbac: isTemplateRBACEnabled } = useFeatureVisibility(); diff --git a/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateSchedulePage.tsx b/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateSchedulePage.tsx index 8e75e29ae860a..5c8cff6184241 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateSchedulePage.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateSchedulePage/TemplateSchedulePage.tsx @@ -2,12 +2,12 @@ import { type FC } from "react"; import { Helmet } from "react-helmet-async"; import { useMutation, useQueryClient } from "react-query"; import { useNavigate, useParams } from "react-router-dom"; -import { pageTitle } from "utils/page"; import { updateTemplateMeta } from "api/api"; import type { UpdateTemplateMeta } from "api/typesGenerated"; import { templateByNameKey } from "api/queries/templates"; import { useOrganizationId } from "contexts/auth/useOrganizationId"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "modules/dashboard/useDashboard"; +import { pageTitle } from "utils/page"; import { displaySuccess } from "components/GlobalSnackbar/utils"; import { useTemplateSettings } from "../TemplateSettingsLayout"; import { TemplateSchedulePageView } from "./TemplateSchedulePageView"; diff --git a/site/src/pages/UserSettingsPage/AccountPage/AccountPage.tsx b/site/src/pages/UserSettingsPage/AccountPage/AccountPage.tsx index c2e7512a29630..c2f11435806ea 100644 --- a/site/src/pages/UserSettingsPage/AccountPage/AccountPage.tsx +++ b/site/src/pages/UserSettingsPage/AccountPage/AccountPage.tsx @@ -5,7 +5,7 @@ import { useAuth } from "contexts/auth/useAuth"; import { useMe } from "contexts/auth/useMe"; import { useOrganizationId } from "contexts/auth/useOrganizationId"; import { usePermissions } from "contexts/auth/usePermissions"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { Stack } from "components/Stack/Stack"; import { Section } from "../Section"; import { AccountUserGroups } from "./AccountUserGroups"; diff --git a/site/src/pages/UserSettingsPage/Sidebar.tsx b/site/src/pages/UserSettingsPage/Sidebar.tsx index a67d7b2bed171..ddad8a2ab5468 100644 --- a/site/src/pages/UserSettingsPage/Sidebar.tsx +++ b/site/src/pages/UserSettingsPage/Sidebar.tsx @@ -13,7 +13,7 @@ import { SidebarNavItem, } from "components/Sidebar/Sidebar"; import { GitIcon } from "components/Icons/GitIcon"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "modules/dashboard/useDashboard"; interface SidebarProps { user: User; diff --git a/site/src/pages/UsersPage/UsersLayout.tsx b/site/src/pages/UsersPage/UsersLayout.tsx index e2a7c00e94bc6..2f8a72d5840fe 100644 --- a/site/src/pages/UsersPage/UsersLayout.tsx +++ b/site/src/pages/UsersPage/UsersLayout.tsx @@ -4,10 +4,10 @@ import GroupAdd from "@mui/icons-material/GroupAddOutlined"; import PersonAdd from "@mui/icons-material/PersonAddOutlined"; import { type FC, Suspense } from "react"; import { Link as RouterLink, Outlet, useNavigate } from "react-router-dom"; -import { USERS_LINK } from "components/Dashboard/Navbar/NavbarView"; -import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader"; -import { useFeatureVisibility } from "hooks/useFeatureVisibility"; import { usePermissions } from "contexts/auth/usePermissions"; +import { USERS_LINK } from "modules/dashboard/Navbar/NavbarView"; +import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; +import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader"; import { Margins } from "components/Margins/Margins"; import { TabLink, Tabs } from "components/Tabs/Tabs"; import { Loader } from "components/Loader/Loader"; diff --git a/site/src/pages/UsersPage/UsersPage.tsx b/site/src/pages/UsersPage/UsersPage.tsx index 165254a359a65..e6547824fcc4d 100644 --- a/site/src/pages/UsersPage/UsersPage.tsx +++ b/site/src/pages/UsersPage/UsersPage.tsx @@ -2,7 +2,7 @@ import { type FC, useState } from "react"; import { Helmet } from "react-helmet-async"; import { useMutation, useQuery, useQueryClient } from "react-query"; import { useSearchParams, useNavigate } from "react-router-dom"; -import { type User } from "api/typesGenerated"; +import type { User } from "api/typesGenerated"; import { roles } from "api/queries/roles"; import { groupsByUserId } from "api/queries/groups"; import { getErrorMessage } from "api/errors"; @@ -17,10 +17,10 @@ import { authMethods, } from "api/queries/users"; import { useOrganizationId } from "contexts/auth/useOrganizationId"; -import { useMe } from "contexts/auth/useMe"; import { usePermissions } from "contexts/auth/usePermissions"; +import { useMe } from "contexts/auth/useMe"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { useFilter } from "components/Filter/filter"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog"; import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog"; import { displayError, displaySuccess } from "components/GlobalSnackbar/utils"; diff --git a/site/src/pages/WorkspaceBuildPage/WorkspaceBuildPageView.tsx b/site/src/pages/WorkspaceBuildPage/WorkspaceBuildPageView.tsx index ed61339d7bee4..ec26222a08921 100644 --- a/site/src/pages/WorkspaceBuildPage/WorkspaceBuildPageView.tsx +++ b/site/src/pages/WorkspaceBuildPage/WorkspaceBuildPageView.tsx @@ -1,7 +1,10 @@ import { type Interpolation, type Theme, useTheme } from "@emotion/react"; -import { BuildAvatar } from "components/BuildAvatar/BuildAvatar"; import { type FC } from "react"; -import { ProvisionerJobLog, WorkspaceBuild } from "api/typesGenerated"; +import type { ProvisionerJobLog, WorkspaceBuild } from "api/typesGenerated"; +import { Link } from "react-router-dom"; +import { displayWorkspaceBuildDuration } from "utils/workspace"; +import { DashboardFullPage } from "modules/dashboard/DashboardLayout"; +import { BuildAvatar } from "components/BuildAvatar/BuildAvatar"; import { Loader } from "components/Loader/Loader"; import { Stack } from "components/Stack/Stack"; import { WorkspaceBuildLogs } from "components/WorkspaceBuildLogs/WorkspaceBuildLogs"; @@ -10,16 +13,13 @@ import { PageHeaderTitle, PageHeaderSubtitle, } from "components/PageHeader/FullWidthPageHeader"; -import { Link } from "react-router-dom"; import { Stats, StatsItem } from "components/Stats/Stats"; -import { displayWorkspaceBuildDuration } from "utils/workspace"; -import { Sidebar, SidebarCaption, SidebarItem } from "./Sidebar"; import { Alert } from "components/Alert/Alert"; -import { DashboardFullPage } from "components/Dashboard/DashboardLayout"; import { WorkspaceBuildData, WorkspaceBuildDataSkeleton, } from "components/WorkspaceBuild/WorkspaceBuildData"; +import { Sidebar, SidebarCaption, SidebarItem } from "./Sidebar"; const sortLogsByCreatedAt = (logs: ProvisionerJobLog[]) => { return [...logs].sort( diff --git a/site/src/pages/WorkspacePage/Workspace.stories.tsx b/site/src/pages/WorkspacePage/Workspace.stories.tsx index 07a320c56c513..9c9b41dbf7416 100644 --- a/site/src/pages/WorkspacePage/Workspace.stories.tsx +++ b/site/src/pages/WorkspacePage/Workspace.stories.tsx @@ -1,14 +1,14 @@ import { action } from "@storybook/addon-actions"; import { Meta, StoryObj } from "@storybook/react"; -import { WatchAgentMetadataContext } from "components/Resources/AgentMetadata"; -import { ProvisionerJobLog } from "api/typesGenerated"; -import * as Mocks from "testHelpers/entities"; -import { Workspace } from "./Workspace"; -import { withReactContext } from "storybook-react-context"; import EventSource from "eventsourcemock"; +import { withReactContext } from "storybook-react-context"; +import type { ProvisionerJobLog } from "api/typesGenerated"; +import * as Mocks from "testHelpers/entities"; import { ProxyContext, getPreferredProxy } from "contexts/ProxyContext"; -import { DashboardProviderContext } from "components/Dashboard/DashboardProvider"; -import { WorkspaceBuildLogsSection } from "pages/WorkspacePage/WorkspaceBuildLogsSection"; +import { DashboardContext } from "modules/dashboard/DashboardProvider"; +import { WatchAgentMetadataContext } from "components/Resources/AgentMetadata"; +import { Workspace } from "./Workspace"; +import { WorkspaceBuildLogsSection } from "./WorkspaceBuildLogsSection"; import { WorkspacePermissions } from "./permissions"; const MockedAppearance = { @@ -38,7 +38,7 @@ const meta: Meta = { }, decorators: [ (Story) => ( - = { > - + ), withReactContext({ Context: WatchAgentMetadataContext, diff --git a/site/src/pages/WorkspacePage/WorkspaceNotifications/WorkspaceNotifications.tsx b/site/src/pages/WorkspacePage/WorkspaceNotifications/WorkspaceNotifications.tsx index 811ce5214bfff..da5af95863070 100644 --- a/site/src/pages/WorkspacePage/WorkspaceNotifications/WorkspaceNotifications.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceNotifications/WorkspaceNotifications.tsx @@ -1,20 +1,20 @@ import { workspaceResolveAutostart } from "api/queries/workspaceQuota"; import { Template, TemplateVersion, Workspace } from "api/typesGenerated"; -import { FC, useEffect, useState } from "react"; +import { type Interpolation, type Theme } from "@emotion/react"; +import { type FC, useEffect, useState } from "react"; import { useQuery } from "react-query"; -import { WorkspacePermissions } from "../permissions"; import dayjs from "dayjs"; -import { useIsWorkspaceActionsEnabled } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "modules/dashboard/useDashboard"; import formatDistanceToNow from "date-fns/formatDistanceToNow"; import InfoOutlined from "@mui/icons-material/InfoOutlined"; import WarningRounded from "@mui/icons-material/WarningRounded"; import { MemoizedInlineMarkdown } from "components/Markdown/Markdown"; +import type { WorkspacePermissions } from "../permissions"; import { NotificationActionButton, NotificationItem, Notifications, } from "./Notifications"; -import { Interpolation, Theme } from "@emotion/react"; type WorkspaceNotificationsProps = { workspace: Workspace; @@ -103,8 +103,10 @@ export const WorkspaceNotifications: FC = ({ } // Dormant - const areActionsEnabled = useIsWorkspaceActionsEnabled(); - if (areActionsEnabled && workspace.dormant_at) { + const { entitlements } = useDashboard(); + const advancedSchedulingEnabled = + entitlements.features["advanced_template_scheduling"].enabled; + if (advancedSchedulingEnabled && workspace.dormant_at) { const formatDate = (dateStr: string, timestamp: boolean): string => { const date = new Date(dateStr); return date.toLocaleDateString(undefined, { diff --git a/site/src/pages/WorkspacePage/WorkspacePage.tsx b/site/src/pages/WorkspacePage/WorkspacePage.tsx index c70f83de6316f..b5aa890021f79 100644 --- a/site/src/pages/WorkspacePage/WorkspacePage.tsx +++ b/site/src/pages/WorkspacePage/WorkspacePage.tsx @@ -1,18 +1,18 @@ import { type FC, useEffect } from "react"; import { useQuery, useQueryClient } from "react-query"; import { useParams } from "react-router-dom"; -import { useEffectEvent } from "hooks/hookPolyfills"; -import { useOrganizationId } from "contexts/auth/useOrganizationId"; import { watchWorkspace } from "api/api"; import type { Workspace } from "api/typesGenerated"; import { workspaceBuildsKey } from "api/queries/workspaceBuilds"; import { templateByName } from "api/queries/templates"; import { workspaceByOwnerAndName } from "api/queries/workspaces"; import { checkAuthorization } from "api/queries/authCheck"; +import { useEffectEvent } from "hooks/hookPolyfills"; +import { useOrganizationId } from "contexts/auth/useOrganizationId"; +import { Navbar } from "modules/dashboard/Navbar/Navbar"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Loader } from "components/Loader/Loader"; import { Margins } from "components/Margins/Margins"; -import { Navbar } from "components/Dashboard/Navbar/Navbar"; import { WorkspacePermissions, workspaceChecks } from "./permissions"; import { WorkspaceReadyPage } from "./WorkspaceReadyPage"; diff --git a/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx b/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx index a39876e1bbcfe..10441590784f7 100644 --- a/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx @@ -4,21 +4,15 @@ import { Helmet } from "react-helmet-async"; import { useMutation, useQuery, useQueryClient } from "react-query"; import { useNavigate } from "react-router-dom"; import { MissingBuildParameters, restartWorkspace } from "api/api"; -import { useFeatureVisibility } from "hooks/useFeatureVisibility"; -import { pageTitle } from "utils/page"; import { getErrorMessage } from "api/errors"; import type * as TypesGen from "api/typesGenerated"; import { templateVersion, templateVersions } from "api/queries/templates"; import { deploymentConfig, deploymentSSHConfig } from "api/queries/deployment"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; -import { - ConfirmDialog, - ConfirmDialogProps, -} from "components/Dialogs/ConfirmDialog/ConfirmDialog"; -import { Alert } from "components/Alert/Alert"; -import { Stack } from "components/Stack/Stack"; import { useMe } from "contexts/auth/useMe"; import { useWorkspaceBuildLogs } from "hooks/useWorkspaceBuildLogs"; +import { useDashboard } from "modules/dashboard/useDashboard"; +import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility"; +import { pageTitle } from "utils/page"; import { activate, changeVersion, @@ -28,9 +22,15 @@ import { startWorkspace, cancelBuild, } from "api/queries/workspaces"; +import { Alert } from "components/Alert/Alert"; +import { Stack } from "components/Stack/Stack"; +import { + ConfirmDialog, + ConfirmDialogProps, +} from "components/Dialogs/ConfirmDialog/ConfirmDialog"; import { displayError } from "components/GlobalSnackbar/utils"; -import { WorkspacePermissions } from "./permissions"; import { ChangeVersionDialog } from "./ChangeVersionDialog"; +import { WorkspacePermissions } from "./permissions"; import { UpdateBuildParametersDialog } from "./UpdateBuildParametersDialog"; import { Workspace } from "./Workspace"; import { WorkspaceBuildLogsSection } from "./WorkspaceBuildLogsSection"; diff --git a/site/src/pages/WorkspacePage/WorkspaceTopbar.tsx b/site/src/pages/WorkspacePage/WorkspaceTopbar.tsx index 96bf6ada94ab4..88e2634ef4418 100644 --- a/site/src/pages/WorkspacePage/WorkspaceTopbar.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceTopbar.tsx @@ -1,6 +1,15 @@ +import Tooltip from "@mui/material/Tooltip"; +import Link from "@mui/material/Link"; +import MonetizationOnOutlined from "@mui/icons-material/MonetizationOnOutlined"; +import DeleteOutline from "@mui/icons-material/DeleteOutline"; +import PersonOutline from "@mui/icons-material/PersonOutline"; +import ArrowBackOutlined from "@mui/icons-material/ArrowBackOutlined"; +import ScheduleOutlined from "@mui/icons-material/ScheduleOutlined"; +import { useTheme } from "@emotion/react"; +import { type FC } from "react"; +import { useQuery } from "react-query"; import { Link as RouterLink } from "react-router-dom"; import type * as TypesGen from "api/typesGenerated"; -import { WorkspaceActions } from "pages/WorkspacePage/WorkspaceActions/WorkspaceActions"; import { Topbar, TopbarAvatar, @@ -9,27 +18,19 @@ import { TopbarIcon, TopbarIconButton, } from "components/FullPageLayout/Topbar"; -import Tooltip from "@mui/material/Tooltip"; -import ArrowBackOutlined from "@mui/icons-material/ArrowBackOutlined"; -import ScheduleOutlined from "@mui/icons-material/ScheduleOutlined"; import { WorkspaceStatusBadge } from "components/WorkspaceStatusBadge/WorkspaceStatusBadge"; import { WorkspaceScheduleControls, shouldDisplayScheduleControls, } from "./WorkspaceScheduleControls"; import { workspaceQuota } from "api/queries/workspaceQuota"; -import { useQuery } from "react-query"; -import MonetizationOnOutlined from "@mui/icons-material/MonetizationOnOutlined"; -import { useTheme } from "@mui/material/styles"; -import Link from "@mui/material/Link"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { displayDormantDeletion } from "utils/dormant"; -import DeleteOutline from "@mui/icons-material/DeleteOutline"; -import PersonOutline from "@mui/icons-material/PersonOutline"; import { Popover, PopoverTrigger } from "components/Popover/Popover"; import { HelpTooltipContent } from "components/HelpTooltip/HelpTooltip"; import { AvatarData } from "components/AvatarData/AvatarData"; import { ExternalAvatar } from "components/Avatar/Avatar"; +import { WorkspaceActions } from "./WorkspaceActions/WorkspaceActions"; import { WorkspaceNotifications } from "./WorkspaceNotifications/WorkspaceNotifications"; import { WorkspacePermissions } from "./permissions"; @@ -64,30 +65,29 @@ export interface WorkspaceProps { latestVersion?: TypesGen.TemplateVersion; } -export const WorkspaceTopbar = (props: WorkspaceProps) => { - const { - handleStart, - handleStop, - handleRestart, - handleDelete, - handleUpdate, - handleCancel, - handleSettings, - handleChangeVersion, - handleDormantActivate, - workspace, - isUpdating, - isRestarting, - canUpdateWorkspace, - canChangeVersions, - canRetryDebugMode, - handleBuildRetry, - handleBuildRetryDebug, - isOwner, - template, - latestVersion, - permissions, - } = props; +export const WorkspaceTopbar: FC = ({ + handleStart, + handleStop, + handleRestart, + handleDelete, + handleUpdate, + handleCancel, + handleSettings, + handleChangeVersion, + handleDormantActivate, + workspace, + isUpdating, + isRestarting, + canUpdateWorkspace, + canChangeVersions, + canRetryDebugMode, + handleBuildRetry, + handleBuildRetryDebug, + isOwner, + template, + latestVersion, + permissions, +}) => { const theme = useTheme(); // Quota diff --git a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx index 077e85c6f80fb..3fba54f8ad951 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPage.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPage.tsx @@ -2,16 +2,16 @@ import { type FC, useEffect, useState } from "react"; import { Helmet } from "react-helmet-async"; import { useQuery } from "react-query"; import { useSearchParams } from "react-router-dom"; -import { templates } from "api/queries/templates"; import type { Workspace } from "api/typesGenerated"; +import { templates } from "api/queries/templates"; import { useOrganizationId } from "contexts/auth/useOrganizationId"; import { usePermissions } from "contexts/auth/usePermissions"; +import { useEffectEvent } from "hooks/hookPolyfills"; import { usePagination } from "hooks/usePagination"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { pageTitle } from "utils/page"; -import { useDashboard } from "components/Dashboard/DashboardProvider"; import { useFilter } from "components/Filter/filter"; import { useUserFilterMenu } from "components/Filter/UserFilter"; -import { useEffectEvent } from "hooks/hookPolyfills"; import { useBatchActions } from "./batchActions"; import { useWorkspacesData, useWorkspaceUpdate } from "./data"; import { useTemplateFilterMenu, useStatusFilterMenu } from "./filter/menus"; diff --git a/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx b/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx index 1b0bf8c814ecc..cfff23823889e 100644 --- a/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx +++ b/site/src/pages/WorkspacesPage/WorkspacesPageView.stories.tsx @@ -19,7 +19,7 @@ import { MockTemplate, } from "testHelpers/entities"; import { WorkspacesPageView } from "./WorkspacesPageView"; -import { DashboardProviderContext } from "components/Dashboard/DashboardProvider"; +import { DashboardContext } from "modules/dashboard/DashboardProvider"; import { ComponentProps } from "react"; import { MockMenu, @@ -141,7 +141,7 @@ const meta: Meta = { }, decorators: [ (Story) => ( - = { }} > - + ), ], }; diff --git a/site/src/pages/WorkspacesPage/filter/filter.tsx b/site/src/pages/WorkspacesPage/filter/filter.tsx index f89e2992c4a6d..112aac6f18e0d 100644 --- a/site/src/pages/WorkspacesPage/filter/filter.tsx +++ b/site/src/pages/WorkspacesPage/filter/filter.tsx @@ -1,9 +1,7 @@ -import { type FC } from "react"; import { useTheme } from "@emotion/react"; -import { useIsWorkspaceActionsEnabled } from "components/Dashboard/DashboardProvider"; +import { type FC } from "react"; +import { useDashboard } from "modules/dashboard/useDashboard"; import { Avatar, type AvatarProps } from "components/Avatar/Avatar"; -import type { TemplateFilterMenu, StatusFilterMenu } from "./menus"; -import type { TemplateOption, StatusOption } from "./options"; import { Filter, FilterMenu, @@ -15,6 +13,8 @@ import { } from "components/Filter/filter"; import { type UserFilterMenu, UserMenu } from "components/Filter/UserFilter"; import { docs } from "utils/docs"; +import type { TemplateFilterMenu, StatusFilterMenu } from "./menus"; +import type { TemplateOption, StatusOption } from "./options"; export const workspaceFilterQuery = { me: "owner:me", @@ -74,8 +74,10 @@ export const WorkspacesFilter: FC = ({ error, menus, }) => { - const actionsEnabled = useIsWorkspaceActionsEnabled(); - const presets = actionsEnabled ? PRESETS_WITH_DORMANT : PRESET_FILTERS; + const { entitlements } = useDashboard(); + const presets = entitlements.features["advanced_template_scheduling"].enabled + ? PRESETS_WITH_DORMANT + : PRESET_FILTERS; return ( { - acc[feature] = { enabled: true, entitlement: "entitled" }; - return acc; - }, - {} as Entitlements["features"], + Object.fromEntries( + features.map((feature) => [ + feature, + { enabled: true, entitlement: "entitled" }, + ]), ), ), }; return ( - - + ); }; diff --git a/site/vite.config.ts b/site/vite.config.ts index 82d32c63a655f..1ca3de51cb292 100644 --- a/site/vite.config.ts +++ b/site/vite.config.ts @@ -84,14 +84,13 @@ export default defineConfig({ alias: { api: path.resolve(__dirname, "./src/api"), components: path.resolve(__dirname, "./src/components"), - hooks: path.resolve(__dirname, "./src/hooks"), contexts: path.resolve(__dirname, "./src/contexts"), - i18n: path.resolve(__dirname, "./src/i18n"), + hooks: path.resolve(__dirname, "./src/hooks"), + modules: path.resolve(__dirname, "./src/modules"), pages: path.resolve(__dirname, "./src/pages"), testHelpers: path.resolve(__dirname, "./src/testHelpers"), theme: path.resolve(__dirname, "./src/theme"), utils: path.resolve(__dirname, "./src/utils"), - xServices: path.resolve(__dirname, "./src/xServices"), }, }, }); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy