mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: expose all organization ids from AuthContext (#13268)
This commit is contained in:
@@ -30,7 +30,7 @@ export type AuthContextValue = {
|
||||
isUpdatingProfile: boolean;
|
||||
user: User | undefined;
|
||||
permissions: Permissions | undefined;
|
||||
organizationId: string | undefined;
|
||||
organizationIds: readonly string[] | undefined;
|
||||
signInError: unknown;
|
||||
updateProfileError: unknown;
|
||||
signOut: () => void;
|
||||
@@ -119,7 +119,7 @@ export const AuthProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
permissions: permissionsQuery.data as Permissions | undefined,
|
||||
signInError: loginMutation.error,
|
||||
updateProfileError: updateProfileMutation.error,
|
||||
organizationId: userQuery.data?.organization_ids[0],
|
||||
organizationIds: userQuery.data?.organization_ids,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -45,7 +45,7 @@ const createAuthWrapper = (override: Partial<AuthContextValue>) => {
|
||||
isUpdatingProfile: false,
|
||||
permissions: undefined,
|
||||
authMethods: undefined,
|
||||
organizationId: undefined,
|
||||
organizationIds: undefined,
|
||||
signInError: undefined,
|
||||
updateProfileError: undefined,
|
||||
signOut: jest.fn(),
|
||||
@@ -95,6 +95,7 @@ describe("useAuthenticated", () => {
|
||||
wrapper: createAuthWrapper({
|
||||
user: MockUser,
|
||||
permissions: MockPermissions,
|
||||
organizationIds: [],
|
||||
}),
|
||||
});
|
||||
}).not.toThrow();
|
||||
|
||||
@@ -66,15 +66,18 @@ export const RequireAuth: FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
// We can do some TS magic here but I would rather to be explicit on what
|
||||
// values are not undefined when authenticated
|
||||
type NonNullableAuth = AuthContextValue & {
|
||||
user: Exclude<AuthContextValue["user"], undefined>;
|
||||
permissions: Exclude<AuthContextValue["permissions"], undefined>;
|
||||
organizationId: Exclude<AuthContextValue["organizationId"], undefined>;
|
||||
type RequireKeys<T, R extends keyof T> = Omit<T, R> & {
|
||||
[K in keyof Pick<T, R>]: NonNullable<T[K]>;
|
||||
};
|
||||
|
||||
export const useAuthenticated = (): NonNullableAuth => {
|
||||
// We can do some TS magic here but I would rather to be explicit on what
|
||||
// values are not undefined when authenticated
|
||||
type AuthenticatedAuthContextValue = RequireKeys<
|
||||
AuthContextValue,
|
||||
"user" | "permissions" | "organizationIds"
|
||||
>;
|
||||
|
||||
export const useAuthenticated = (): AuthenticatedAuthContextValue => {
|
||||
const auth = useAuthContext();
|
||||
|
||||
if (!auth.user) {
|
||||
@@ -85,5 +88,9 @@ export const useAuthenticated = (): NonNullableAuth => {
|
||||
throw new Error("Permissions are not available.");
|
||||
}
|
||||
|
||||
return auth as NonNullableAuth;
|
||||
if (!auth.organizationIds) {
|
||||
throw new Error("Organization ID is not available.");
|
||||
}
|
||||
|
||||
return auth as AuthenticatedAuthContextValue;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { createContext, type FC, type PropsWithChildren } from "react";
|
||||
import {
|
||||
createContext,
|
||||
type FC,
|
||||
type PropsWithChildren,
|
||||
useState,
|
||||
} from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { appearance } from "api/queries/appearance";
|
||||
import { entitlements } from "api/queries/entitlements";
|
||||
@@ -9,9 +14,13 @@ import type {
|
||||
Experiments,
|
||||
} from "api/typesGenerated";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata";
|
||||
|
||||
export interface DashboardValue {
|
||||
organizationId: string;
|
||||
setOrganizationId: (id: string) => void;
|
||||
entitlements: Entitlements;
|
||||
experiments: Experiments;
|
||||
appearance: AppearanceConfig;
|
||||
@@ -23,6 +32,7 @@ export const DashboardContext = createContext<DashboardValue | undefined>(
|
||||
|
||||
export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
const { metadata } = useEmbeddedMetadata();
|
||||
const { user, organizationIds } = useAuthenticated();
|
||||
const entitlementsQuery = useQuery(entitlements(metadata.entitlements));
|
||||
const experimentsQuery = useQuery(experiments(metadata.experiments));
|
||||
const appearanceQuery = useQuery(appearance(metadata.appearance));
|
||||
@@ -30,6 +40,23 @@ export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
const isLoading =
|
||||
!entitlementsQuery.data || !appearanceQuery.data || !experimentsQuery.data;
|
||||
|
||||
const lastUsedOrganizationId = localStorage.getItem(
|
||||
`user:${user.id}.lastUsedOrganizationId`,
|
||||
);
|
||||
const [activeOrganizationId, setActiveOrganizationId] = useState(() =>
|
||||
lastUsedOrganizationId && organizationIds.includes(lastUsedOrganizationId)
|
||||
? lastUsedOrganizationId
|
||||
: organizationIds[0],
|
||||
);
|
||||
|
||||
const setOrganizationId = useEffectEvent((id: string) => {
|
||||
if (!organizationIds.includes(id)) {
|
||||
throw new ReferenceError("Invalid organization ID");
|
||||
}
|
||||
localStorage.setItem(`user:${user.id}.lastUsedOrganizationId`, id);
|
||||
setActiveOrganizationId(id);
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return <Loader fullscreen />;
|
||||
}
|
||||
@@ -37,6 +64,8 @@ export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
return (
|
||||
<DashboardContext.Provider
|
||||
value={{
|
||||
organizationId: activeOrganizationId,
|
||||
setOrganizationId: setOrganizationId,
|
||||
entitlements: entitlementsQuery.data,
|
||||
experiments: experimentsQuery.data,
|
||||
appearance: appearanceQuery.data,
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { DashboardContext } from "modules/dashboard/DashboardProvider";
|
||||
import {
|
||||
MockAppearanceConfig,
|
||||
MockBuildInfo,
|
||||
MockCanceledWorkspace,
|
||||
MockCancelingWorkspace,
|
||||
MockDeletedWorkspace,
|
||||
MockDeletingWorkspace,
|
||||
MockEntitlementsWithScheduling,
|
||||
MockExperiments,
|
||||
MockFailedWorkspace,
|
||||
MockPendingWorkspace,
|
||||
MockStartingWorkspace,
|
||||
@@ -16,6 +12,7 @@ import {
|
||||
MockStoppingWorkspace,
|
||||
MockWorkspace,
|
||||
} from "testHelpers/entities";
|
||||
import { withDashboardProvider } from "testHelpers/storybook";
|
||||
import { WorkspaceStatusBadge } from "./WorkspaceStatusBadge";
|
||||
|
||||
const meta: Meta<typeof WorkspaceStatusBadge> = {
|
||||
@@ -29,19 +26,7 @@ const meta: Meta<typeof WorkspaceStatusBadge> = {
|
||||
},
|
||||
],
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<DashboardContext.Provider
|
||||
value={{
|
||||
entitlements: MockEntitlementsWithScheduling,
|
||||
experiments: MockExperiments,
|
||||
appearance: MockAppearanceConfig,
|
||||
}}
|
||||
>
|
||||
<Story />
|
||||
</DashboardContext.Provider>
|
||||
),
|
||||
],
|
||||
decorators: [withDashboardProvider],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
} from "api/queries/templates";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { CreateTemplateForm } from "./CreateTemplateForm";
|
||||
import type { CreateTemplatePageViewProps } from "./types";
|
||||
@@ -24,7 +23,7 @@ export const DuplicateTemplateView: FC<CreateTemplatePageViewProps> = ({
|
||||
isCreating,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { entitlements, organizationId } = useDashboard();
|
||||
const [searchParams] = useSearchParams();
|
||||
const templateByNameQuery = useQuery(
|
||||
templateByName(organizationId, searchParams.get("fromTemplate")!),
|
||||
@@ -47,8 +46,7 @@ export const DuplicateTemplateView: FC<CreateTemplatePageViewProps> = ({
|
||||
templateVersionQuery.error ||
|
||||
templateVersionVariablesQuery.error;
|
||||
|
||||
const dashboard = useDashboard();
|
||||
const formPermissions = getFormPermissions(dashboard.entitlements);
|
||||
const formPermissions = getFormPermissions(entitlements);
|
||||
|
||||
const isJobError = error instanceof JobError;
|
||||
const templateVersionLogsQuery = useQuery({
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
} from "api/queries/templates";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { CreateTemplateForm } from "./CreateTemplateForm";
|
||||
import type { CreateTemplatePageViewProps } from "./types";
|
||||
@@ -27,7 +26,7 @@ export const ImportStarterTemplateView: FC<CreateTemplatePageViewProps> = ({
|
||||
isCreating,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { entitlements, organizationId } = useDashboard();
|
||||
const [searchParams] = useSearchParams();
|
||||
const templateExamplesQuery = useQuery(templateExamples(organizationId));
|
||||
const templateExample = templateExamplesQuery.data?.find(
|
||||
@@ -37,8 +36,7 @@ export const ImportStarterTemplateView: FC<CreateTemplatePageViewProps> = ({
|
||||
const isLoading = templateExamplesQuery.isLoading;
|
||||
const loadingError = templateExamplesQuery.error;
|
||||
|
||||
const dashboard = useDashboard();
|
||||
const formPermissions = getFormPermissions(dashboard.entitlements);
|
||||
const formPermissions = getFormPermissions(entitlements);
|
||||
|
||||
const isJobError = error instanceof JobError;
|
||||
const templateVersionLogsQuery = useQuery({
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
JobError,
|
||||
templateVersionVariables,
|
||||
} from "api/queries/templates";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { CreateTemplateForm } from "./CreateTemplateForm";
|
||||
import type { CreateTemplatePageViewProps } from "./types";
|
||||
@@ -21,10 +20,9 @@ export const UploadTemplateView: FC<CreateTemplatePageViewProps> = ({
|
||||
error,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const { organizationId } = useAuthenticated();
|
||||
|
||||
const dashboard = useDashboard();
|
||||
const formPermissions = getFormPermissions(dashboard.entitlements);
|
||||
const { entitlements, organizationId } = useDashboard();
|
||||
const formPermissions = getFormPermissions(entitlements);
|
||||
|
||||
const uploadFileMutation = useMutation(uploadFile());
|
||||
const uploadedFile = uploadFileMutation.data;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useNavigate } from "react-router-dom";
|
||||
import { authMethods, createUser } from "api/queries/users";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { CreateUserForm } from "./CreateUserForm";
|
||||
|
||||
@@ -14,7 +14,7 @@ export const Language = {
|
||||
};
|
||||
|
||||
export const CreateUserPage: FC = () => {
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
const navigate = useNavigate();
|
||||
const queryClient = useQueryClient();
|
||||
const createUserMutation = useMutation(createUser(queryClient));
|
||||
|
||||
@@ -35,10 +35,10 @@ export type ExternalAuthPollingState = "idle" | "polling" | "abandoned";
|
||||
|
||||
const CreateWorkspacePage: FC = () => {
|
||||
const { template: templateName } = useParams() as { template: string };
|
||||
const { user: me, organizationId } = useAuthenticated();
|
||||
const { user: me } = useAuthenticated();
|
||||
const navigate = useNavigate();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const { experiments } = useDashboard();
|
||||
const { experiments, organizationId } = useDashboard();
|
||||
|
||||
const customVersionId = searchParams.get("version") ?? undefined;
|
||||
const defaultName = searchParams.get("name");
|
||||
|
||||
@@ -3,14 +3,14 @@ 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 { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import CreateGroupPageView from "./CreateGroupPageView";
|
||||
|
||||
export const CreateGroupPage: FC = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const navigate = useNavigate();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
const createGroupMutation = useMutation(createGroup(queryClient));
|
||||
|
||||
return (
|
||||
|
||||
@@ -5,12 +5,14 @@ import { getErrorMessage } from "api/errors";
|
||||
import { groups } from "api/queries/groups";
|
||||
import { displayError } from "components/GlobalSnackbar/utils";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
import { pageTitle } from "utils/page";
|
||||
import GroupsPageView from "./GroupsPageView";
|
||||
|
||||
export const GroupsPage: FC = () => {
|
||||
const { organizationId, permissions } = useAuthenticated();
|
||||
const { permissions } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
const { createGroup: canCreateGroup } = permissions;
|
||||
const { template_rbac: isTemplateRBACEnabled } = useFeatureVisibility();
|
||||
const groupsQuery = useQuery(groups(organizationId));
|
||||
|
||||
@@ -3,13 +3,13 @@ import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { templateExamples } from "api/queries/templates";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { StarterTemplatePageView } from "./StarterTemplatePageView";
|
||||
|
||||
const StarterTemplatePage: FC = () => {
|
||||
const { exampleId } = useParams() as { exampleId: string };
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
const templateExamplesQuery = useQuery(templateExamples(organizationId));
|
||||
const starterTemplate = templateExamplesQuery.data?.find(
|
||||
(example) => example.id === exampleId,
|
||||
|
||||
@@ -3,13 +3,13 @@ import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { templateExamples } from "api/queries/templates";
|
||||
import type { TemplateExample } from "api/typesGenerated";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { getTemplatesByTag } from "utils/starterTemplates";
|
||||
import { StarterTemplatesPageView } from "./StarterTemplatesPageView";
|
||||
|
||||
const StarterTemplatesPage: FC = () => {
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
const templateExamplesQuery = useQuery(templateExamples(organizationId));
|
||||
const starterTemplatesByTag = templateExamplesQuery.data
|
||||
? // Currently, the scratch template should not be displayed on the starter templates page.
|
||||
|
||||
@@ -3,13 +3,13 @@ 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 { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { TemplateFiles } from "modules/templates/TemplateFiles/TemplateFiles";
|
||||
import { useTemplateLayoutContext } from "pages/TemplatePage/TemplateLayout";
|
||||
import { getTemplatePageTitle } from "../utils";
|
||||
|
||||
const TemplateFilesPage: FC = () => {
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
const { template, activeVersion } = useTemplateLayoutContext();
|
||||
const { data: currentFiles } = useQuery(
|
||||
templateFiles(activeVersion.job.file_id),
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { TAB_PADDING_Y, TabLink, Tabs, TabsList } from "components/Tabs/Tabs";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { TemplatePageHeader } from "./TemplatePageHeader";
|
||||
|
||||
const templatePermissions = (
|
||||
@@ -71,7 +71,7 @@ export const TemplateLayout: FC<PropsWithChildren> = ({
|
||||
children = <Outlet />,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
const { template: templateName } = useParams() as { template: string };
|
||||
const { data, error, isLoading } = useQuery({
|
||||
queryKey: ["template", templateName],
|
||||
|
||||
+1
-3
@@ -6,7 +6,6 @@ import { API } from "api/api";
|
||||
import { templateByNameKey } from "api/queries/templates";
|
||||
import type { UpdateTemplateMeta } from "api/typesGenerated";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||
@@ -15,10 +14,9 @@ import { TemplateSettingsPageView } from "./TemplateSettingsPageView";
|
||||
export const TemplateSettingsPage: FC = () => {
|
||||
const { template: templateName } = useParams() as { template: string };
|
||||
const navigate = useNavigate();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { template } = useTemplateSettings();
|
||||
const queryClient = useQueryClient();
|
||||
const { entitlements } = useDashboard();
|
||||
const { entitlements, organizationId } = useDashboard();
|
||||
const accessControlEnabled = entitlements.features.access_control.enabled;
|
||||
const advancedSchedulingEnabled =
|
||||
entitlements.features.advanced_template_scheduling.enabled;
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { setGroupRole, setUserRole, templateACL } from "api/queries/templates";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Paywall } from "components/Paywall/Paywall";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
import { docs } from "utils/docs";
|
||||
import { pageTitle } from "utils/page";
|
||||
@@ -12,7 +12,7 @@ import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||
import { TemplatePermissionsPageView } from "./TemplatePermissionsPageView";
|
||||
|
||||
export const TemplatePermissionsPage: FC = () => {
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
const { template, permissions } = useTemplateSettings();
|
||||
const { template_rbac: isTemplateRBACEnabled } = useFeatureVisibility();
|
||||
const templateACLQuery = useQuery(templateACL(template.id));
|
||||
|
||||
@@ -6,7 +6,6 @@ import { API } from "api/api";
|
||||
import { templateByNameKey } from "api/queries/templates";
|
||||
import type { UpdateTemplateMeta } from "api/typesGenerated";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||
@@ -16,9 +15,8 @@ const TemplateSchedulePage: FC = () => {
|
||||
const { template: templateName } = useParams() as { template: string };
|
||||
const navigate = useNavigate();
|
||||
const queryClient = useQueryClient();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { template } = useTemplateSettings();
|
||||
const { entitlements } = useDashboard();
|
||||
const { entitlements, organizationId } = useDashboard();
|
||||
const allowAdvancedScheduling =
|
||||
entitlements.features["advanced_template_scheduling"].enabled;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { Sidebar } from "./Sidebar";
|
||||
|
||||
@@ -27,7 +27,7 @@ export function useTemplateSettings() {
|
||||
}
|
||||
|
||||
export const TemplateSettingsLayout: FC = () => {
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
const { template: templateName } = useParams() as { template: string };
|
||||
const templateQuery = useQuery(templateByName(organizationId, templateName));
|
||||
const permissionsQuery = useQuery({
|
||||
|
||||
@@ -16,7 +16,7 @@ import type {
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||
import { TemplateVariablesPageView } from "./TemplateVariablesPageView";
|
||||
@@ -26,7 +26,7 @@ export const TemplateVariablesPage: FC = () => {
|
||||
organization: string;
|
||||
template: string;
|
||||
};
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
const { template } = useTemplateSettings();
|
||||
const navigate = useNavigate();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
@@ -18,7 +18,7 @@ import type {
|
||||
} from "api/typesGenerated";
|
||||
import { displayError } from "components/GlobalSnackbar/utils";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { useWatchVersionLogs } from "modules/templates/useWatchVersionLogs";
|
||||
import { type FileTree, traverse } from "utils/filetree";
|
||||
import { pageTitle } from "utils/page";
|
||||
@@ -36,7 +36,7 @@ export const TemplateVersionEditorPage: FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const { version: versionName, template: templateName } =
|
||||
useParams() as Params;
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
const templateQuery = useQuery(templateByName(organizationId, templateName));
|
||||
const templateVersionOptions = templateVersionByName(
|
||||
organizationId,
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
templateVersionByName,
|
||||
} from "api/queries/templates";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import TemplateVersionPageView from "./TemplateVersionPageView";
|
||||
|
||||
@@ -20,7 +21,7 @@ type Params = {
|
||||
export const TemplateVersionPage: FC = () => {
|
||||
const { version: versionName, template: templateName } =
|
||||
useParams() as Params;
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
|
||||
/**
|
||||
* Template version files
|
||||
|
||||
@@ -3,11 +3,14 @@ import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { templateExamples, templates } from "api/queries/templates";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { TemplatesPageView } from "./TemplatesPageView";
|
||||
|
||||
export const TemplatesPage: FC = () => {
|
||||
const { organizationId, permissions } = useAuthenticated();
|
||||
const { permissions } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
|
||||
const templatesQuery = useQuery(templates(organizationId));
|
||||
const examplesQuery = useQuery({
|
||||
...templateExamples(organizationId),
|
||||
|
||||
@@ -12,10 +12,10 @@ import { AccountForm } from "./AccountForm";
|
||||
import { AccountUserGroups } from "./AccountUserGroups";
|
||||
|
||||
export const AccountPage: FC = () => {
|
||||
const { user: me, permissions, organizationId } = useAuthenticated();
|
||||
const { permissions, user: me } = useAuthenticated();
|
||||
const { updateProfile, updateProfileError, isUpdatingProfile } =
|
||||
useAuthContext();
|
||||
const { entitlements, experiments } = useDashboard();
|
||||
const { entitlements, experiments, organizationId } = useDashboard();
|
||||
|
||||
const hasGroupsFeature = entitlements.features.user_role_management.enabled;
|
||||
const groupsQuery = useQuery({
|
||||
|
||||
@@ -35,15 +35,13 @@ export const UsersPage: FC = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const searchParamsResult = useSearchParams();
|
||||
const { entitlements } = useDashboard();
|
||||
const { entitlements, organizationId } = useDashboard();
|
||||
const [searchParams] = searchParamsResult;
|
||||
|
||||
const { organizationId } = useAuthenticated();
|
||||
const groupsByUserIdQuery = useQuery(groupsByUserId(organizationId));
|
||||
const authMethodsQuery = useQuery(authMethods());
|
||||
|
||||
const { user: me } = useAuthenticated();
|
||||
const { permissions } = useAuthenticated();
|
||||
const { permissions, user: me } = useAuthenticated();
|
||||
const { updateUsers: canEditUsers, viewDeploymentValues } = permissions;
|
||||
const rolesQuery = useQuery(roles());
|
||||
const { data: deploymentValues } = useQuery({
|
||||
|
||||
@@ -2,8 +2,8 @@ import { action } from "@storybook/addon-actions";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import type { ProvisionerJobLog } from "api/typesGenerated";
|
||||
import { ProxyContext, getPreferredProxy } from "contexts/ProxyContext";
|
||||
import { DashboardContext } from "modules/dashboard/DashboardProvider";
|
||||
import * as Mocks from "testHelpers/entities";
|
||||
import { withDashboardProvider } from "testHelpers/storybook";
|
||||
import type { WorkspacePermissions } from "./permissions";
|
||||
import { Workspace } from "./Workspace";
|
||||
import { WorkspaceBuildLogsSection } from "./WorkspaceBuildLogsSection";
|
||||
@@ -32,35 +32,28 @@ const meta: Meta<typeof Workspace> = {
|
||||
],
|
||||
},
|
||||
decorators: [
|
||||
withDashboardProvider,
|
||||
(Story) => (
|
||||
<DashboardContext.Provider
|
||||
<ProxyContext.Provider
|
||||
value={{
|
||||
entitlements: Mocks.MockEntitlementsWithScheduling,
|
||||
experiments: Mocks.MockExperiments,
|
||||
appearance: Mocks.MockAppearanceConfig,
|
||||
proxyLatencies: Mocks.MockProxyLatencies,
|
||||
proxy: getPreferredProxy([], undefined),
|
||||
proxies: [],
|
||||
isLoading: false,
|
||||
isFetched: true,
|
||||
clearProxy: () => {
|
||||
return;
|
||||
},
|
||||
setProxy: () => {
|
||||
return;
|
||||
},
|
||||
refetchProxyLatencies: (): Date => {
|
||||
return new Date();
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ProxyContext.Provider
|
||||
value={{
|
||||
proxyLatencies: Mocks.MockProxyLatencies,
|
||||
proxy: getPreferredProxy([], undefined),
|
||||
proxies: [],
|
||||
isLoading: false,
|
||||
isFetched: true,
|
||||
clearProxy: () => {
|
||||
return;
|
||||
},
|
||||
setProxy: () => {
|
||||
return;
|
||||
},
|
||||
refetchProxyLatencies: (): Date => {
|
||||
return new Date();
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Story />
|
||||
</ProxyContext.Provider>
|
||||
</DashboardContext.Provider>
|
||||
<Story />
|
||||
</ProxyContext.Provider>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
@@ -10,10 +10,10 @@ import type { Workspace } from "api/typesGenerated";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { Navbar } from "modules/dashboard/Navbar/Navbar";
|
||||
import { NotificationBanners } from "modules/dashboard/NotificationBanners/NotificationBanners";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { workspaceChecks, type WorkspacePermissions } from "./permissions";
|
||||
import { WorkspaceReadyPage } from "./WorkspaceReadyPage";
|
||||
|
||||
@@ -25,7 +25,7 @@ export const WorkspacePage: FC = () => {
|
||||
};
|
||||
const workspaceName = params.workspace;
|
||||
const username = params.username.replace("@", "");
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { organizationId } = useDashboard();
|
||||
|
||||
// Workspace
|
||||
const workspaceQueryOptions = workspaceByOwnerAndName(
|
||||
|
||||
@@ -38,8 +38,9 @@ const WorkspacesPage: FC = () => {
|
||||
// each hook.
|
||||
const searchParamsResult = useSafeSearchParams();
|
||||
const pagination = usePagination({ searchParamsResult });
|
||||
const { permissions } = useAuthenticated();
|
||||
const { entitlements, organizationId } = useDashboard();
|
||||
|
||||
const { organizationId, permissions } = useAuthenticated();
|
||||
const templatesQuery = useQuery(templates(organizationId, false));
|
||||
|
||||
const filterProps = useWorkspacesFilter({
|
||||
@@ -61,7 +62,6 @@ const WorkspacesPage: FC = () => {
|
||||
"delete" | "update" | null
|
||||
>(null);
|
||||
const [urlSearchParams] = searchParamsResult;
|
||||
const { entitlements } = useDashboard();
|
||||
const canCheckWorkspaces =
|
||||
entitlements.features["workspace_batch_actions"].enabled;
|
||||
const batchActions = useBatchActions({
|
||||
|
||||
@@ -12,18 +12,15 @@ import {
|
||||
getDefaultFilterProps,
|
||||
} from "components/Filter/storyHelpers";
|
||||
import { DEFAULT_RECORDS_PER_PAGE } from "components/PaginationWidget/utils";
|
||||
import { DashboardContext } from "modules/dashboard/DashboardProvider";
|
||||
import {
|
||||
MockWorkspace,
|
||||
MockAppearanceConfig,
|
||||
MockBuildInfo,
|
||||
MockEntitlementsWithScheduling,
|
||||
MockExperiments,
|
||||
mockApiError,
|
||||
MockUser,
|
||||
MockPendingProvisionerJob,
|
||||
MockTemplate,
|
||||
} from "testHelpers/entities";
|
||||
import { withDashboardProvider } from "testHelpers/storybook";
|
||||
import { WorkspacesPageView } from "./WorkspacesPageView";
|
||||
|
||||
const createWorkspace = (
|
||||
@@ -141,19 +138,7 @@ const meta: Meta<typeof WorkspacesPageView> = {
|
||||
},
|
||||
],
|
||||
},
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<DashboardContext.Provider
|
||||
value={{
|
||||
entitlements: MockEntitlementsWithScheduling,
|
||||
experiments: MockExperiments,
|
||||
appearance: MockAppearanceConfig,
|
||||
}}
|
||||
>
|
||||
<Story />
|
||||
</DashboardContext.Provider>
|
||||
),
|
||||
],
|
||||
decorators: [withDashboardProvider],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
@@ -26,6 +26,8 @@ export const withDashboardProvider = (
|
||||
return (
|
||||
<DashboardContext.Provider
|
||||
value={{
|
||||
organizationId: "",
|
||||
setOrganizationId: () => {},
|
||||
entitlements,
|
||||
experiments,
|
||||
appearance: MockAppearanceConfig,
|
||||
|
||||
Reference in New Issue
Block a user