Skip to content

Commit efbd625

Browse files
authored
chore: remove global organization id state (#14135)
1 parent f9b660e commit efbd625

File tree

29 files changed

+177
-151
lines changed

29 files changed

+177
-151
lines changed

site/src/api/api.ts

+26-11
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,20 @@ const BASE_CONTENT_TYPE_JSON = {
300300
"Content-Type": "application/json",
301301
} as const satisfies HeadersInit;
302302

303-
type TemplateOptions = Readonly<{
303+
export type GetTemplatesOptions = Readonly<{
304304
readonly deprecated?: boolean;
305305
}>;
306306

307+
function normalizeGetTemplatesOptions(
308+
options: GetTemplatesOptions = {},
309+
): Record<string, string> {
310+
const params: Record<string, string> = {};
311+
if (options.deprecated !== undefined) {
312+
params["deprecated"] = String(options.deprecated);
313+
}
314+
return params;
315+
}
316+
307317
type SearchParamOptions = TypesGen.Pagination & {
308318
q?: string;
309319
};
@@ -625,21 +635,26 @@ class ApiMethods {
625635
return response.data;
626636
};
627637

638+
getTemplates = async (
639+
options?: GetTemplatesOptions,
640+
): Promise<TypesGen.Template[]> => {
641+
const params = normalizeGetTemplatesOptions(options);
642+
const response = await this.axios.get<TypesGen.Template[]>(
643+
`/api/v2/templates`,
644+
{ params },
645+
);
646+
647+
return response.data;
648+
};
649+
628650
/**
629651
* @param organization Can be the organization's ID or name
630652
*/
631-
getTemplates = async (
653+
getTemplatesByOrganization = async (
632654
organization: string,
633-
options?: TemplateOptions,
655+
options?: GetTemplatesOptions,
634656
): Promise<TypesGen.Template[]> => {
635-
const params: Record<string, string> = {};
636-
if (options?.deprecated !== undefined) {
637-
// Just want to check if it isn't undefined. If it has
638-
// a boolean value, convert it to a string and include
639-
// it as a param.
640-
params["deprecated"] = String(options.deprecated);
641-
}
642-
657+
const params = normalizeGetTemplatesOptions(options);
643658
const response = await this.axios.get<TypesGen.Template[]>(
644659
`/api/v2/organizations/${organization}/templates`,
645660
{ params },

site/src/api/queries/templates.ts

+25-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { MutationOptions, QueryClient, QueryOptions } from "react-query";
2-
import { API } from "api/api";
2+
import { API, type GetTemplatesOptions } from "api/api";
33
import type {
44
CreateTemplateRequest,
55
CreateTemplateVersionRequest,
@@ -38,16 +38,30 @@ export const templateByName = (
3838
};
3939
};
4040

41-
const getTemplatesQueryKey = (organizationId: string, deprecated?: boolean) => [
42-
organizationId,
41+
const getTemplatesQueryKey = (options?: GetTemplatesOptions) => [
4342
"templates",
44-
deprecated,
43+
options?.deprecated,
4544
];
4645

47-
export const templates = (organizationId: string, deprecated?: boolean) => {
46+
export const templates = (options?: GetTemplatesOptions) => {
4847
return {
49-
queryKey: getTemplatesQueryKey(organizationId, deprecated),
50-
queryFn: () => API.getTemplates(organizationId, { deprecated }),
48+
queryKey: getTemplatesQueryKey(options),
49+
queryFn: () => API.getTemplates(options),
50+
};
51+
};
52+
53+
const getTemplatesByOrganizationQueryKey = (
54+
organization: string,
55+
options?: GetTemplatesOptions,
56+
) => [organization, "templates", options?.deprecated];
57+
58+
export const templatesByOrganization = (
59+
organization: string,
60+
options: GetTemplatesOptions = {},
61+
) => {
62+
return {
63+
queryKey: getTemplatesByOrganizationQueryKey(organization, options),
64+
queryFn: () => API.getTemplatesByOrganization(organization, options),
5165
};
5266
};
5367

@@ -100,7 +114,10 @@ export const setGroupRole = (
100114

101115
export const templateExamples = (organizationId: string) => {
102116
return {
103-
queryKey: [...getTemplatesQueryKey(organizationId), "examples"],
117+
queryKey: [
118+
...getTemplatesByOrganizationQueryKey(organizationId),
119+
"examples",
120+
],
104121
queryFn: () => API.getTemplateExamples(organizationId),
105122
};
106123
};

site/src/modules/dashboard/DashboardProvider.tsx

+20-7
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,22 @@ import { useQuery } from "react-query";
33
import { appearance } from "api/queries/appearance";
44
import { entitlements } from "api/queries/entitlements";
55
import { experiments } from "api/queries/experiments";
6+
import { organizations } from "api/queries/organizations";
67
import type {
78
AppearanceConfig,
89
Entitlements,
910
Experiments,
11+
Organization,
1012
} from "api/typesGenerated";
13+
import { ErrorAlert } from "components/Alert/ErrorAlert";
1114
import { Loader } from "components/Loader/Loader";
1215
import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata";
1316

1417
export interface DashboardValue {
15-
/**
16-
* @deprecated Do not add new usage of this value. It is being removed as part
17-
* of the multi-org work.
18-
*/
19-
organizationId: string;
2018
entitlements: Entitlements;
2119
experiments: Experiments;
2220
appearance: AppearanceConfig;
21+
organizations: Organization[];
2322
}
2423

2524
export const DashboardContext = createContext<DashboardValue | undefined>(
@@ -31,9 +30,23 @@ export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => {
3130
const entitlementsQuery = useQuery(entitlements(metadata.entitlements));
3231
const experimentsQuery = useQuery(experiments(metadata.experiments));
3332
const appearanceQuery = useQuery(appearance(metadata.appearance));
33+
const organizationsQuery = useQuery(organizations());
34+
35+
const error =
36+
entitlementsQuery.error ||
37+
appearanceQuery.error ||
38+
experimentsQuery.error ||
39+
organizationsQuery.error;
40+
41+
if (error) {
42+
return <ErrorAlert error={error} />;
43+
}
3444

3545
const isLoading =
36-
!entitlementsQuery.data || !appearanceQuery.data || !experimentsQuery.data;
46+
!entitlementsQuery.data ||
47+
!appearanceQuery.data ||
48+
!experimentsQuery.data ||
49+
!organizationsQuery.data;
3750

3851
if (isLoading) {
3952
return <Loader fullscreen />;
@@ -42,10 +55,10 @@ export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => {
4255
return (
4356
<DashboardContext.Provider
4457
value={{
45-
organizationId: "00000000-0000-0000-0000-000000000000",
4658
entitlements: entitlementsQuery.data,
4759
experiments: experimentsQuery.data,
4860
appearance: appearanceQuery.data,
61+
organizations: organizationsQuery.data,
4962
}}
5063
>
5164
{children}

site/src/modules/navigation.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@ export const linkToUsers = withFilter("/users", "status:active");
2727

2828
export const linkToTemplate =
2929
(organizationName: string, templateName: string): LinkThunk =>
30-
(dashboard) =>
31-
dashboard.experiments.includes("multi-organization") &&
32-
selectFeatureVisibility(dashboard.entitlements).multiple_organizations
30+
(dashboard) => {
31+
const hasMultipleOrganizations = dashboard.organizations.length > 1;
32+
const organizationsEnabled =
33+
dashboard.experiments.includes("multi-organization") &&
34+
selectFeatureVisibility(dashboard.entitlements).multiple_organizations;
35+
36+
return hasMultipleOrganizations || organizationsEnabled
3337
? `/templates/${organizationName}/${templateName}`
3438
: `/templates/${templateName}`;
39+
};

site/src/pages/CreateTemplatePage/CreateTemplateForm.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -233,13 +233,13 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = (props) => {
233233

234234
{showOrganizationPicker && (
235235
<OrganizationAutocomplete
236-
{...getFieldHelpers("organization_id")}
236+
{...getFieldHelpers("organization")}
237237
required
238238
label="Belongs to"
239239
value={selectedOrg}
240240
onChange={(newValue) => {
241241
setSelectedOrg(newValue);
242-
void form.setFieldValue("organization", newValue?.id || "");
242+
void form.setFieldValue("organization", newValue?.name || "");
243243
}}
244244
size="medium"
245245
/>

site/src/pages/CreateUserPage/CreateUserForm.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ export interface CreateUserFormProps {
6565
onCancel: () => void;
6666
error?: unknown;
6767
isLoading: boolean;
68-
organizationId: string;
6968
authMethods?: TypesGen.AuthMethods;
7069
}
7170

@@ -86,15 +85,15 @@ const validationSchema = Yup.object({
8685

8786
export const CreateUserForm: FC<
8887
React.PropsWithChildren<CreateUserFormProps>
89-
> = ({ onSubmit, onCancel, error, isLoading, organizationId, authMethods }) => {
88+
> = ({ onSubmit, onCancel, error, isLoading, authMethods }) => {
9089
const form: FormikContextType<TypesGen.CreateUserRequest> =
9190
useFormik<TypesGen.CreateUserRequest>({
9291
initialValues: {
9392
email: "",
9493
password: "",
9594
username: "",
9695
name: "",
97-
organization_id: organizationId,
96+
organization_id: "00000000-0000-0000-0000-000000000000",
9897
disable_login: false,
9998
login_type: "",
10099
},

site/src/pages/CreateUserPage/CreateUserPage.tsx

-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { useNavigate } from "react-router-dom";
55
import { authMethods, createUser } from "api/queries/users";
66
import { displaySuccess } from "components/GlobalSnackbar/utils";
77
import { Margins } from "components/Margins/Margins";
8-
import { useDashboard } from "modules/dashboard/useDashboard";
98
import { pageTitle } from "utils/page";
109
import { CreateUserForm } from "./CreateUserForm";
1110

@@ -14,7 +13,6 @@ export const Language = {
1413
};
1514

1615
export const CreateUserPage: FC = () => {
17-
const { organizationId } = useDashboard();
1816
const navigate = useNavigate();
1917
const queryClient = useQueryClient();
2018
const createUserMutation = useMutation(createUser(queryClient));
@@ -38,7 +36,6 @@ export const CreateUserPage: FC = () => {
3836
navigate("..", { relative: "path" });
3937
}}
4038
isLoading={createUserMutation.isLoading}
41-
organizationId={organizationId}
4239
/>
4340
</Margins>
4441
);

site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx

+13-10
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,12 @@ export type CreateWorkspaceMode = (typeof createWorkspaceModes)[number];
3333
export type ExternalAuthPollingState = "idle" | "polling" | "abandoned";
3434

3535
const CreateWorkspacePage: FC = () => {
36-
const { template: templateName } = useParams() as {
37-
template: string;
38-
};
36+
const { organization: organizationName = "default", template: templateName } =
37+
useParams() as { organization?: string; template: string };
3938
const { user: me } = useAuthenticated();
4039
const navigate = useNavigate();
4140
const [searchParams] = useSearchParams();
42-
const { experiments, organizationId } = useDashboard();
41+
const { experiments } = useDashboard();
4342

4443
const customVersionId = searchParams.get("version") ?? undefined;
4544
const defaultName = searchParams.get("name");
@@ -54,15 +53,19 @@ const CreateWorkspacePage: FC = () => {
5453
);
5554
const createWorkspaceMutation = useMutation(createWorkspace(queryClient));
5655

57-
const templateQuery = useQuery(templateByName(organizationId, templateName));
58-
56+
const templateQuery = useQuery(
57+
templateByName(organizationName, templateName),
58+
);
5959
const permissionsQuery = useQuery(
60-
checkAuthorization({
61-
checks: createWorkspaceChecks(organizationId),
62-
}),
60+
templateQuery.data
61+
? checkAuthorization({
62+
checks: createWorkspaceChecks(templateQuery.data.organization_id),
63+
})
64+
: { enabled: false },
6365
);
6466
const realizedVersionId =
6567
customVersionId ?? templateQuery.data?.active_version_id;
68+
const organizationId = templateQuery.data?.organization_id;
6669
const richParametersQuery = useQuery({
6770
...richParameters(realizedVersionId ?? ""),
6871
enabled: realizedVersionId !== undefined,
@@ -110,7 +113,7 @@ const CreateWorkspacePage: FC = () => {
110113

111114
const autoCreationStartedRef = useRef(false);
112115
const automateWorkspaceCreation = useEffectEvent(async () => {
113-
if (autoCreationStartedRef.current) {
116+
if (autoCreationStartedRef.current || !organizationId) {
114117
return;
115118
}
116119

site/src/pages/GroupsPage/GroupsPage.tsx

+1-3
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,15 @@ import { getErrorMessage } from "api/errors";
55
import { groups } from "api/queries/groups";
66
import { displayError } from "components/GlobalSnackbar/utils";
77
import { useAuthenticated } from "contexts/auth/RequireAuth";
8-
import { useDashboard } from "modules/dashboard/useDashboard";
98
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
109
import { pageTitle } from "utils/page";
1110
import GroupsPageView from "./GroupsPageView";
1211

1312
export const GroupsPage: FC = () => {
1413
const { permissions } = useAuthenticated();
15-
const { organizationId } = useDashboard();
1614
const { createGroup: canCreateGroup } = permissions;
1715
const { template_rbac: isTemplateRBACEnabled } = useFeatureVisibility();
18-
const groupsQuery = useQuery(groups(organizationId));
16+
const groupsQuery = useQuery(groups("default"));
1917

2018
useEffect(() => {
2119
if (groupsQuery.error) {

site/src/pages/ManagementSettingsPage/GroupsPage/GroupPage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ import { pageTitle } from "utils/page";
5151

5252
export const GroupPage: FC = () => {
5353
const { organization = "default", groupName } = useParams() as {
54-
organization: string;
54+
organization?: string;
5555
groupName: string;
5656
};
5757
const queryClient = useQueryClient();

site/src/pages/ManagementSettingsPage/GroupsPage/GroupSettingsPage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import GroupSettingsPageView from "./GroupSettingsPageView";
1212

1313
export const GroupSettingsPage: FC = () => {
1414
const { organization = "default", groupName } = useParams() as {
15-
organization: string;
15+
organization?: string;
1616
groupName: string;
1717
};
1818
const queryClient = useQueryClient();

site/src/pages/ManagementSettingsPage/GroupsPage/GroupsPage.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export const GroupsPage: FC = () => {
3030
} = useFeatureVisibility();
3131
const { experiments } = useDashboard();
3232
const location = useLocation();
33-
const { organization = "default" } = useParams() as { organization: string };
33+
const { organization = "default" } = useParams() as { organization?: string };
3434
const groupsQuery = useQuery(groups(organization));
3535
const { organizations } = useOrganizationSettings();
3636

0 commit comments

Comments
 (0)