refactor: reorganize auth components and hooks (#11717)

This commit is contained in:
Kayla Washburn-Love
2024-01-22 10:43:32 -07:00
committed by GitHub
parent f02561a599
commit f74ef142d0
57 changed files with 264 additions and 262 deletions
-1
View File
@@ -170,7 +170,6 @@ rules:
react/jsx-uses-react: "off"
react/no-unknown-property: ["error", { ignore: ["css"] }]
react/react-in-jsx-scope: "off"
"unicorn/explicit-length-check": "error"
# https://github.com/jsx-eslint/eslint-plugin-react/issues/2628#issuecomment-984160944
no-restricted-syntax:
[
+1 -1
View File
@@ -3,7 +3,7 @@ import { type FC, type ReactNode, useEffect, useState } from "react";
import { HelmetProvider } from "react-helmet-async";
import { AppRouter } from "./AppRouter";
import { ThemeProvider } from "./contexts/ThemeProvider";
import { AuthProvider } from "./contexts/AuthProvider/AuthProvider";
import { AuthProvider } from "./contexts/auth/AuthProvider";
import { ErrorBoundary } from "./components/ErrorBoundary/ErrorBoundary";
import { GlobalSnackbar } from "./components/GlobalSnackbar/GlobalSnackbar";
import "./theme/globalFonts";
+3 -3
View File
@@ -5,17 +5,17 @@ import {
BrowserRouter as Router,
Navigate,
} from "react-router-dom";
import { RequireAuth } from "./contexts/auth/RequireAuth";
import { DashboardLayout } from "./components/Dashboard/DashboardLayout";
import { DeploySettingsLayout } from "./pages/DeploySettingsPage/DeploySettingsLayout";
import { FullScreenLoader } from "./components/Loader/FullScreenLoader";
import { RequireAuth } from "./components/RequireAuth/RequireAuth";
import { UsersLayout } from "./pages/UsersPage/UsersLayout";
import AuditPage from "./pages/AuditPage/AuditPage";
import { DeploySettingsLayout } from "./pages/DeploySettingsPage/DeploySettingsLayout";
import LoginPage from "./pages/LoginPage/LoginPage";
import { SetupPage } from "./pages/SetupPage/SetupPage";
import { TemplateLayout } from "./pages/TemplatePage/TemplateLayout";
import { HealthLayout } from "./pages/HealthPage/HealthLayout";
import TemplatesPage from "./pages/TemplatesPage/TemplatesPage";
import { UsersLayout } from "./pages/UsersPage/UsersLayout";
import UsersPage from "./pages/UsersPage/UsersPage";
import WorkspacesPage from "./pages/WorkspacesPage/WorkspacesPage";
import UserSettingsLayout from "./pages/UserSettingsPage/Layout";
@@ -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 { 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 { usePermissions } from "hooks/usePermissions";
import { dashboardContentBottomPadding } from "theme/constants";
import { docs } from "utils/docs";
import { Navbar } from "./Navbar/Navbar";
@@ -1,9 +1,9 @@
import { type FC } from "react";
import { useQuery } from "react-query";
import { deploymentStats } from "api/queries/deployment";
import { usePermissions } from "hooks/usePermissions";
import { DeploymentBannerView } from "./DeploymentBannerView";
import { health } from "api/queries/debug";
import { deploymentStats } from "api/queries/deployment";
import { usePermissions } from "contexts/auth/usePermissions";
import { DeploymentBannerView } from "./DeploymentBannerView";
export const DeploymentBanner: FC = () => {
const permissions = usePermissions();
@@ -1,10 +1,10 @@
import { type FC } from "react";
import { useAuth } from "contexts/AuthProvider/AuthProvider";
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 { useMe } from "hooks/useMe";
import { usePermissions } from "hooks/usePermissions";
import { NavbarView } from "./NavbarView";
export const Navbar: FC = () => {
@@ -7,19 +7,19 @@ import Button from "@mui/material/Button";
import MenuItem from "@mui/material/MenuItem";
import KeyboardArrowDownOutlined from "@mui/icons-material/KeyboardArrowDownOutlined";
import MenuIcon from "@mui/icons-material/Menu";
import { visuallyHidden } from "@mui/utils";
import { css, type Interpolation, type Theme, useTheme } from "@emotion/react";
import { type FC, type ReactNode, useRef, useState } from "react";
import { NavLink, useLocation, useNavigate } from "react-router-dom";
import { BUTTON_SM_HEIGHT, navHeight } from "theme/constants";
import type * as TypesGen from "api/typesGenerated";
import { usePermissions } from "contexts/auth/usePermissions";
import type { ProxyContextValue } from "contexts/ProxyContext";
import { Abbr } from "components/Abbr/Abbr";
import { displayError } from "components/GlobalSnackbar/utils";
import { ProxyStatusLatency } from "components/ProxyStatusLatency/ProxyStatusLatency";
import { CoderIcon } from "components/Icons/CoderIcon";
import { usePermissions } from "hooks/usePermissions";
import { UserDropdown } from "./UserDropdown/UserDropdown";
import { visuallyHidden } from "@mui/utils";
import { Abbr } from "components/Abbr/Abbr";
export const USERS_LINK = `/users?filter=${encodeURIComponent(
"status:active",
+4 -4
View File
@@ -1,10 +1,10 @@
import { type FC } from "react";
import { useMe } from "hooks";
import { BaseOption } from "./options";
import { getUsers } from "api/api";
import { UseFilterMenuOptions, useFilterMenu } from "./menu";
import { useMe } from "contexts/auth/useMe";
import { UserAvatar } from "../UserAvatar/UserAvatar";
import { FilterSearchMenu, OptionItem } from "./filter";
import { UserAvatar } from "components/UserAvatar/UserAvatar";
import { UseFilterMenuOptions, useFilterMenu } from "./menu";
import { BaseOption } from "./options";
export type UserOption = BaseOption & {
avatarUrl?: string;
+6 -6
View File
@@ -1,17 +1,17 @@
import { useQuery } from "react-query";
import { getWorkspaceProxies, getWorkspaceProxyRegions } from "api/api";
import { Region, WorkspaceProxy } from "api/typesGenerated";
import {
createContext,
FC,
PropsWithChildren,
type FC,
type PropsWithChildren,
useCallback,
useContext,
useEffect,
useState,
} from "react";
import { useQuery } from "react-query";
import { getWorkspaceProxies, getWorkspaceProxyRegions } from "api/api";
import type { Region, WorkspaceProxy } from "api/typesGenerated";
import { usePermissions } from "contexts/auth/usePermissions";
import { ProxyLatencyReport, useProxyLatency } from "./useProxyLatency";
import { usePermissions } from "hooks/usePermissions";
export interface ProxyContextValue {
// proxy is **always** the workspace proxy that should be used.
+1 -1
View File
@@ -14,7 +14,7 @@ import {
useState,
} from "react";
import themes, { DEFAULT_THEME, type Theme } from "theme";
import { AuthContext } from "./AuthProvider/AuthProvider";
import { AuthContext } from "./auth/AuthProvider";
/**
*
@@ -3,7 +3,6 @@ import {
type FC,
type PropsWithChildren,
useCallback,
useContext,
} from "react";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { checkAuthorization } from "api/queries/authCheck";
@@ -129,13 +128,3 @@ export const AuthProvider: FC<PropsWithChildren> = ({ children }) => {
</AuthContext.Provider>
);
};
export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) {
throw new Error("useAuth should be used inside of <AuthProvider />");
}
return context;
};
@@ -3,10 +3,10 @@ import { type FC, useEffect } from "react";
import { Outlet, Navigate, useLocation } from "react-router-dom";
import { embedRedirect } from "utils/redirect";
import { isApiError } from "api/errors";
import { useAuth } from "contexts/AuthProvider/AuthProvider";
import { ProxyProvider } from "contexts/ProxyContext";
import { DashboardProvider } from "../Dashboard/DashboardProvider";
import { FullScreenLoader } from "../Loader/FullScreenLoader";
import { DashboardProvider } from "components/Dashboard/DashboardProvider";
import { FullScreenLoader } from "components/Loader/FullScreenLoader";
import { useAuth } from "./useAuth";
export const RequireAuth: FC = () => {
const { signOut, isSigningOut, isSignedOut, isSignedIn, isLoading } =
@@ -1,8 +1,8 @@
import { FC } from "react";
import { type FC, type ReactNode } from "react";
import { Navigate } from "react-router-dom";
export interface RequirePermissionProps {
children: JSX.Element;
children?: ReactNode;
isFeatureVisible: boolean;
}
@@ -16,6 +16,6 @@ export const RequirePermission: FC<RequirePermissionProps> = ({
if (!isFeatureVisible) {
return <Navigate to="/workspaces" />;
} else {
return children;
return <>{children}</>;
}
};
+12
View File
@@ -0,0 +1,12 @@
import { useContext } from "react";
import { AuthContext } from "./AuthProvider";
export const useAuth = () => {
const context = useContext(AuthContext);
if (!context) {
throw new Error("useAuth should be used inside of <AuthProvider />");
}
return context;
};
@@ -1,5 +1,5 @@
import type { User } from "api/typesGenerated";
import { useAuth } from "contexts/AuthProvider/AuthProvider";
import { useAuth } from "./useAuth";
export const useMe = (): User => {
const { user } = useAuth();
@@ -0,0 +1,11 @@
import { useMe } from "./useMe";
export const useOrganizationId = (): string => {
const me = useMe();
if (me.organization_ids.length < 1) {
throw new Error("User is not a member of any organizations");
}
return me.organization_ids[0];
};
@@ -1,5 +1,5 @@
import { useAuth } from "contexts/AuthProvider/AuthProvider";
import type { Permissions } from "contexts/AuthProvider/permissions";
import { useAuth } from "./useAuth";
import type { Permissions } from "./permissions";
export const usePermissions = (): Permissions => {
const { permissions } = useAuth();
-3
View File
@@ -2,8 +2,5 @@ export * from "./useClickable";
export * from "./useClickableTableRow";
export * from "./useClipboard";
export * from "./useFeatureVisibility";
export * from "./useMe";
export * from "./useOrganizationId";
export * from "./usePagination";
export * from "./usePermissions";
export * from "./useTab";
-6
View File
@@ -1,6 +0,0 @@
import { useMe } from "./useMe";
export const useOrganizationId = (): string => {
const user = useMe();
return user.organization_ids[0];
};
@@ -1,4 +1,6 @@
import { type FC } from "react";
import { useQuery, useMutation } from "react-query";
import { useNavigate, useSearchParams } from "react-router-dom";
import {
templateVersionLogs,
templateByName,
@@ -7,15 +9,14 @@ import {
JobError,
createTemplate,
} from "api/queries/templates";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { useOrganizationId } from "hooks";
import { useNavigate, useSearchParams } from "react-router-dom";
import { CreateTemplateForm } from "./CreateTemplateForm";
import { Loader } from "components/Loader/Loader";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { CreateTemplateForm } from "./CreateTemplateForm";
import { firstVersionFromFile, getFormPermissions, newTemplate } from "./utils";
export const DuplicateTemplateView = () => {
export const DuplicateTemplateView: FC = () => {
const navigate = useNavigate();
const organizationId = useOrganizationId();
const [searchParams] = useSearchParams();
@@ -1,4 +1,6 @@
import { type FC } from "react";
import { useQuery, useMutation } from "react-query";
import { useNavigate, useSearchParams } from "react-router-dom";
import {
templateVersionLogs,
JobError,
@@ -6,19 +8,18 @@ import {
templateExamples,
templateVersionVariables,
} from "api/queries/templates";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { useOrganizationId } from "hooks";
import { useNavigate, useSearchParams } from "react-router-dom";
import { CreateTemplateForm } from "./CreateTemplateForm";
import { Loader } from "components/Loader/Loader";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { CreateTemplateForm } from "./CreateTemplateForm";
import {
firstVersionFromExample,
getFormPermissions,
newTemplate,
} from "./utils";
export const ImportStarterTemplateView = () => {
export const ImportStarterTemplateView: FC = () => {
const navigate = useNavigate();
const organizationId = useOrganizationId();
const [searchParams] = useSearchParams();
@@ -1,16 +1,16 @@
import { useQuery, useMutation } from "react-query";
import { useNavigate } from "react-router-dom";
import {
templateVersionLogs,
JobError,
createTemplate,
templateVersionVariables,
} from "api/queries/templates";
import { useOrganizationId } from "hooks";
import { useNavigate } from "react-router-dom";
import { CreateTemplateForm } from "./CreateTemplateForm";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { firstVersionFromFile, getFormPermissions, newTemplate } from "./utils";
import { uploadFile } from "api/queries/files";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { CreateTemplateForm } from "./CreateTemplateForm";
import { firstVersionFromFile, getFormPermissions, newTemplate } from "./utils";
export const UploadTemplateView = () => {
const navigate = useNavigate();
@@ -1,13 +1,13 @@
import { useOrganizationId } from "hooks/useOrganizationId";
import { FC } from "react";
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { useNavigate } from "react-router-dom";
import { CreateUserForm } from "./CreateUserForm";
import { Margins } from "components/Margins/Margins";
import { pageTitle } from "utils/page";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { useNavigate } from "react-router-dom";
import { pageTitle } from "utils/page";
import { authMethods, createUser } from "api/queries/users";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { Margins } from "components/Margins/Margins";
import { displaySuccess } from "components/GlobalSnackbar/utils";
import { CreateUserForm } from "./CreateUserForm";
export const Language = {
unknownError: "Oops, an unknown error occurred.",
@@ -1,34 +1,34 @@
import {
TemplateVersionParameter,
Workspace,
WorkspaceBuildParameter,
} from "api/typesGenerated";
import { useMe } from "hooks/useMe";
import { useOrganizationId } from "hooks/useOrganizationId";
import { type FC, useCallback, useState, useEffect } from "react";
import { Helmet } from "react-helmet-async";
import { useNavigate, useParams, useSearchParams } from "react-router-dom";
import { pageTitle } from "utils/page";
import { CreateWorkspacePageView } from "./CreateWorkspacePageView";
import { Loader } from "components/Loader/Loader";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { useMutation, useQuery, useQueryClient } from "react-query";
import {
uniqueNamesGenerator,
animals,
colors,
NumberDictionary,
} from "unique-names-generator";
import { useMutation, useQuery, useQueryClient } from "react-query";
import type {
TemplateVersionParameter,
Workspace,
WorkspaceBuildParameter,
} from "api/typesGenerated";
import { useMe } from "contexts/auth/useMe";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { pageTitle } from "utils/page";
import { checkAuthorization } from "api/queries/authCheck";
import {
templateByName,
templateVersionExternalAuth,
richParameters,
} from "api/queries/templates";
import { autoCreateWorkspace, createWorkspace } from "api/queries/workspaces";
import { checkAuthorization } from "api/queries/authCheck";
import { CreateWSPermissions, createWorkspaceChecks } from "./permissions";
import { paramsUsedToCreateWorkspace } from "utils/workspace";
import { useEffectEvent } from "hooks/hookPolyfills";
import { paramsUsedToCreateWorkspace } from "utils/workspace";
import { Loader } from "components/Loader/Loader";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { CreateWSPermissions, createWorkspaceChecks } from "./permissions";
import { CreateWorkspacePageView } from "./CreateWorkspacePageView";
export const createWorkspaceModes = ["form", "auto", "duplicate"] as const;
export type CreateWorkspaceMode = (typeof createWorkspaceModes)[number];
@@ -1,14 +1,14 @@
import { createContext, type FC, Suspense, useContext } from "react";
import { useQuery } from "react-query";
import { Outlet } from "react-router-dom";
import { DeploymentConfig } from "api/api";
import { deploymentConfig } from "api/queries/deployment";
import { RequirePermission } from "contexts/auth/RequirePermission";
import { usePermissions } from "contexts/auth/usePermissions";
import { Loader } from "components/Loader/Loader";
import { Margins } from "components/Margins/Margins";
import { Stack } from "components/Stack/Stack";
import { Sidebar } from "./Sidebar";
import { createContext, Suspense, useContext, FC } from "react";
import { Loader } from "components/Loader/Loader";
import { RequirePermission } from "components/RequirePermission/RequirePermission";
import { usePermissions } from "hooks/usePermissions";
import { Outlet } from "react-router-dom";
import { DeploymentConfig } from "api/api";
import { useQuery } from "react-query";
import { deploymentConfig } from "api/queries/deployment";
type DeploySettingsContextValue = {
deploymentValues: DeploymentConfig;
@@ -1,18 +1,18 @@
import Button from "@mui/material/Button";
import { useQuery, useQueryClient } from "react-query";
import { usePermissions } from "hooks";
import { isAxiosError } from "axios";
import { type FC } from "react";
import { useParams, useSearchParams } from "react-router-dom";
import ExternalAuthPageView from "./ExternalAuthPageView";
import { ApiErrorResponse } from "api/errors";
import { isAxiosError } from "axios";
import Button from "@mui/material/Button";
import { SignInLayout } from "components/SignInLayout/SignInLayout";
import { Welcome } from "components/Welcome/Welcome";
import {
externalAuthDevice,
externalAuthProvider,
exchangeExternalAuthDevice,
} from "api/queries/externalAuth";
import { usePermissions } from "contexts/auth/usePermissions";
import { SignInLayout } from "components/SignInLayout/SignInLayout";
import { Welcome } from "components/Welcome/Welcome";
import ExternalAuthPageView from "./ExternalAuthPageView";
const ExternalAuthPage: FC = () => {
const { provider } = useParams() as { provider: string };
@@ -1,11 +1,11 @@
import { useOrganizationId } from "hooks/useOrganizationId";
import { FC } from "react";
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { useMutation, useQueryClient } from "react-query";
import { useNavigate } from "react-router-dom";
import { createGroup } from "api/queries/groups";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { pageTitle } from "utils/page";
import CreateGroupPageView from "./CreateGroupPageView";
import { useMutation, useQueryClient } from "react-query";
import { createGroup } from "api/queries/groups";
export const CreateGroupPage: FC = () => {
const queryClient = useQueryClient();
+8 -8
View File
@@ -1,14 +1,14 @@
import { useFeatureVisibility } from "hooks/useFeatureVisibility";
import { useOrganizationId } from "hooks/useOrganizationId";
import { usePermissions } from "hooks/usePermissions";
import { FC, useEffect } from "react";
import { type FC, useEffect } from "react";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "utils/page";
import GroupsPageView from "./GroupsPageView";
import { useQuery } from "react-query";
import { groups } from "api/queries/groups";
import { displayError } from "components/GlobalSnackbar/utils";
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 { displayError } from "components/GlobalSnackbar/utils";
import GroupsPageView from "./GroupsPageView";
export const GroupsPage: FC = () => {
const organizationId = useOrganizationId();
+1 -1
View File
@@ -1,7 +1,7 @@
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { Navigate, useLocation, useNavigate } from "react-router-dom";
import { useAuth } from "contexts/AuthProvider/AuthProvider";
import { useAuth } from "contexts/auth/useAuth";
import { getApplicationName } from "utils/appearance";
import { retrieveRedirect } from "utils/redirect";
import { LoginPageView } from "./LoginPageView";
+1 -1
View File
@@ -4,7 +4,7 @@ import { useMutation } from "react-query";
import { Navigate, useNavigate } from "react-router-dom";
import { pageTitle } from "utils/page";
import { createFirstUser } from "api/queries/users";
import { useAuth } from "contexts/AuthProvider/AuthProvider";
import { useAuth } from "contexts/auth/useAuth";
import { FullScreenLoader } from "components/Loader/FullScreenLoader";
import { SetupPageView } from "./SetupPageView";
@@ -1,11 +1,11 @@
import { useOrganizationId } from "hooks/useOrganizationId";
import { FC } from "react";
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { useParams } from "react-router-dom";
import { pageTitle } from "utils/page";
import { StarterTemplatePageView } from "./StarterTemplatePageView";
import { useQuery } from "react-query";
import { useParams } from "react-router-dom";
import { templateExamples } from "api/queries/templates";
import { pageTitle } from "utils/page";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { StarterTemplatePageView } from "./StarterTemplatePageView";
const StarterTemplatePage: FC = () => {
const { exampleId } = useParams() as { exampleId: string };
@@ -1,11 +1,11 @@
import { useOrganizationId } from "hooks/useOrganizationId";
import { FC } from "react";
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "utils/page";
import { StarterTemplatesPageView } from "./StarterTemplatesPageView";
import { useQuery } from "react-query";
import { templateExamples } from "api/queries/templates";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { pageTitle } from "utils/page";
import { getTemplatesByTag } from "utils/starterTemplates";
import { StarterTemplatesPageView } from "./StarterTemplatesPageView";
const StarterTemplatesPage: FC = () => {
const organizationId = useOrganizationId();
@@ -1,15 +1,15 @@
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { useQuery } from "react-query";
import { previousTemplateVersion, templateFiles } from "api/queries/templates";
import { Loader } from "components/Loader/Loader";
import {
TemplateFiles,
useFileTab,
} from "components/TemplateFiles/TemplateFiles";
import { useTemplateLayoutContext } from "pages/TemplatePage/TemplateLayout";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { getTemplatePageTitle } from "../utils";
import { useQuery } from "react-query";
import { previousTemplateVersion, templateFiles } from "api/queries/templates";
import { useOrganizationId } from "hooks";
const TemplateFilesPage: FC = () => {
const orgId = useOrganizationId();
@@ -13,12 +13,12 @@ import {
getTemplateByName,
getTemplateVersion,
} from "api/api";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { Margins } from "components/Margins/Margins";
import { Loader } from "components/Loader/Loader";
import { useOrganizationId } from "hooks/useOrganizationId";
import { TemplatePageHeader } from "./TemplatePageHeader";
import { TabLink, Tabs } from "components/Tabs/Tabs";
import { TemplatePageHeader } from "./TemplatePageHeader";
const templatePermissions = (
templateId: string,
@@ -1,16 +1,16 @@
import { useMutation, useQueryClient } from "react-query";
import { updateTemplateMeta } from "api/api";
import { UpdateTemplateMeta } from "api/typesGenerated";
import { displaySuccess } from "components/GlobalSnackbar/utils";
import { FC } from "react";
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 { displaySuccess } from "components/GlobalSnackbar/utils";
import { useTemplateSettings } from "../TemplateSettingsLayout";
import { TemplateSettingsPageView } from "./TemplateSettingsPageView";
import { templateByNameKey } from "api/queries/templates";
import { useOrganizationId } from "hooks";
import { useDashboard } from "components/Dashboard/DashboardProvider";
export const TemplateSettingsPage: FC = () => {
const { template: templateName } = useParams() as { template: string };
@@ -1,19 +1,19 @@
import Button from "@mui/material/Button";
import Link from "@mui/material/Link";
import ArrowRightAltOutlined from "@mui/icons-material/ArrowRightAltOutlined";
import { Paywall } from "components/Paywall/Paywall";
import { Stack } from "components/Stack/Stack";
import { useFeatureVisibility } from "hooks/useFeatureVisibility";
import { useOrganizationId } from "hooks/useOrganizationId";
import { FC } from "react";
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "utils/page";
import { useTemplateSettings } from "../TemplateSettingsLayout";
import { TemplatePermissionsPageView } from "./TemplatePermissionsPageView";
import { docs } from "utils/docs";
import { useMutation, useQuery, useQueryClient } from "react-query";
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 { pageTitle } from "utils/page";
import { docs } from "utils/docs";
import { useTemplateSettings } from "../TemplateSettingsLayout";
import { TemplatePermissionsPageView } from "./TemplatePermissionsPageView";
export const TemplatePermissionsPage: FC<
React.PropsWithChildren<unknown>
@@ -1,16 +1,16 @@
import { useMutation, useQueryClient } from "react-query";
import { updateTemplateMeta } from "api/api";
import { UpdateTemplateMeta } from "api/typesGenerated";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { displaySuccess } from "components/GlobalSnackbar/utils";
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 { displaySuccess } from "components/GlobalSnackbar/utils";
import { useTemplateSettings } from "../TemplateSettingsLayout";
import { TemplateSchedulePageView } from "./TemplateSchedulePageView";
import { useOrganizationId } from "hooks";
import { templateByNameKey } from "api/queries/templates";
const TemplateSchedulePage: FC = () => {
const { template: templateName } = useParams() as { template: string };
@@ -1,16 +1,16 @@
import { createContext, type FC, Suspense, useContext } from "react";
import { Helmet } from "react-helmet-async";
import { useQuery } from "react-query";
import { pageTitle } from "utils/page";
import { Stack } from "components/Stack/Stack";
import { Loader } from "components/Loader/Loader";
import { Outlet, useParams } from "react-router-dom";
import { Margins } from "components/Margins/Margins";
import { useOrganizationId } from "hooks/useOrganizationId";
import { pageTitle } from "utils/page";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { checkAuthorization } from "api/queries/authCheck";
import { templateByName } from "api/queries/templates";
import type { AuthorizationResponse, Template } from "api/typesGenerated";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { checkAuthorization } from "api/queries/authCheck";
import { Loader } from "components/Loader/Loader";
import { Margins } from "components/Margins/Margins";
import { Stack } from "components/Stack/Stack";
import { Sidebar } from "./Sidebar";
const TemplateSettings = createContext<
@@ -1,25 +1,25 @@
import {
import { useCallback, type FC } from "react";
import { Helmet } from "react-helmet-async";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { useNavigate, useParams } from "react-router-dom";
import type {
CreateTemplateVersionRequest,
TemplateVersionVariable,
VariableValue,
} from "api/typesGenerated";
import { displaySuccess } from "components/GlobalSnackbar/utils";
import { useOrganizationId } from "hooks/useOrganizationId";
import { useCallback, type FC } from "react";
import { Helmet } from "react-helmet-async";
import { useNavigate, useParams } from "react-router-dom";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { pageTitle } from "utils/page";
import { useTemplateSettings } from "../TemplateSettingsLayout";
import { TemplateVariablesPageView } from "./TemplateVariablesPageView";
import {
createAndBuildTemplateVersion,
templateVersion,
templateVersionVariables,
updateActiveTemplateVersion,
} from "api/queries/templates";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { Loader } from "components/Loader/Loader";
import { useTemplateSettings } from "../TemplateSettingsLayout";
import { TemplateVariablesPageView } from "./TemplateVariablesPageView";
export const TemplateVariablesPage: FC = () => {
const { template: templateName } = useParams() as {
@@ -1,10 +1,20 @@
import { TemplateVersionEditor } from "./TemplateVersionEditor";
import { useOrganizationId } from "hooks/useOrganizationId";
import { FC, useEffect, useState } from "react";
import { type FC, useEffect, useState } from "react";
import { Helmet } from "react-helmet-async";
import { useNavigate, useParams } from "react-router-dom";
import { pageTitle } from "utils/page";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { useNavigate, useParams } from "react-router-dom";
import { TemplateVersionEditor } from "./TemplateVersionEditor";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { pageTitle } from "utils/page";
import {
patchTemplateVersion,
updateActiveTemplateVersion,
watchBuildLogsByTemplateVersionId,
} from "api/api";
import type {
PatchTemplateVersionRequest,
ProvisionerJobLog,
TemplateVersion,
} from "api/typesGenerated";
import {
createTemplateVersion,
resources,
@@ -19,16 +29,6 @@ import {
createTemplateVersionFileTree,
isAllowedFile,
} from "utils/templateVersion";
import {
patchTemplateVersion,
updateActiveTemplateVersion,
watchBuildLogsByTemplateVersionId,
} from "api/api";
import {
PatchTemplateVersionRequest,
ProvisionerJobLog,
TemplateVersion,
} from "api/typesGenerated";
import { displayError } from "components/GlobalSnackbar/utils";
import { FullScreenLoader } from "components/Loader/FullScreenLoader";
@@ -1,18 +1,18 @@
import { usePermissions } from "hooks/usePermissions";
import { useOrganizationId } from "hooks/useOrganizationId";
import { type FC, useMemo } from "react";
import { Helmet } from "react-helmet-async";
import { useParams } from "react-router-dom";
import { pageTitle } from "utils/page";
import TemplateVersionPageView from "./TemplateVersionPageView";
import { useQuery } from "react-query";
import { useParams } from "react-router-dom";
import { usePermissions } from "contexts/auth/usePermissions";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { pageTitle } from "utils/page";
import { useFileTab } from "components/TemplateFiles/TemplateFiles";
import TemplateVersionPageView from "./TemplateVersionPageView";
import {
templateByName,
templateFiles,
templateVersion,
templateVersionByName,
} from "api/queries/templates";
import { useFileTab } from "components/TemplateFiles/TemplateFiles";
type Params = {
version: string;
@@ -1,11 +1,11 @@
import { useOrganizationId } from "hooks/useOrganizationId";
import { usePermissions } from "hooks/usePermissions";
import { FC } from "react";
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { useQuery } from "react-query";
import { templateExamples, templates } from "api/queries/templates";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { usePermissions } from "contexts/auth/usePermissions";
import { pageTitle } from "utils/page";
import { TemplatesPageView } from "./TemplatesPageView";
import { templateExamples, templates } from "api/queries/templates";
import { useQuery } from "react-query";
export const TemplatesPage: FC = () => {
const organizationId = useOrganizationId();
@@ -1,12 +1,12 @@
import { Stack } from "@mui/system";
import { type FC } from "react";
import { useQuery } from "react-query";
import { useOrganizationId } from "hooks";
import { useMe } from "hooks/useMe";
import { usePermissions } from "hooks/usePermissions";
import { groupsForUser } from "api/queries/groups";
import { useAuth } from "contexts/AuthProvider/AuthProvider";
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 { Stack } from "components/Stack/Stack";
import { Section } from "../Section";
import { AccountUserGroups } from "./AccountUserGroups";
import { AccountForm } from "./AccountForm";
@@ -3,7 +3,7 @@ import { type FC } from "react";
import { useMutation, useQueryClient } from "react-query";
import { updateAppearanceSettings } from "api/queries/users";
import { Stack } from "components/Stack/Stack";
import { useMe } from "hooks";
import { useMe } from "contexts/auth/useMe";
import { Section } from "../Section";
import { AppearanceForm } from "./AppearanceForm";
+1 -1
View File
@@ -2,7 +2,7 @@ import { type FC, Suspense } from "react";
import { Outlet } from "react-router-dom";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "utils/page";
import { useMe } from "hooks/useMe";
import { useMe } from "contexts/auth/useMe";
import { Loader } from "components/Loader/Loader";
import { Margins } from "components/Margins/Margins";
import { Stack } from "components/Stack/Stack";
@@ -1,7 +1,7 @@
import { type FC } from "react";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { useMe } from "hooks/useMe";
import { useMe } from "contexts/auth/useMe";
import { Loader } from "components/Loader/Loader";
import {
updateUserQuietHoursSchedule,
@@ -2,7 +2,7 @@ import { type ComponentProps, type FC } from "react";
import { useMutation, useQuery } from "react-query";
import { getUserLoginType } from "api/api";
import { authMethods, updatePassword } from "api/queries/users";
import { useMe } from "hooks/useMe";
import { useMe } from "contexts/auth/useMe";
import { Loader } from "components/Loader/Loader";
import { Stack } from "components/Stack/Stack";
import { displaySuccess } from "components/GlobalSnackbar/utils";
+3 -3
View File
@@ -2,12 +2,12 @@ import Button from "@mui/material/Button";
import Link from "@mui/material/Link";
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 "hooks/usePermissions";
import { FC, Suspense } from "react";
import { Link as RouterLink, Outlet, useNavigate } from "react-router-dom";
import { usePermissions } from "contexts/auth/usePermissions";
import { Margins } from "components/Margins/Margins";
import { TabLink, Tabs } from "components/Tabs/Tabs";
import { Loader } from "components/Loader/Loader";
+14 -17
View File
@@ -1,5 +1,7 @@
import { type FC, type PropsWithChildren, useState } from "react";
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 { roles } from "api/queries/roles";
import { groupsByUserId } from "api/queries/groups";
@@ -14,28 +16,23 @@ import {
updateRoles,
authMethods,
} from "api/queries/users";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { useSearchParams, useNavigate } from "react-router-dom";
import { useOrganizationId } from "hooks";
import { useMe } from "hooks/useMe";
import { usePermissions } from "hooks/usePermissions";
import { useStatusFilterMenu } from "./UsersFilter";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { useMe } from "contexts/auth/useMe";
import { usePermissions } from "contexts/auth/usePermissions";
import { useFilter } from "components/Filter/filter";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { generateRandomString } from "utils/random";
import { Helmet } from "react-helmet-async";
import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog";
import { isNonInitialPage } from "components/PaginationWidget/utils";
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
import { ResetPasswordDialog } from "./ResetPasswordDialog";
import { pageTitle } from "utils/page";
import { UsersPageView } from "./UsersPageView";
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
import { isNonInitialPage } from "components/PaginationWidget/utils";
import { usePaginatedQuery } from "hooks/usePaginatedQuery";
import { pageTitle } from "utils/page";
import { generateRandomString } from "utils/random";
import { ResetPasswordDialog } from "./ResetPasswordDialog";
import { useStatusFilterMenu } from "./UsersFilter";
import { UsersPageView } from "./UsersPageView";
export const UsersPage: FC<PropsWithChildren> = () => {
export const UsersPage: FC = () => {
const queryClient = useQueryClient();
const navigate = useNavigate();
+11 -11
View File
@@ -1,20 +1,20 @@
import { Loader } from "components/Loader/Loader";
import { FC, useEffect } from "react";
import { useParams } from "react-router-dom";
import { WorkspaceReadyPage } from "./WorkspaceReadyPage";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { useOrganizationId } from "hooks";
import { Margins } from "components/Margins/Margins";
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 { WorkspacePermissions, workspaceChecks } from "./permissions";
import { watchWorkspace } from "api/api";
import { Workspace } from "api/typesGenerated";
import { useEffectEvent } from "hooks/hookPolyfills";
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";
export const WorkspacePage: FC = () => {
const queryClient = useQueryClient();
@@ -1,23 +1,23 @@
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { useFeatureVisibility } from "hooks/useFeatureVisibility";
import dayjs from "dayjs";
import { type FC, useEffect, useState } from "react";
import { Helmet } from "react-helmet-async";
import { useNavigate } from "react-router-dom";
import { Workspace } from "./Workspace";
import { pageTitle } from "utils/page";
import { UpdateBuildParametersDialog } from "./UpdateBuildParametersDialog";
import { ChangeVersionDialog } from "./ChangeVersionDialog";
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 * as TypesGen from "api/typesGenerated";
import { WorkspaceBuildLogsSection } from "./WorkspaceBuildLogsSection";
import { templateVersion, templateVersions } from "api/queries/templates";
import { Alert } from "components/Alert/Alert";
import { Stack } from "components/Stack/Stack";
import { useMe } from "contexts/auth/useMe";
import { useWorkspaceBuildLogs } from "hooks/useWorkspaceBuildLogs";
import {
activate,
@@ -28,13 +28,13 @@ import {
startWorkspace,
cancelBuild,
} from "api/queries/workspaces";
import { getErrorMessage } from "api/errors";
import { displayError } from "components/GlobalSnackbar/utils";
import { deploymentConfig, deploymentSSHConfig } from "api/queries/deployment";
import { WorkspacePermissions } from "./permissions";
import { ChangeVersionDialog } from "./ChangeVersionDialog";
import { UpdateBuildParametersDialog } from "./UpdateBuildParametersDialog";
import { Workspace } from "./Workspace";
import { WorkspaceBuildLogsSection } from "./WorkspaceBuildLogsSection";
import { WorkspaceDeleteDialog } from "./WorkspaceDeleteDialog";
import dayjs from "dayjs";
import { useMe } from "hooks";
interface WorkspaceReadyPageProps {
template: TypesGen.Template;
@@ -1,22 +1,23 @@
import { usePagination } from "hooks/usePagination";
import { Workspace } from "api/typesGenerated";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { type FC, useEffect, useState } from "react";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "utils/page";
import { useWorkspacesData, useWorkspaceUpdate } from "./data";
import { WorkspacesPageView } from "./WorkspacesPageView";
import { useOrganizationId, usePermissions } from "hooks";
import { useTemplateFilterMenu, useStatusFilterMenu } from "./filter/menus";
import { useQuery } from "react-query";
import { useSearchParams } from "react-router-dom";
import { templates } from "api/queries/templates";
import type { Workspace } from "api/typesGenerated";
import { useOrganizationId } from "contexts/auth/useOrganizationId";
import { usePermissions } from "contexts/auth/usePermissions";
import { usePagination } from "hooks/usePagination";
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 { useQuery } from "react-query";
import { templates } from "api/queries/templates";
import { useBatchActions } from "./batchActions";
import { useWorkspacesData, useWorkspaceUpdate } from "./data";
import { useTemplateFilterMenu, useStatusFilterMenu } from "./filter/menus";
import { BatchDeleteConfirmation } from "./BatchDeleteConfirmation";
import { BatchUpdateConfirmation } from "./BatchUpdateConfirmation";
import { WorkspacesPageView } from "./WorkspacesPageView";
function useSafeSearchParams() {
// Have to wrap setSearchParams because React Router doesn't make sure that
+1 -1
View File
@@ -6,7 +6,7 @@ import {
import { FieldError } from "api/errors";
import type * as TypesGen from "api/typesGenerated";
import range from "lodash/range";
import { Permissions } from "contexts/AuthProvider/permissions";
import type { Permissions } from "contexts/auth/permissions";
import { TemplateVersionFiles } from "utils/templateVersion";
import { FileTree } from "utils/filetree";
import { ProxyLatencyReport } from "contexts/useProxyLatency";
+1 -1
View File
@@ -1,6 +1,6 @@
import { rest } from "msw";
import { CreateWorkspaceBuildRequest } from "api/typesGenerated";
import { permissionsToCheck } from "contexts/AuthProvider/permissions";
import { permissionsToCheck } from "contexts/auth/permissions";
import * as M from "./entities";
import { MockGroup, MockWorkspaceQuota } from "./entities";
import fs from "fs";
+1 -1
View File
@@ -9,7 +9,7 @@ import { QueryClient } from "react-query";
import { AppProviders } from "App";
import { ThemeProvider } from "contexts/ThemeProvider";
import { DashboardLayout } from "components/Dashboard/DashboardLayout";
import { RequireAuth } from "components/RequireAuth/RequireAuth";
import { RequireAuth } from "contexts/auth/RequireAuth";
import { TemplateSettingsLayout } from "pages/TemplateSettingsPage/TemplateSettingsLayout";
import { WorkspaceSettingsLayout } from "pages/WorkspaceSettingsPage/WorkspaceSettingsLayout";
import {