diff --git a/site/e2e/expectUrl.ts b/site/e2e/expectUrl.ts index eb3777f577907..0ed0d99649cdd 100644 --- a/site/e2e/expectUrl.ts +++ b/site/e2e/expectUrl.ts @@ -23,7 +23,12 @@ export const expectUrl = expect.extend({ pass, actual, expected, - message: () => "The page does not have the expected URL pathname.", + message: () => + "The page does not have the expected URL pathname.\n" + + `Expected: ${this.isNot ? "not" : ""}${this.utils.printExpected( + expected, + )}\n` + + `Actual: ${this.utils.printReceived(actual)}`, }; }, }); diff --git a/site/src/api/api.ts b/site/src/api/api.ts index a98ce16afc61b..7aeefe98a444c 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -516,73 +516,97 @@ class ApiMethods { return response.data; }; + /** + * @param organization Can be the organization's ID or name + */ updateOrganization = async ( - organizationId: string, + organization: string, params: TypesGen.UpdateOrganizationRequest, ) => { const response = await this.axios.patch( - `/api/v2/organizations/${organizationId}`, + `/api/v2/organizations/${organization}`, params, ); return response.data; }; - deleteOrganization = async (organizationId: string) => { + /** + * @param organization Can be the organization's ID or name + */ + deleteOrganization = async (organization: string) => { await this.axios.delete( - `/api/v2/organizations/${organizationId}`, + `/api/v2/organizations/${organization}`, ); }; + /** + * @param organization Can be the organization's ID or name + */ getOrganization = async ( - organizationId: string, + organization: string, ): Promise => { const response = await this.axios.get( - `/api/v2/organizations/${organizationId}`, + `/api/v2/organizations/${organization}`, ); return response.data; }; - getOrganizationMembers = async (organizationId: string) => { + /** + * @param organization Can be the organization's ID or name + */ + getOrganizationMembers = async (organization: string) => { const response = await this.axios.get< TypesGen.OrganizationMemberWithUserData[] - >(`/api/v2/organizations/${organizationId}/members`); + >(`/api/v2/organizations/${organization}/members`); return response.data; }; - getOrganizationRoles = async (organizationId: string) => { + /** + * @param organization Can be the organization's ID or name + */ + getOrganizationRoles = async (organization: string) => { const response = await this.axios.get( - `/api/v2/organizations/${organizationId}/members/roles`, + `/api/v2/organizations/${organization}/members/roles`, ); return response.data; }; + /** + * @param organization Can be the organization's ID or name + */ updateOrganizationMemberRoles = async ( - organizationId: string, + organization: string, userId: string, roles: TypesGen.SlimRole["name"][], ): Promise => { const response = await this.axios.put( - `/api/v2/organizations/${organizationId}/members/${userId}/roles`, + `/api/v2/organizations/${organization}/members/${userId}/roles`, { roles }, ); return response.data; }; - addOrganizationMember = async (organizationId: string, userId: string) => { + /** + * @param organization Can be the organization's ID or name + */ + addOrganizationMember = async (organization: string, userId: string) => { const response = await this.axios.post( - `/api/v2/organizations/${organizationId}/members/${userId}`, + `/api/v2/organizations/${organization}/members/${userId}`, ); return response.data; }; - removeOrganizationMember = async (organizationId: string, userId: string) => { + /** + * @param organization Can be the organization's ID or name + */ + removeOrganizationMember = async (organization: string, userId: string) => { await this.axios.delete( - `/api/v2/organizations/${organizationId}/members/${userId}`, + `/api/v2/organizations/${organization}/members/${userId}`, ); }; @@ -601,8 +625,11 @@ class ApiMethods { return response.data; }; + /** + * @param organization Can be the organization's ID or name + */ getTemplates = async ( - organizationId: string, + organization: string, options?: TemplateOptions, ): Promise => { const params: Record = {}; @@ -614,19 +641,22 @@ class ApiMethods { } const response = await this.axios.get( - `/api/v2/organizations/${organizationId}/templates`, + `/api/v2/organizations/${organization}/templates`, { params }, ); return response.data; }; + /** + * @param organization Can be the organization's ID or name + */ getTemplateByName = async ( - organizationId: string, + organization: string, name: string, ): Promise => { const response = await this.axios.get( - `/api/v2/organizations/${organizationId}/templates/${name}`, + `/api/v2/organizations/${organization}/templates/${name}`, ); return response.data; @@ -675,26 +705,32 @@ class ApiMethods { return response.data; }; + /** + * @param organization Can be the organization's ID or name + */ getTemplateVersionByName = async ( - organizationId: string, + organization: string, templateName: string, versionName: string, ): Promise => { const response = await this.axios.get( - `/api/v2/organizations/${organizationId}/templates/${templateName}/versions/${versionName}`, + `/api/v2/organizations/${organization}/templates/${templateName}/versions/${versionName}`, ); return response.data; }; + /** + * @param organization Can be the organization's ID or name + */ getPreviousTemplateVersionByName = async ( - organizationId: string, + organization: string, templateName: string, versionName: string, ) => { try { const response = await this.axios.get( - `/api/v2/organizations/${organizationId}/templates/${templateName}/versions/${versionName}/previous`, + `/api/v2/organizations/${organization}/templates/${templateName}/versions/${versionName}/previous`, ); return response.data; @@ -713,12 +749,15 @@ class ApiMethods { } }; + /** + * @param organization Can be the organization's ID or name + */ createTemplateVersion = async ( - organizationId: string, + organization: string, data: TypesGen.CreateTemplateVersionRequest, ): Promise => { const response = await this.axios.post( - `/api/v2/organizations/${organizationId}/templateversions`, + `/api/v2/organizations/${organization}/templateversions`, data, ); @@ -744,12 +783,15 @@ class ApiMethods { return response.data; }; + /** + * @param organization Can be the organization's ID or name + */ createTemplate = async ( - organizationId: string, + organization: string, data: TypesGen.CreateTemplateRequest, ): Promise => { const response = await this.axios.post( - `/api/v2/organizations/${organizationId}/templates`, + `/api/v2/organizations/${organization}/templates`, data, ); @@ -1480,31 +1522,40 @@ class ApiMethods { return response.data; }; - getGroups = async (organizationId: string): Promise => { + /** + * @param organization Can be the organization's ID or name + */ + getGroups = async (organization: string): Promise => { const response = await this.axios.get( - `/api/v2/organizations/${organizationId}/groups`, + `/api/v2/organizations/${organization}/groups`, ); return response.data; }; + /** + * @param organization Can be the organization's ID or name + */ createGroup = async ( - organizationId: string, + organization: string, data: TypesGen.CreateGroupRequest, ): Promise => { const response = await this.axios.post( - `/api/v2/organizations/${organizationId}/groups`, + `/api/v2/organizations/${organization}/groups`, data, ); return response.data; }; + /** + * @param organization Can be the organization's ID or name + */ getGroup = async ( - organizationId: string, + organization: string, groupName: string, ): Promise => { const response = await this.axios.get( - `/api/v2/organizations/${organizationId}/groups/${groupName}`, + `/api/v2/organizations/${organization}/groups/${groupName}`, ); return response.data; }; @@ -1673,11 +1724,14 @@ class ApiMethods { return response.data; }; + /** + * @param organization Can be the organization's ID or name + */ getTemplateExamples = async ( - organizationId: string, + organization: string, ): Promise => { const response = await this.axios.get( - `/api/v2/organizations/${organizationId}/templates/examples`, + `/api/v2/organizations/${organization}/templates/examples`, ); return response.data; diff --git a/site/src/api/queries/groups.ts b/site/src/api/queries/groups.ts index 7658abd8e5304..ed670c5d17a9d 100644 --- a/site/src/api/queries/groups.ts +++ b/site/src/api/queries/groups.ts @@ -8,38 +8,38 @@ import type { type GroupSortOrder = "asc" | "desc"; -const getGroupsQueryKey = (organizationId: string) => [ +const getGroupsQueryKey = (organization: string) => [ "organization", - organizationId, + organization, "groups", ]; -export const groups = (organizationId: string) => { +export const groups = (organization: string) => { return { - queryKey: getGroupsQueryKey(organizationId), - queryFn: () => API.getGroups(organizationId), + queryKey: getGroupsQueryKey(organization), + queryFn: () => API.getGroups(organization), } satisfies UseQueryOptions; }; -const getGroupQueryKey = (organizationId: string, groupName: string) => [ +const getGroupQueryKey = (organization: string, groupName: string) => [ "organization", - organizationId, + organization, "group", groupName, ]; -export const group = (organizationId: string, groupName: string) => { +export const group = (organization: string, groupName: string) => { return { - queryKey: getGroupQueryKey(organizationId, groupName), - queryFn: () => API.getGroup(organizationId, groupName), + queryKey: getGroupQueryKey(organization, groupName), + queryFn: () => API.getGroup(organization, groupName), }; }; export type GroupsByUserId = Readonly>; -export function groupsByUserId(organizationId: string) { +export function groupsByUserId(organization: string) { return { - ...groups(organizationId), + ...groups(organization), select: (allGroups) => { // Sorting here means that nothing has to be sorted for the individual // user arrays later @@ -63,9 +63,9 @@ export function groupsByUserId(organizationId: string) { } satisfies UseQueryOptions; } -export function groupsForUser(organizationId: string, userId: string) { +export function groupsForUser(organization: string, userId: string) { return { - ...groups(organizationId), + ...groups(organization), select: (allGroups) => { const groupsForUser = allGroups.filter((group) => { const groupMemberIds = group.members.map((member) => member.id); @@ -95,15 +95,12 @@ export const groupPermissions = (groupId: string) => { }; }; -export const createGroup = ( - queryClient: QueryClient, - organizationId: string, -) => { +export const createGroup = (queryClient: QueryClient, organization: string) => { return { mutationFn: (request: CreateGroupRequest) => - API.createGroup(organizationId, request), + API.createGroup(organization, request), onSuccess: async () => { - await queryClient.invalidateQueries(getGroupsQueryKey(organizationId)); + await queryClient.invalidateQueries(getGroupsQueryKey(organization)); }, }; }; @@ -148,12 +145,12 @@ export const removeMember = (queryClient: QueryClient) => { export const invalidateGroup = ( queryClient: QueryClient, - organizationId: string, + organization: string, groupId: string, ) => Promise.all([ - queryClient.invalidateQueries(getGroupsQueryKey(organizationId)), - queryClient.invalidateQueries(getGroupQueryKey(organizationId, groupId)), + queryClient.invalidateQueries(getGroupsQueryKey(organization)), + queryClient.invalidateQueries(getGroupQueryKey(organization, groupId)), ]); export function sortGroupsByName( diff --git a/site/src/api/queries/templates.ts b/site/src/api/queries/templates.ts index 605ef54e0b35b..46d3d03507e08 100644 --- a/site/src/api/queries/templates.ts +++ b/site/src/api/queries/templates.ts @@ -13,11 +13,19 @@ import type { import { delay } from "utils/delay"; import { getTemplateVersionFiles } from "utils/templateVersion"; +export const templateKey = (templateId: string) => ["template", templateId]; + +export const template = (templateId: string): QueryOptions