diff --git a/site/src/api/api.ts b/site/src/api/api.ts index b486dd2696699..b7929107c7bed 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -1684,11 +1684,13 @@ class ApiMethods { }; getWorkspaceQuota = async ( + organizationName: string, username: string, ): Promise => { const response = await this.axios.get( - `/api/v2/workspace-quota/${encodeURIComponent(username)}`, + `/api/v2/organizations/${encodeURIComponent(organizationName)}/members/${encodeURIComponent(username)}/workspace-quota`, ); + return response.data; }; diff --git a/site/src/api/queries/workspaceQuota.ts b/site/src/api/queries/workspaceQuota.ts index 0c44a06375309..17b39463d6247 100644 --- a/site/src/api/queries/workspaceQuota.ts +++ b/site/src/api/queries/workspaceQuota.ts @@ -1,14 +1,16 @@ import { API } from "api/api"; -export const getWorkspaceQuotaQueryKey = (username: string) => [ - username, - "workspaceQuota", -]; +export const getWorkspaceQuotaQueryKey = ( + organizationName: string, + username: string, +) => { + return ["workspaceQuota", organizationName, username]; +}; -export const workspaceQuota = (username: string) => { +export const workspaceQuota = (organizationName: string, username: string) => { return { - queryKey: getWorkspaceQuotaQueryKey(username), - queryFn: () => API.getWorkspaceQuota(username), + queryKey: getWorkspaceQuotaQueryKey(organizationName, username), + queryFn: () => API.getWorkspaceQuota(organizationName, username), }; }; diff --git a/site/src/modules/dashboard/DashboardProvider.tsx b/site/src/modules/dashboard/DashboardProvider.tsx index 958e0f199e55f..7744f16e5fdeb 100644 --- a/site/src/modules/dashboard/DashboardProvider.tsx +++ b/site/src/modules/dashboard/DashboardProvider.tsx @@ -19,7 +19,7 @@ export interface DashboardValue { entitlements: Entitlements; experiments: Experiments; appearance: AppearanceConfig; - organizations: Organization[]; + organizations: readonly Organization[]; showOrganizations: boolean; } diff --git a/site/src/pages/ManagementSettingsPage/GroupsPage/GroupsPage.tsx b/site/src/pages/ManagementSettingsPage/GroupsPage/GroupsPage.tsx index 4777f289e73eb..ce0e3fd0804d3 100644 --- a/site/src/pages/ManagementSettingsPage/GroupsPage/GroupsPage.tsx +++ b/site/src/pages/ManagementSettingsPage/GroupsPage/GroupsPage.tsx @@ -99,5 +99,8 @@ export const GroupsPage: FC = () => { export default GroupsPage; -export const getOrganizationNameByDefault = (organizations: Organization[]) => - organizations.find((org) => org.is_default)?.name; +export const getOrganizationNameByDefault = ( + organizations: readonly Organization[], +) => { + return organizations.find((org) => org.is_default)?.name; +}; diff --git a/site/src/pages/ManagementSettingsPage/ManagementSettingsLayout.tsx b/site/src/pages/ManagementSettingsPage/ManagementSettingsLayout.tsx index 8692c5dcd0408..4a74417e86a65 100644 --- a/site/src/pages/ManagementSettingsPage/ManagementSettingsLayout.tsx +++ b/site/src/pages/ManagementSettingsPage/ManagementSettingsLayout.tsx @@ -12,9 +12,9 @@ import { Outlet } from "react-router-dom"; import { DeploySettingsContext } from "../DeploySettingsPage/DeploySettingsLayout"; import { Sidebar } from "./Sidebar"; -type OrganizationSettingsValue = { - organizations: Organization[]; -}; +type OrganizationSettingsValue = Readonly<{ + organizations: readonly Organization[]; +}>; export const useOrganizationSettings = (): OrganizationSettingsValue => { const { organizations } = useDashboard(); diff --git a/site/src/pages/ManagementSettingsPage/OrganizationProvisionersPage.tsx b/site/src/pages/ManagementSettingsPage/OrganizationProvisionersPage.tsx index c233826ef07fc..3a048db2cb059 100644 --- a/site/src/pages/ManagementSettingsPage/OrganizationProvisionersPage.tsx +++ b/site/src/pages/ManagementSettingsPage/OrganizationProvisionersPage.tsx @@ -59,5 +59,9 @@ const OrganizationProvisionersPage: FC = () => { export default OrganizationProvisionersPage; -const getOrganizationByName = (organizations: Organization[], name: string) => - organizations.find((org) => org.name === name); +const getOrganizationByName = ( + organizations: readonly Organization[], + name: string, +) => { + return organizations.find((org) => org.name === name); +}; diff --git a/site/src/pages/ManagementSettingsPage/OrganizationSettingsPage.tsx b/site/src/pages/ManagementSettingsPage/OrganizationSettingsPage.tsx index 5eb1a6e0f4e49..7e63bf8111c2c 100644 --- a/site/src/pages/ManagementSettingsPage/OrganizationSettingsPage.tsx +++ b/site/src/pages/ManagementSettingsPage/OrganizationSettingsPage.tsx @@ -55,7 +55,7 @@ const OrganizationSettingsPage: FC = () => { // Redirect /organizations => /organizations/default-org, or if they cannot edit // the default org, then the first org they can edit, if any. if (!organizationName) { - const editableOrg = organizations + const editableOrg = [...organizations] .sort((a, b) => { // Prefer default org (it may not be first). // JavaScript will happily subtract booleans, but use numbers to keep @@ -112,5 +112,9 @@ const OrganizationSettingsPage: FC = () => { export default OrganizationSettingsPage; -const getOrganizationByName = (organizations: Organization[], name: string) => - organizations.find((org) => org.name === name); +const getOrganizationByName = ( + organizations: readonly Organization[], + name: string, +) => { + return organizations.find((org) => org.name === name); +}; diff --git a/site/src/pages/TemplatePage/TemplateRedirectController.tsx b/site/src/pages/TemplatePage/TemplateRedirectController.tsx index d1052b7a9c2d3..c4164746d1a6a 100644 --- a/site/src/pages/TemplatePage/TemplateRedirectController.tsx +++ b/site/src/pages/TemplatePage/TemplateRedirectController.tsx @@ -45,8 +45,11 @@ export const TemplateRedirectController: FC = () => { return ; }; -const getOrganizationNameByDefault = (organizations: Organization[]) => - organizations.find((org) => org.is_default)?.name; +const getOrganizationNameByDefault = ( + organizations: readonly Organization[], +) => { + return organizations.find((org) => org.is_default)?.name; +}; // I really hate doing it this way, but React Router does not provide a better way. const removePrefix = (self: string, prefix: string) => diff --git a/site/src/pages/WorkspacePage/WorkspaceNotifications/WorkspaceNotifications.tsx b/site/src/pages/WorkspacePage/WorkspaceNotifications/WorkspaceNotifications.tsx index ab6bbce85f368..bcab68a9a592f 100644 --- a/site/src/pages/WorkspacePage/WorkspaceNotifications/WorkspaceNotifications.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceNotifications/WorkspaceNotifications.tsx @@ -220,6 +220,12 @@ export const WorkspaceNotifications: FC = ({ (n) => n.severity === "warning", ); + // We have to avoid rendering out a div at all if there is no content so + // that we don't introduce additional gaps via the parent flex container + if (infoNotifications.length === 0 && warningNotifications.length === 0) { + return null; + } + return (
{infoNotifications.length > 0 && ( diff --git a/site/src/pages/WorkspacePage/WorkspaceScheduleControls.tsx b/site/src/pages/WorkspacePage/WorkspaceScheduleControls.tsx index 196f742104d21..607ab4d86e4d1 100644 --- a/site/src/pages/WorkspacePage/WorkspaceScheduleControls.tsx +++ b/site/src/pages/WorkspacePage/WorkspaceScheduleControls.tsx @@ -30,14 +30,15 @@ import { } from "utils/schedule"; import { isWorkspaceOn } from "utils/workspace"; -export interface WorkspaceScheduleContainerProps { +interface WorkspaceScheduleContainerProps { children?: ReactNode; onClickIcon?: () => void; } -export const WorkspaceScheduleContainer: FC< - WorkspaceScheduleContainerProps -> = ({ children, onClickIcon }) => { +const WorkspaceScheduleContainer: FC = ({ + children, + onClickIcon, +}) => { const icon = ( @@ -49,6 +50,7 @@ export const WorkspaceScheduleContainer: FC< {onClickIcon ? (