mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
chore: remove global organization id state (#14135)
This commit is contained in:
committed by
GitHub
parent
f9b660e573
commit
efbd6257e4
@ -300,10 +300,20 @@ const BASE_CONTENT_TYPE_JSON = {
|
|||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
} as const satisfies HeadersInit;
|
} as const satisfies HeadersInit;
|
||||||
|
|
||||||
type TemplateOptions = Readonly<{
|
export type GetTemplatesOptions = Readonly<{
|
||||||
readonly deprecated?: boolean;
|
readonly deprecated?: boolean;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
function normalizeGetTemplatesOptions(
|
||||||
|
options: GetTemplatesOptions = {},
|
||||||
|
): Record<string, string> {
|
||||||
|
const params: Record<string, string> = {};
|
||||||
|
if (options.deprecated !== undefined) {
|
||||||
|
params["deprecated"] = String(options.deprecated);
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
type SearchParamOptions = TypesGen.Pagination & {
|
type SearchParamOptions = TypesGen.Pagination & {
|
||||||
q?: string;
|
q?: string;
|
||||||
};
|
};
|
||||||
@ -625,21 +635,26 @@ class ApiMethods {
|
|||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getTemplates = async (
|
||||||
|
options?: GetTemplatesOptions,
|
||||||
|
): Promise<TypesGen.Template[]> => {
|
||||||
|
const params = normalizeGetTemplatesOptions(options);
|
||||||
|
const response = await this.axios.get<TypesGen.Template[]>(
|
||||||
|
`/api/v2/templates`,
|
||||||
|
{ params },
|
||||||
|
);
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param organization Can be the organization's ID or name
|
* @param organization Can be the organization's ID or name
|
||||||
*/
|
*/
|
||||||
getTemplates = async (
|
getTemplatesByOrganization = async (
|
||||||
organization: string,
|
organization: string,
|
||||||
options?: TemplateOptions,
|
options?: GetTemplatesOptions,
|
||||||
): Promise<TypesGen.Template[]> => {
|
): Promise<TypesGen.Template[]> => {
|
||||||
const params: Record<string, string> = {};
|
const params = normalizeGetTemplatesOptions(options);
|
||||||
if (options?.deprecated !== undefined) {
|
|
||||||
// Just want to check if it isn't undefined. If it has
|
|
||||||
// a boolean value, convert it to a string and include
|
|
||||||
// it as a param.
|
|
||||||
params["deprecated"] = String(options.deprecated);
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await this.axios.get<TypesGen.Template[]>(
|
const response = await this.axios.get<TypesGen.Template[]>(
|
||||||
`/api/v2/organizations/${organization}/templates`,
|
`/api/v2/organizations/${organization}/templates`,
|
||||||
{ params },
|
{ params },
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { MutationOptions, QueryClient, QueryOptions } from "react-query";
|
import type { MutationOptions, QueryClient, QueryOptions } from "react-query";
|
||||||
import { API } from "api/api";
|
import { API, type GetTemplatesOptions } from "api/api";
|
||||||
import type {
|
import type {
|
||||||
CreateTemplateRequest,
|
CreateTemplateRequest,
|
||||||
CreateTemplateVersionRequest,
|
CreateTemplateVersionRequest,
|
||||||
@ -38,16 +38,30 @@ export const templateByName = (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTemplatesQueryKey = (organizationId: string, deprecated?: boolean) => [
|
const getTemplatesQueryKey = (options?: GetTemplatesOptions) => [
|
||||||
organizationId,
|
|
||||||
"templates",
|
"templates",
|
||||||
deprecated,
|
options?.deprecated,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const templates = (organizationId: string, deprecated?: boolean) => {
|
export const templates = (options?: GetTemplatesOptions) => {
|
||||||
return {
|
return {
|
||||||
queryKey: getTemplatesQueryKey(organizationId, deprecated),
|
queryKey: getTemplatesQueryKey(options),
|
||||||
queryFn: () => API.getTemplates(organizationId, { deprecated }),
|
queryFn: () => API.getTemplates(options),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTemplatesByOrganizationQueryKey = (
|
||||||
|
organization: string,
|
||||||
|
options?: GetTemplatesOptions,
|
||||||
|
) => [organization, "templates", options?.deprecated];
|
||||||
|
|
||||||
|
export const templatesByOrganization = (
|
||||||
|
organization: string,
|
||||||
|
options: GetTemplatesOptions = {},
|
||||||
|
) => {
|
||||||
|
return {
|
||||||
|
queryKey: getTemplatesByOrganizationQueryKey(organization, options),
|
||||||
|
queryFn: () => API.getTemplatesByOrganization(organization, options),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,7 +114,10 @@ export const setGroupRole = (
|
|||||||
|
|
||||||
export const templateExamples = (organizationId: string) => {
|
export const templateExamples = (organizationId: string) => {
|
||||||
return {
|
return {
|
||||||
queryKey: [...getTemplatesQueryKey(organizationId), "examples"],
|
queryKey: [
|
||||||
|
...getTemplatesByOrganizationQueryKey(organizationId),
|
||||||
|
"examples",
|
||||||
|
],
|
||||||
queryFn: () => API.getTemplateExamples(organizationId),
|
queryFn: () => API.getTemplateExamples(organizationId),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -3,23 +3,22 @@ import { useQuery } from "react-query";
|
|||||||
import { appearance } from "api/queries/appearance";
|
import { appearance } from "api/queries/appearance";
|
||||||
import { entitlements } from "api/queries/entitlements";
|
import { entitlements } from "api/queries/entitlements";
|
||||||
import { experiments } from "api/queries/experiments";
|
import { experiments } from "api/queries/experiments";
|
||||||
|
import { organizations } from "api/queries/organizations";
|
||||||
import type {
|
import type {
|
||||||
AppearanceConfig,
|
AppearanceConfig,
|
||||||
Entitlements,
|
Entitlements,
|
||||||
Experiments,
|
Experiments,
|
||||||
|
Organization,
|
||||||
} from "api/typesGenerated";
|
} from "api/typesGenerated";
|
||||||
|
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||||
import { Loader } from "components/Loader/Loader";
|
import { Loader } from "components/Loader/Loader";
|
||||||
import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata";
|
import { useEmbeddedMetadata } from "hooks/useEmbeddedMetadata";
|
||||||
|
|
||||||
export interface DashboardValue {
|
export interface DashboardValue {
|
||||||
/**
|
|
||||||
* @deprecated Do not add new usage of this value. It is being removed as part
|
|
||||||
* of the multi-org work.
|
|
||||||
*/
|
|
||||||
organizationId: string;
|
|
||||||
entitlements: Entitlements;
|
entitlements: Entitlements;
|
||||||
experiments: Experiments;
|
experiments: Experiments;
|
||||||
appearance: AppearanceConfig;
|
appearance: AppearanceConfig;
|
||||||
|
organizations: Organization[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DashboardContext = createContext<DashboardValue | undefined>(
|
export const DashboardContext = createContext<DashboardValue | undefined>(
|
||||||
@ -31,9 +30,23 @@ export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => {
|
|||||||
const entitlementsQuery = useQuery(entitlements(metadata.entitlements));
|
const entitlementsQuery = useQuery(entitlements(metadata.entitlements));
|
||||||
const experimentsQuery = useQuery(experiments(metadata.experiments));
|
const experimentsQuery = useQuery(experiments(metadata.experiments));
|
||||||
const appearanceQuery = useQuery(appearance(metadata.appearance));
|
const appearanceQuery = useQuery(appearance(metadata.appearance));
|
||||||
|
const organizationsQuery = useQuery(organizations());
|
||||||
|
|
||||||
|
const error =
|
||||||
|
entitlementsQuery.error ||
|
||||||
|
appearanceQuery.error ||
|
||||||
|
experimentsQuery.error ||
|
||||||
|
organizationsQuery.error;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return <ErrorAlert error={error} />;
|
||||||
|
}
|
||||||
|
|
||||||
const isLoading =
|
const isLoading =
|
||||||
!entitlementsQuery.data || !appearanceQuery.data || !experimentsQuery.data;
|
!entitlementsQuery.data ||
|
||||||
|
!appearanceQuery.data ||
|
||||||
|
!experimentsQuery.data ||
|
||||||
|
!organizationsQuery.data;
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <Loader fullscreen />;
|
return <Loader fullscreen />;
|
||||||
@ -42,10 +55,10 @@ export const DashboardProvider: FC<PropsWithChildren> = ({ children }) => {
|
|||||||
return (
|
return (
|
||||||
<DashboardContext.Provider
|
<DashboardContext.Provider
|
||||||
value={{
|
value={{
|
||||||
organizationId: "00000000-0000-0000-0000-000000000000",
|
|
||||||
entitlements: entitlementsQuery.data,
|
entitlements: entitlementsQuery.data,
|
||||||
experiments: experimentsQuery.data,
|
experiments: experimentsQuery.data,
|
||||||
appearance: appearanceQuery.data,
|
appearance: appearanceQuery.data,
|
||||||
|
organizations: organizationsQuery.data,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
@ -27,8 +27,13 @@ export const linkToUsers = withFilter("/users", "status:active");
|
|||||||
|
|
||||||
export const linkToTemplate =
|
export const linkToTemplate =
|
||||||
(organizationName: string, templateName: string): LinkThunk =>
|
(organizationName: string, templateName: string): LinkThunk =>
|
||||||
(dashboard) =>
|
(dashboard) => {
|
||||||
dashboard.experiments.includes("multi-organization") &&
|
const hasMultipleOrganizations = dashboard.organizations.length > 1;
|
||||||
selectFeatureVisibility(dashboard.entitlements).multiple_organizations
|
const organizationsEnabled =
|
||||||
|
dashboard.experiments.includes("multi-organization") &&
|
||||||
|
selectFeatureVisibility(dashboard.entitlements).multiple_organizations;
|
||||||
|
|
||||||
|
return hasMultipleOrganizations || organizationsEnabled
|
||||||
? `/templates/${organizationName}/${templateName}`
|
? `/templates/${organizationName}/${templateName}`
|
||||||
: `/templates/${templateName}`;
|
: `/templates/${templateName}`;
|
||||||
|
};
|
||||||
|
@ -233,13 +233,13 @@ export const CreateTemplateForm: FC<CreateTemplateFormProps> = (props) => {
|
|||||||
|
|
||||||
{showOrganizationPicker && (
|
{showOrganizationPicker && (
|
||||||
<OrganizationAutocomplete
|
<OrganizationAutocomplete
|
||||||
{...getFieldHelpers("organization_id")}
|
{...getFieldHelpers("organization")}
|
||||||
required
|
required
|
||||||
label="Belongs to"
|
label="Belongs to"
|
||||||
value={selectedOrg}
|
value={selectedOrg}
|
||||||
onChange={(newValue) => {
|
onChange={(newValue) => {
|
||||||
setSelectedOrg(newValue);
|
setSelectedOrg(newValue);
|
||||||
void form.setFieldValue("organization", newValue?.id || "");
|
void form.setFieldValue("organization", newValue?.name || "");
|
||||||
}}
|
}}
|
||||||
size="medium"
|
size="medium"
|
||||||
/>
|
/>
|
||||||
|
@ -65,7 +65,6 @@ export interface CreateUserFormProps {
|
|||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
error?: unknown;
|
error?: unknown;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
organizationId: string;
|
|
||||||
authMethods?: TypesGen.AuthMethods;
|
authMethods?: TypesGen.AuthMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +85,7 @@ const validationSchema = Yup.object({
|
|||||||
|
|
||||||
export const CreateUserForm: FC<
|
export const CreateUserForm: FC<
|
||||||
React.PropsWithChildren<CreateUserFormProps>
|
React.PropsWithChildren<CreateUserFormProps>
|
||||||
> = ({ onSubmit, onCancel, error, isLoading, organizationId, authMethods }) => {
|
> = ({ onSubmit, onCancel, error, isLoading, authMethods }) => {
|
||||||
const form: FormikContextType<TypesGen.CreateUserRequest> =
|
const form: FormikContextType<TypesGen.CreateUserRequest> =
|
||||||
useFormik<TypesGen.CreateUserRequest>({
|
useFormik<TypesGen.CreateUserRequest>({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
@ -94,7 +93,7 @@ export const CreateUserForm: FC<
|
|||||||
password: "",
|
password: "",
|
||||||
username: "",
|
username: "",
|
||||||
name: "",
|
name: "",
|
||||||
organization_id: organizationId,
|
organization_id: "00000000-0000-0000-0000-000000000000",
|
||||||
disable_login: false,
|
disable_login: false,
|
||||||
login_type: "",
|
login_type: "",
|
||||||
},
|
},
|
||||||
|
@ -5,7 +5,6 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import { authMethods, createUser } from "api/queries/users";
|
import { authMethods, createUser } from "api/queries/users";
|
||||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||||
import { Margins } from "components/Margins/Margins";
|
import { Margins } from "components/Margins/Margins";
|
||||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
|
||||||
import { pageTitle } from "utils/page";
|
import { pageTitle } from "utils/page";
|
||||||
import { CreateUserForm } from "./CreateUserForm";
|
import { CreateUserForm } from "./CreateUserForm";
|
||||||
|
|
||||||
@ -14,7 +13,6 @@ export const Language = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const CreateUserPage: FC = () => {
|
export const CreateUserPage: FC = () => {
|
||||||
const { organizationId } = useDashboard();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const createUserMutation = useMutation(createUser(queryClient));
|
const createUserMutation = useMutation(createUser(queryClient));
|
||||||
@ -38,7 +36,6 @@ export const CreateUserPage: FC = () => {
|
|||||||
navigate("..", { relative: "path" });
|
navigate("..", { relative: "path" });
|
||||||
}}
|
}}
|
||||||
isLoading={createUserMutation.isLoading}
|
isLoading={createUserMutation.isLoading}
|
||||||
organizationId={organizationId}
|
|
||||||
/>
|
/>
|
||||||
</Margins>
|
</Margins>
|
||||||
);
|
);
|
||||||
|
@ -33,13 +33,12 @@ export type CreateWorkspaceMode = (typeof createWorkspaceModes)[number];
|
|||||||
export type ExternalAuthPollingState = "idle" | "polling" | "abandoned";
|
export type ExternalAuthPollingState = "idle" | "polling" | "abandoned";
|
||||||
|
|
||||||
const CreateWorkspacePage: FC = () => {
|
const CreateWorkspacePage: FC = () => {
|
||||||
const { template: templateName } = useParams() as {
|
const { organization: organizationName = "default", template: templateName } =
|
||||||
template: string;
|
useParams() as { organization?: string; template: string };
|
||||||
};
|
|
||||||
const { user: me } = useAuthenticated();
|
const { user: me } = useAuthenticated();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const { experiments, organizationId } = useDashboard();
|
const { experiments } = useDashboard();
|
||||||
|
|
||||||
const customVersionId = searchParams.get("version") ?? undefined;
|
const customVersionId = searchParams.get("version") ?? undefined;
|
||||||
const defaultName = searchParams.get("name");
|
const defaultName = searchParams.get("name");
|
||||||
@ -54,15 +53,19 @@ const CreateWorkspacePage: FC = () => {
|
|||||||
);
|
);
|
||||||
const createWorkspaceMutation = useMutation(createWorkspace(queryClient));
|
const createWorkspaceMutation = useMutation(createWorkspace(queryClient));
|
||||||
|
|
||||||
const templateQuery = useQuery(templateByName(organizationId, templateName));
|
const templateQuery = useQuery(
|
||||||
|
templateByName(organizationName, templateName),
|
||||||
|
);
|
||||||
const permissionsQuery = useQuery(
|
const permissionsQuery = useQuery(
|
||||||
checkAuthorization({
|
templateQuery.data
|
||||||
checks: createWorkspaceChecks(organizationId),
|
? checkAuthorization({
|
||||||
}),
|
checks: createWorkspaceChecks(templateQuery.data.organization_id),
|
||||||
|
})
|
||||||
|
: { enabled: false },
|
||||||
);
|
);
|
||||||
const realizedVersionId =
|
const realizedVersionId =
|
||||||
customVersionId ?? templateQuery.data?.active_version_id;
|
customVersionId ?? templateQuery.data?.active_version_id;
|
||||||
|
const organizationId = templateQuery.data?.organization_id;
|
||||||
const richParametersQuery = useQuery({
|
const richParametersQuery = useQuery({
|
||||||
...richParameters(realizedVersionId ?? ""),
|
...richParameters(realizedVersionId ?? ""),
|
||||||
enabled: realizedVersionId !== undefined,
|
enabled: realizedVersionId !== undefined,
|
||||||
@ -110,7 +113,7 @@ const CreateWorkspacePage: FC = () => {
|
|||||||
|
|
||||||
const autoCreationStartedRef = useRef(false);
|
const autoCreationStartedRef = useRef(false);
|
||||||
const automateWorkspaceCreation = useEffectEvent(async () => {
|
const automateWorkspaceCreation = useEffectEvent(async () => {
|
||||||
if (autoCreationStartedRef.current) {
|
if (autoCreationStartedRef.current || !organizationId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,17 +5,15 @@ import { getErrorMessage } from "api/errors";
|
|||||||
import { groups } from "api/queries/groups";
|
import { groups } from "api/queries/groups";
|
||||||
import { displayError } from "components/GlobalSnackbar/utils";
|
import { displayError } from "components/GlobalSnackbar/utils";
|
||||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
|
||||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||||
import { pageTitle } from "utils/page";
|
import { pageTitle } from "utils/page";
|
||||||
import GroupsPageView from "./GroupsPageView";
|
import GroupsPageView from "./GroupsPageView";
|
||||||
|
|
||||||
export const GroupsPage: FC = () => {
|
export const GroupsPage: FC = () => {
|
||||||
const { permissions } = useAuthenticated();
|
const { permissions } = useAuthenticated();
|
||||||
const { organizationId } = useDashboard();
|
|
||||||
const { createGroup: canCreateGroup } = permissions;
|
const { createGroup: canCreateGroup } = permissions;
|
||||||
const { template_rbac: isTemplateRBACEnabled } = useFeatureVisibility();
|
const { template_rbac: isTemplateRBACEnabled } = useFeatureVisibility();
|
||||||
const groupsQuery = useQuery(groups(organizationId));
|
const groupsQuery = useQuery(groups("default"));
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (groupsQuery.error) {
|
if (groupsQuery.error) {
|
||||||
|
@ -51,7 +51,7 @@ import { pageTitle } from "utils/page";
|
|||||||
|
|
||||||
export const GroupPage: FC = () => {
|
export const GroupPage: FC = () => {
|
||||||
const { organization = "default", groupName } = useParams() as {
|
const { organization = "default", groupName } = useParams() as {
|
||||||
organization: string;
|
organization?: string;
|
||||||
groupName: string;
|
groupName: string;
|
||||||
};
|
};
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
@ -12,7 +12,7 @@ import GroupSettingsPageView from "./GroupSettingsPageView";
|
|||||||
|
|
||||||
export const GroupSettingsPage: FC = () => {
|
export const GroupSettingsPage: FC = () => {
|
||||||
const { organization = "default", groupName } = useParams() as {
|
const { organization = "default", groupName } = useParams() as {
|
||||||
organization: string;
|
organization?: string;
|
||||||
groupName: string;
|
groupName: string;
|
||||||
};
|
};
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
@ -30,7 +30,7 @@ export const GroupsPage: FC = () => {
|
|||||||
} = useFeatureVisibility();
|
} = useFeatureVisibility();
|
||||||
const { experiments } = useDashboard();
|
const { experiments } = useDashboard();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { organization = "default" } = useParams() as { organization: string };
|
const { organization = "default" } = useParams() as { organization?: string };
|
||||||
const groupsQuery = useQuery(groups(organization));
|
const groupsQuery = useQuery(groups(organization));
|
||||||
const { organizations } = useOrganizationSettings();
|
const { organizations } = useOrganizationSettings();
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { createContext, type FC, Suspense, useContext } from "react";
|
import { type FC, Suspense } from "react";
|
||||||
import { useQuery } from "react-query";
|
import { useQuery } from "react-query";
|
||||||
import { Outlet } from "react-router-dom";
|
import { Outlet } from "react-router-dom";
|
||||||
import { deploymentConfig } from "api/queries/deployment";
|
import { deploymentConfig } from "api/queries/deployment";
|
||||||
import { organizations } from "api/queries/organizations";
|
|
||||||
import type { Organization } from "api/typesGenerated";
|
import type { Organization } from "api/typesGenerated";
|
||||||
import { Loader } from "components/Loader/Loader";
|
import { Loader } from "components/Loader/Loader";
|
||||||
import { Margins } from "components/Margins/Margins";
|
import { Margins } from "components/Margins/Margins";
|
||||||
@ -14,29 +13,17 @@ import NotFoundPage from "pages/404Page/404Page";
|
|||||||
import { DeploySettingsContext } from "../DeploySettingsPage/DeploySettingsLayout";
|
import { DeploySettingsContext } from "../DeploySettingsPage/DeploySettingsLayout";
|
||||||
import { Sidebar } from "./Sidebar";
|
import { Sidebar } from "./Sidebar";
|
||||||
|
|
||||||
type OrganizationSettingsContextValue = {
|
type OrganizationSettingsValue = { organizations: Organization[] };
|
||||||
organizations: Organization[];
|
|
||||||
};
|
|
||||||
|
|
||||||
const OrganizationSettingsContext = createContext<
|
export const useOrganizationSettings = (): OrganizationSettingsValue => {
|
||||||
OrganizationSettingsContextValue | undefined
|
const { organizations } = useDashboard();
|
||||||
>(undefined);
|
return { organizations };
|
||||||
|
|
||||||
export const useOrganizationSettings = (): OrganizationSettingsContextValue => {
|
|
||||||
const context = useContext(OrganizationSettingsContext);
|
|
||||||
if (!context) {
|
|
||||||
throw new Error(
|
|
||||||
"useOrganizationSettings should be used inside of OrganizationSettingsLayout",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ManagementSettingsLayout: FC = () => {
|
export const ManagementSettingsLayout: FC = () => {
|
||||||
const { permissions } = useAuthenticated();
|
const { permissions } = useAuthenticated();
|
||||||
const { experiments } = useDashboard();
|
const { experiments } = useDashboard();
|
||||||
const deploymentConfigQuery = useQuery(deploymentConfig());
|
const deploymentConfigQuery = useQuery(deploymentConfig());
|
||||||
const organizationsQuery = useQuery(organizations());
|
|
||||||
|
|
||||||
const multiOrgExperimentEnabled = experiments.includes("multi-organization");
|
const multiOrgExperimentEnabled = experiments.includes("multi-organization");
|
||||||
|
|
||||||
@ -48,30 +35,20 @@ export const ManagementSettingsLayout: FC = () => {
|
|||||||
<RequirePermission isFeatureVisible={permissions.viewDeploymentValues}>
|
<RequirePermission isFeatureVisible={permissions.viewDeploymentValues}>
|
||||||
<Margins>
|
<Margins>
|
||||||
<Stack css={{ padding: "48px 0" }} direction="row" spacing={6}>
|
<Stack css={{ padding: "48px 0" }} direction="row" spacing={6}>
|
||||||
{organizationsQuery.data ? (
|
<Sidebar />
|
||||||
<OrganizationSettingsContext.Provider
|
<main css={{ width: "100%" }}>
|
||||||
value={{ organizations: organizationsQuery.data }}
|
{deploymentConfigQuery.data ? (
|
||||||
>
|
<DeploySettingsContext.Provider
|
||||||
<Sidebar />
|
value={{ deploymentValues: deploymentConfigQuery.data }}
|
||||||
<main css={{ width: "100%" }}>
|
>
|
||||||
{deploymentConfigQuery.data ? (
|
<Suspense fallback={<Loader />}>
|
||||||
<DeploySettingsContext.Provider
|
<Outlet />
|
||||||
value={{
|
</Suspense>
|
||||||
deploymentValues: deploymentConfigQuery.data,
|
</DeploySettingsContext.Provider>
|
||||||
}}
|
) : (
|
||||||
>
|
<Loader />
|
||||||
<Suspense fallback={<Loader />}>
|
)}
|
||||||
<Outlet />
|
</main>
|
||||||
</Suspense>
|
|
||||||
</DeploySettingsContext.Provider>
|
|
||||||
) : (
|
|
||||||
<Loader />
|
|
||||||
)}
|
|
||||||
</main>
|
|
||||||
</OrganizationSettingsContext.Provider>
|
|
||||||
) : (
|
|
||||||
<Loader />
|
|
||||||
)}
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</Margins>
|
</Margins>
|
||||||
</RequirePermission>
|
</RequirePermission>
|
||||||
|
@ -9,15 +9,19 @@ import { useTemplateLayoutContext } from "pages/TemplatePage/TemplateLayout";
|
|||||||
import { getTemplatePageTitle } from "../utils";
|
import { getTemplatePageTitle } from "../utils";
|
||||||
|
|
||||||
const TemplateFilesPage: FC = () => {
|
const TemplateFilesPage: FC = () => {
|
||||||
const { organization: organizationId = "default" } = useParams() as {
|
const { organization: organizationName = "default" } = useParams() as {
|
||||||
organization: string;
|
organization?: string;
|
||||||
};
|
};
|
||||||
const { template, activeVersion } = useTemplateLayoutContext();
|
const { template, activeVersion } = useTemplateLayoutContext();
|
||||||
const { data: currentFiles } = useQuery(
|
const { data: currentFiles } = useQuery(
|
||||||
templateFiles(activeVersion.job.file_id),
|
templateFiles(activeVersion.job.file_id),
|
||||||
);
|
);
|
||||||
const previousVersionQuery = useQuery(
|
const previousVersionQuery = useQuery(
|
||||||
previousTemplateVersion(organizationId, template.name, activeVersion.name),
|
previousTemplateVersion(
|
||||||
|
organizationName,
|
||||||
|
template.name,
|
||||||
|
activeVersion.name,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const previousVersion = previousVersionQuery.data;
|
const previousVersion = previousVersionQuery.data;
|
||||||
const hasPreviousVersion =
|
const hasPreviousVersion =
|
||||||
|
@ -71,14 +71,11 @@ export const TemplateLayout: FC<PropsWithChildren> = ({
|
|||||||
children = <Outlet />,
|
children = <Outlet />,
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { template: templateName, organization: organizationId = "default" } =
|
const { organization: organizationName = "default", template: templateName } =
|
||||||
useParams() as {
|
useParams() as { organization?: string; template: string };
|
||||||
template: string;
|
|
||||||
organization: string;
|
|
||||||
};
|
|
||||||
const { data, error, isLoading } = useQuery({
|
const { data, error, isLoading } = useQuery({
|
||||||
queryKey: ["template", templateName],
|
queryKey: ["template", templateName],
|
||||||
queryFn: () => fetchTemplate(organizationId, templateName),
|
queryFn: () => fetchTemplate(organizationName, templateName),
|
||||||
});
|
});
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const paths = location.pathname.split("/");
|
const paths = location.pathname.split("/");
|
||||||
|
@ -7,19 +7,19 @@ import { templateByNameKey } from "api/queries/templates";
|
|||||||
import type { UpdateTemplateMeta } from "api/typesGenerated";
|
import type { UpdateTemplateMeta } from "api/typesGenerated";
|
||||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||||
|
import { linkToTemplate, useLinks } from "modules/navigation";
|
||||||
import { pageTitle } from "utils/page";
|
import { pageTitle } from "utils/page";
|
||||||
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||||
import { TemplateSchedulePageView } from "./TemplateSchedulePageView";
|
import { TemplateSchedulePageView } from "./TemplateSchedulePageView";
|
||||||
|
|
||||||
const TemplateSchedulePage: FC = () => {
|
const TemplateSchedulePage: FC = () => {
|
||||||
const { template: templateName } = useParams() as { template: string };
|
const getLink = useLinks();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const { template } = useTemplateSettings();
|
const { template } = useTemplateSettings();
|
||||||
const { entitlements } = useDashboard();
|
const { entitlements } = useDashboard();
|
||||||
const { organization: organizationId = "default" } = useParams() as {
|
const { organization: organizationName = "default", template: templateName } =
|
||||||
organization: string;
|
useParams() as { organization?: string; template: string };
|
||||||
};
|
|
||||||
const allowAdvancedScheduling =
|
const allowAdvancedScheduling =
|
||||||
entitlements.features["advanced_template_scheduling"].enabled;
|
entitlements.features["advanced_template_scheduling"].enabled;
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ const TemplateSchedulePage: FC = () => {
|
|||||||
{
|
{
|
||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries(
|
await queryClient.invalidateQueries(
|
||||||
templateByNameKey(organizationId, templateName),
|
templateByNameKey(organizationName, templateName),
|
||||||
);
|
);
|
||||||
displaySuccess("Template updated successfully");
|
displaySuccess("Template updated successfully");
|
||||||
// clear browser storage of workspaces impending deletion
|
// clear browser storage of workspaces impending deletion
|
||||||
@ -53,7 +53,7 @@ const TemplateSchedulePage: FC = () => {
|
|||||||
template={template}
|
template={template}
|
||||||
submitError={submitError}
|
submitError={submitError}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
navigate(`/templates/${organizationId}/${templateName}`);
|
navigate(getLink(linkToTemplate(organizationName, templateName)));
|
||||||
}}
|
}}
|
||||||
onSubmit={(templateScheduleSettings) => {
|
onSubmit={(templateScheduleSettings) => {
|
||||||
updateTemplate({
|
updateTemplate({
|
||||||
|
@ -27,10 +27,7 @@ export function useTemplateSettings() {
|
|||||||
|
|
||||||
export const TemplateSettingsLayout: FC = () => {
|
export const TemplateSettingsLayout: FC = () => {
|
||||||
const { organization: organizationName = "default", template: templateName } =
|
const { organization: organizationName = "default", template: templateName } =
|
||||||
useParams() as {
|
useParams() as { organization?: string; template: string };
|
||||||
organization: string;
|
|
||||||
template: string;
|
|
||||||
};
|
|
||||||
const templateQuery = useQuery(
|
const templateQuery = useQuery(
|
||||||
templateByName(organizationName, templateName),
|
templateByName(organizationName, templateName),
|
||||||
);
|
);
|
||||||
|
@ -16,13 +16,15 @@ import type {
|
|||||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||||
import { Loader } from "components/Loader/Loader";
|
import { Loader } from "components/Loader/Loader";
|
||||||
|
import { linkToTemplate, useLinks } from "modules/navigation";
|
||||||
import { pageTitle } from "utils/page";
|
import { pageTitle } from "utils/page";
|
||||||
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||||
import { TemplateVariablesPageView } from "./TemplateVariablesPageView";
|
import { TemplateVariablesPageView } from "./TemplateVariablesPageView";
|
||||||
|
|
||||||
export const TemplateVariablesPage: FC = () => {
|
export const TemplateVariablesPage: FC = () => {
|
||||||
|
const getLink = useLinks();
|
||||||
const { organization = "default", template: templateName } = useParams() as {
|
const { organization = "default", template: templateName } = useParams() as {
|
||||||
organization: string;
|
organization?: string;
|
||||||
template: string;
|
template: string;
|
||||||
};
|
};
|
||||||
const { template } = useTemplateSettings();
|
const { template } = useTemplateSettings();
|
||||||
@ -97,7 +99,7 @@ export const TemplateVariablesPage: FC = () => {
|
|||||||
publishError,
|
publishError,
|
||||||
}}
|
}}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
navigate(`/templates/${organization}/${templateName}`);
|
navigate(getLink(linkToTemplate(organization, templateName)));
|
||||||
}}
|
}}
|
||||||
onSubmit={async (formData) => {
|
onSubmit={async (formData) => {
|
||||||
const request = filterEmptySensitiveVariables(formData, variables);
|
const request = filterEmptySensitiveVariables(formData, variables);
|
||||||
|
@ -35,7 +35,7 @@ export const TemplateVersionEditorPage: FC = () => {
|
|||||||
template: templateName,
|
template: templateName,
|
||||||
version: versionName,
|
version: versionName,
|
||||||
} = useParams() as {
|
} = useParams() as {
|
||||||
organization: string;
|
organization?: string;
|
||||||
template: string;
|
template: string;
|
||||||
version: string;
|
version: string;
|
||||||
};
|
};
|
||||||
@ -194,7 +194,9 @@ export const TemplateVersionEditorPage: FC = () => {
|
|||||||
params.set("version", publishedVersion.id);
|
params.set("version", publishedVersion.id);
|
||||||
}
|
}
|
||||||
navigate(
|
navigate(
|
||||||
`/templates/${organizationName}/${templateName}/workspace?${params.toString()}`,
|
`${getLink(
|
||||||
|
linkToTemplate(organizationName, templateName),
|
||||||
|
)}/workspace?${params.toString()}`,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
isBuilding={
|
isBuilding={
|
||||||
|
@ -9,16 +9,18 @@ import {
|
|||||||
templateVersionByName,
|
templateVersionByName,
|
||||||
} from "api/queries/templates";
|
} from "api/queries/templates";
|
||||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||||
|
import { linkToTemplate, useLinks } from "modules/navigation";
|
||||||
import { pageTitle } from "utils/page";
|
import { pageTitle } from "utils/page";
|
||||||
import TemplateVersionPageView from "./TemplateVersionPageView";
|
import TemplateVersionPageView from "./TemplateVersionPageView";
|
||||||
|
|
||||||
export const TemplateVersionPage: FC = () => {
|
export const TemplateVersionPage: FC = () => {
|
||||||
|
const getLink = useLinks();
|
||||||
const {
|
const {
|
||||||
organization: organizationName = "default",
|
organization: organizationName = "default",
|
||||||
template: templateName,
|
template: templateName,
|
||||||
version: versionName,
|
version: versionName,
|
||||||
} = useParams() as {
|
} = useParams() as {
|
||||||
organization: string;
|
organization?: string;
|
||||||
template: string;
|
template: string;
|
||||||
version: string;
|
version: string;
|
||||||
};
|
};
|
||||||
@ -51,10 +53,12 @@ export const TemplateVersionPage: FC = () => {
|
|||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
if (versionId) {
|
if (versionId) {
|
||||||
params.set("version", versionId);
|
params.set("version", versionId);
|
||||||
return `/templates/${organizationName}/${templateName}/workspace?${params.toString()}`;
|
return `${getLink(
|
||||||
|
linkToTemplate(organizationName, templateName),
|
||||||
|
)}/workspace?${params.toString()}`;
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}, [templateName, versionId, organizationName]);
|
}, [getLink, templateName, versionId, organizationName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -3,15 +3,13 @@ import { Helmet } from "react-helmet-async";
|
|||||||
import { useQuery } from "react-query";
|
import { useQuery } from "react-query";
|
||||||
import { templateExamples, templates } from "api/queries/templates";
|
import { templateExamples, templates } from "api/queries/templates";
|
||||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
|
||||||
import { pageTitle } from "utils/page";
|
import { pageTitle } from "utils/page";
|
||||||
import { TemplatesPageView } from "./TemplatesPageView";
|
import { TemplatesPageView } from "./TemplatesPageView";
|
||||||
|
|
||||||
export const TemplatesPage: FC = () => {
|
export const TemplatesPage: FC = () => {
|
||||||
const { permissions } = useAuthenticated();
|
const { permissions } = useAuthenticated();
|
||||||
const { organizationId } = useDashboard();
|
|
||||||
|
|
||||||
const templatesQuery = useQuery(templates(organizationId));
|
const templatesQuery = useQuery(templates());
|
||||||
const examplesQuery = useQuery({
|
const examplesQuery = useQuery({
|
||||||
...templateExamples("default"),
|
...templateExamples("default"),
|
||||||
enabled: permissions.createTemplates,
|
enabled: permissions.createTemplates,
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
MockAppearanceConfig,
|
MockAppearanceConfig,
|
||||||
MockAuthMethodsAll,
|
MockAuthMethodsAll,
|
||||||
MockBuildInfo,
|
MockBuildInfo,
|
||||||
|
MockDefaultOrganization,
|
||||||
MockEntitlements,
|
MockEntitlements,
|
||||||
MockExperiments,
|
MockExperiments,
|
||||||
MockUser,
|
MockUser,
|
||||||
@ -70,6 +71,7 @@ const meta = {
|
|||||||
{ key: ["entitlements"], data: MockEntitlements },
|
{ key: ["entitlements"], data: MockEntitlements },
|
||||||
{ key: ["experiments"], data: MockExperiments },
|
{ key: ["experiments"], data: MockExperiments },
|
||||||
{ key: ["appearance"], data: MockAppearanceConfig },
|
{ key: ["appearance"], data: MockAppearanceConfig },
|
||||||
|
{ key: ["organizations"], data: [MockDefaultOrganization] },
|
||||||
{
|
{
|
||||||
key: getAuthorizationKey({ checks: permissionsToCheck }),
|
key: getAuthorizationKey({ checks: permissionsToCheck }),
|
||||||
data: { editWorkspaceProxies: true },
|
data: { editWorkspaceProxies: true },
|
||||||
|
@ -13,11 +13,12 @@ export const AccountPage: FC = () => {
|
|||||||
const { permissions, user: me } = useAuthenticated();
|
const { permissions, user: me } = useAuthenticated();
|
||||||
const { updateProfile, updateProfileError, isUpdatingProfile } =
|
const { updateProfile, updateProfileError, isUpdatingProfile } =
|
||||||
useAuthContext();
|
useAuthContext();
|
||||||
const { entitlements, organizationId } = useDashboard();
|
const { entitlements } = useDashboard();
|
||||||
|
|
||||||
const hasGroupsFeature = entitlements.features.user_role_management.enabled;
|
const hasGroupsFeature = entitlements.features.user_role_management.enabled;
|
||||||
const groupsQuery = useQuery({
|
const groupsQuery = useQuery({
|
||||||
...groupsForUser(organizationId, me.id),
|
// TODO: This should probably list all groups, not just default org groups
|
||||||
|
...groupsForUser("default", me.id),
|
||||||
enabled: hasGroupsFeature,
|
enabled: hasGroupsFeature,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -40,11 +40,11 @@ const UsersPage: FC = () => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const searchParamsResult = useSearchParams();
|
const searchParamsResult = useSearchParams();
|
||||||
const { entitlements, experiments, organizationId } = useDashboard();
|
const { entitlements, experiments } = useDashboard();
|
||||||
const [searchParams] = searchParamsResult;
|
const [searchParams] = searchParamsResult;
|
||||||
const isMultiOrg = experiments.includes("multi-organization");
|
const isMultiOrg = experiments.includes("multi-organization");
|
||||||
|
|
||||||
const groupsByUserIdQuery = useQuery(groupsByUserId(organizationId));
|
const groupsByUserIdQuery = useQuery(groupsByUserId("default"));
|
||||||
const authMethodsQuery = useQuery(authMethods());
|
const authMethodsQuery = useQuery(authMethods());
|
||||||
|
|
||||||
const { permissions, user: me } = useAuthenticated();
|
const { permissions, user: me } = useAuthenticated();
|
||||||
|
@ -3,7 +3,7 @@ import { useQuery, useQueryClient } from "react-query";
|
|||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { watchWorkspace } from "api/api";
|
import { watchWorkspace } from "api/api";
|
||||||
import { checkAuthorization } from "api/queries/authCheck";
|
import { checkAuthorization } from "api/queries/authCheck";
|
||||||
import { templateByName } from "api/queries/templates";
|
import { template as templateQueryOptions } from "api/queries/templates";
|
||||||
import { workspaceBuildsKey } from "api/queries/workspaceBuilds";
|
import { workspaceBuildsKey } from "api/queries/workspaceBuilds";
|
||||||
import { workspaceByOwnerAndName } from "api/queries/workspaces";
|
import { workspaceByOwnerAndName } from "api/queries/workspaces";
|
||||||
import type { Workspace } from "api/typesGenerated";
|
import type { Workspace } from "api/typesGenerated";
|
||||||
@ -13,7 +13,6 @@ import { Margins } from "components/Margins/Margins";
|
|||||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||||
import { AnnouncementBanners } from "modules/dashboard/AnnouncementBanners/AnnouncementBanners";
|
import { AnnouncementBanners } from "modules/dashboard/AnnouncementBanners/AnnouncementBanners";
|
||||||
import { Navbar } from "modules/dashboard/Navbar/Navbar";
|
import { Navbar } from "modules/dashboard/Navbar/Navbar";
|
||||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
|
||||||
import { workspaceChecks, type WorkspacePermissions } from "./permissions";
|
import { workspaceChecks, type WorkspacePermissions } from "./permissions";
|
||||||
import { WorkspaceReadyPage } from "./WorkspaceReadyPage";
|
import { WorkspaceReadyPage } from "./WorkspaceReadyPage";
|
||||||
|
|
||||||
@ -25,7 +24,6 @@ export const WorkspacePage: FC = () => {
|
|||||||
};
|
};
|
||||||
const workspaceName = params.workspace;
|
const workspaceName = params.workspace;
|
||||||
const username = params.username.replace("@", "");
|
const username = params.username.replace("@", "");
|
||||||
const { organizationId } = useDashboard();
|
|
||||||
|
|
||||||
// Workspace
|
// Workspace
|
||||||
const workspaceQueryOptions = workspaceByOwnerAndName(
|
const workspaceQueryOptions = workspaceByOwnerAndName(
|
||||||
@ -36,10 +34,11 @@ export const WorkspacePage: FC = () => {
|
|||||||
const workspace = workspaceQuery.data;
|
const workspace = workspaceQuery.data;
|
||||||
|
|
||||||
// Template
|
// Template
|
||||||
const templateQuery = useQuery({
|
const templateQuery = useQuery(
|
||||||
...templateByName(organizationId, workspace?.template_name ?? ""),
|
workspace
|
||||||
enabled: workspace !== undefined,
|
? templateQueryOptions(workspace.template_id)
|
||||||
});
|
: { enabled: false },
|
||||||
|
);
|
||||||
const template = templateQuery.data;
|
const template = templateQuery.data;
|
||||||
|
|
||||||
// Permissions
|
// Permissions
|
||||||
|
@ -39,13 +39,12 @@ const WorkspacesPage: FC = () => {
|
|||||||
const searchParamsResult = useSafeSearchParams();
|
const searchParamsResult = useSafeSearchParams();
|
||||||
const pagination = usePagination({ searchParamsResult });
|
const pagination = usePagination({ searchParamsResult });
|
||||||
const { permissions } = useAuthenticated();
|
const { permissions } = useAuthenticated();
|
||||||
const { entitlements, organizationId } = useDashboard();
|
const { entitlements } = useDashboard();
|
||||||
|
|
||||||
const templatesQuery = useQuery(templates(organizationId, false));
|
const templatesQuery = useQuery(templates());
|
||||||
|
|
||||||
const filterProps = useWorkspacesFilter({
|
const filterProps = useWorkspacesFilter({
|
||||||
searchParamsResult,
|
searchParamsResult,
|
||||||
organizationId,
|
|
||||||
onFilterChange: () => pagination.goToPage(1),
|
onFilterChange: () => pagination.goToPage(1),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -142,13 +141,11 @@ export default WorkspacesPage;
|
|||||||
type UseWorkspacesFilterOptions = {
|
type UseWorkspacesFilterOptions = {
|
||||||
searchParamsResult: ReturnType<typeof useSearchParams>;
|
searchParamsResult: ReturnType<typeof useSearchParams>;
|
||||||
onFilterChange: () => void;
|
onFilterChange: () => void;
|
||||||
organizationId: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const useWorkspacesFilter = ({
|
const useWorkspacesFilter = ({
|
||||||
searchParamsResult,
|
searchParamsResult,
|
||||||
onFilterChange,
|
onFilterChange,
|
||||||
organizationId,
|
|
||||||
}: UseWorkspacesFilterOptions) => {
|
}: UseWorkspacesFilterOptions) => {
|
||||||
const filter = useFilter({
|
const filter = useFilter({
|
||||||
fallbackFilter: "owner:me",
|
fallbackFilter: "owner:me",
|
||||||
@ -166,7 +163,6 @@ const useWorkspacesFilter = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const templateMenu = useTemplateFilterMenu({
|
const templateMenu = useTemplateFilterMenu({
|
||||||
organizationId,
|
|
||||||
value: filter.values.template,
|
value: filter.values.template,
|
||||||
onChange: (option) =>
|
onChange: (option) =>
|
||||||
filter.update({ ...filter.values, template: option?.value }),
|
filter.update({ ...filter.values, template: option?.value }),
|
||||||
|
@ -16,18 +16,14 @@ import { getDisplayWorkspaceStatus } from "utils/workspace";
|
|||||||
export const useTemplateFilterMenu = ({
|
export const useTemplateFilterMenu = ({
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
organizationId,
|
}: Pick<UseFilterMenuOptions<SelectFilterOption>, "value" | "onChange">) => {
|
||||||
}: { organizationId: string } & Pick<
|
|
||||||
UseFilterMenuOptions<SelectFilterOption>,
|
|
||||||
"value" | "onChange"
|
|
||||||
>) => {
|
|
||||||
return useFilterMenu({
|
return useFilterMenu({
|
||||||
onChange,
|
onChange,
|
||||||
value,
|
value,
|
||||||
id: "template",
|
id: "template",
|
||||||
getSelectedOption: async () => {
|
getSelectedOption: async () => {
|
||||||
// Show all templates including deprecated
|
// Show all templates including deprecated
|
||||||
const templates = await API.getTemplates(organizationId);
|
const templates = await API.getTemplates();
|
||||||
const template = templates.find((template) => template.name === value);
|
const template = templates.find((template) => template.name === value);
|
||||||
if (template) {
|
if (template) {
|
||||||
return {
|
return {
|
||||||
@ -40,7 +36,7 @@ export const useTemplateFilterMenu = ({
|
|||||||
},
|
},
|
||||||
getOptions: async (query) => {
|
getOptions: async (query) => {
|
||||||
// Show all templates including deprecated
|
// Show all templates including deprecated
|
||||||
const templates = await API.getTemplates(organizationId);
|
const templates = await API.getTemplates();
|
||||||
const filteredTemplates = templates.filter(
|
const filteredTemplates = templates.filter(
|
||||||
(template) =>
|
(template) =>
|
||||||
template.name.toLowerCase().includes(query.toLowerCase()) ||
|
template.name.toLowerCase().includes(query.toLowerCase()) ||
|
||||||
|
@ -42,7 +42,7 @@ export const handlers = [
|
|||||||
|
|
||||||
// organizations
|
// organizations
|
||||||
http.get("/api/v2/organizations", () => {
|
http.get("/api/v2/organizations", () => {
|
||||||
return HttpResponse.json([M.MockDefaultOrganization, M.MockOrganization2]);
|
return HttpResponse.json([M.MockDefaultOrganization]);
|
||||||
}),
|
}),
|
||||||
http.get("/api/v2/organizations/:organizationId", () => {
|
http.get("/api/v2/organizations/:organizationId", () => {
|
||||||
return HttpResponse.json(M.MockOrganization);
|
return HttpResponse.json(M.MockOrganization);
|
||||||
|
@ -3,7 +3,11 @@ import type { FC } from "react";
|
|||||||
import { withDefaultFeatures } from "api/api";
|
import { withDefaultFeatures } from "api/api";
|
||||||
import type { Entitlements } from "api/typesGenerated";
|
import type { Entitlements } from "api/typesGenerated";
|
||||||
import { DashboardContext } from "modules/dashboard/DashboardProvider";
|
import { DashboardContext } from "modules/dashboard/DashboardProvider";
|
||||||
import { MockAppearanceConfig, MockEntitlements } from "./entities";
|
import {
|
||||||
|
MockAppearanceConfig,
|
||||||
|
MockDefaultOrganization,
|
||||||
|
MockEntitlements,
|
||||||
|
} from "./entities";
|
||||||
|
|
||||||
export const withDashboardProvider = (
|
export const withDashboardProvider = (
|
||||||
Story: FC,
|
Story: FC,
|
||||||
@ -26,10 +30,10 @@ export const withDashboardProvider = (
|
|||||||
return (
|
return (
|
||||||
<DashboardContext.Provider
|
<DashboardContext.Provider
|
||||||
value={{
|
value={{
|
||||||
organizationId: "",
|
|
||||||
entitlements,
|
entitlements,
|
||||||
experiments,
|
experiments,
|
||||||
appearance: MockAppearanceConfig,
|
appearance: MockAppearanceConfig,
|
||||||
|
organizations: [MockDefaultOrganization],
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Story />
|
<Story />
|
||||||
|
Reference in New Issue
Block a user