159 lines
6.7 KiB
TypeScript
159 lines
6.7 KiB
TypeScript
/**
|
|
* Copyright (c) 2023-present Plane Software, Inc. and contributors
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
* See the LICENSE file for details.
|
|
*/
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { observer } from "mobx-react";
|
|
// plane imports
|
|
import { useTranslation } from "@plane/i18n";
|
|
import { Button, getButtonStyling } from "@plane/propel/button";
|
|
import type { IWorkspace } from "@plane/types";
|
|
// assets
|
|
import WorkspaceCreationDisabled from "@/app/assets/workspace/workspace-creation-disabled.png?url";
|
|
import { AuthHeaderBase } from "@/components/auth-screens/header";
|
|
// components
|
|
import { CreateWorkspaceForm } from "@/components/workspace/create-workspace-form";
|
|
// hooks
|
|
import { useUser, useUserProfile } from "@/hooks/store/user";
|
|
import { useInstance } from "@/hooks/store/use-instance";
|
|
import { useAppRouter } from "@/hooks/use-app-router";
|
|
// wrappers
|
|
import { AuthenticationWrapper } from "@/lib/wrappers/authentication-wrapper";
|
|
import { WorkspaceService, type NodeDCWorkspacePolicy } from "@/services/workspace.service";
|
|
|
|
const workspaceService = new WorkspaceService();
|
|
|
|
const CreateWorkspacePage = observer(function CreateWorkspacePage() {
|
|
const { t } = useTranslation();
|
|
// router
|
|
const router = useAppRouter();
|
|
// store hooks
|
|
const { config } = useInstance();
|
|
const { data: currentUser } = useUser();
|
|
const { updateUserProfile } = useUserProfile();
|
|
// states
|
|
const [defaultValues, setDefaultValues] = useState<Pick<IWorkspace, "name" | "slug" | "organization_size">>({
|
|
name: "",
|
|
slug: "",
|
|
organization_size: "",
|
|
});
|
|
const [workspacePolicy, setWorkspacePolicy] = useState<NodeDCWorkspacePolicy | null>(null);
|
|
const [workspacePolicyLoading, setWorkspacePolicyLoading] = useState(true);
|
|
// derived values
|
|
const isWorkspaceCreationDisabled = config?.is_workspace_creation_disabled ?? false;
|
|
const isWorkspaceCreationDeniedByNodeDC = Boolean(workspacePolicy?.enabled && !workspacePolicy.can_create_workspace);
|
|
const shouldBlockWorkspaceCreation = isWorkspaceCreationDisabled || isWorkspaceCreationDeniedByNodeDC;
|
|
|
|
useEffect(() => {
|
|
let mounted = true;
|
|
|
|
workspaceService
|
|
.getNodeDCWorkspacePolicy()
|
|
.then((policy) => {
|
|
if (mounted) setWorkspacePolicy(policy);
|
|
})
|
|
.catch(() => {
|
|
if (mounted) {
|
|
setWorkspacePolicy({
|
|
enabled: false,
|
|
can_create_workspace: true,
|
|
mode: "unavailable",
|
|
managed_by: "tasker",
|
|
default_managed_by: "tasker",
|
|
invite_approval: "tasker",
|
|
default_invite_approval: "tasker",
|
|
workspaces: [],
|
|
reason: "NODE.DC workspace policy is unavailable.",
|
|
});
|
|
}
|
|
})
|
|
.finally(() => {
|
|
if (mounted) setWorkspacePolicyLoading(false);
|
|
});
|
|
|
|
return () => {
|
|
mounted = false;
|
|
};
|
|
}, []);
|
|
|
|
// methods
|
|
const getMailtoHref = () => {
|
|
const subject = t("workspace_creation.request_email.subject");
|
|
const body = t("workspace_creation.request_email.body", {
|
|
firstName: currentUser?.first_name || "",
|
|
lastName: currentUser?.last_name || "",
|
|
email: currentUser?.email || "",
|
|
});
|
|
|
|
return `mailto:?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
|
};
|
|
|
|
const onSubmit = async (workspace: IWorkspace) => {
|
|
await updateUserProfile({ last_workspace_id: workspace.id }).then(() => router.push(`/${workspace.slug}`));
|
|
};
|
|
|
|
return (
|
|
<AuthenticationWrapper>
|
|
<div className="relative z-10 flex min-h-screen w-screen flex-col overflow-hidden overflow-y-auto bg-canvas px-8 pt-10 pb-12">
|
|
<AuthHeaderBase pageTitle={t("workspace_creation.heading")} />
|
|
<main className="grid flex-1 place-items-center py-8">
|
|
{workspacePolicyLoading ? (
|
|
<section className="nodedc-auth-shell flex flex-col items-start justify-center gap-4">
|
|
<div className="space-y-3">
|
|
<h1 className="m-0 text-30 font-semibold leading-tight text-primary">Работайте во всех измерениях.</h1>
|
|
<p className="m-0 text-28 font-semibold leading-tight text-secondary">Проверяем доступ к workspace.</p>
|
|
</div>
|
|
<p className="m-0 text-14 leading-6 text-secondary">
|
|
Сверяем платформенную policy NODE.DC перед созданием рабочего пространства.
|
|
</p>
|
|
</section>
|
|
) : shouldBlockWorkspaceCreation ? (
|
|
<section className="nodedc-auth-shell flex flex-col items-center justify-center gap-4 text-center">
|
|
<img
|
|
src={WorkspaceCreationDisabled}
|
|
className="max-h-56 w-full object-contain"
|
|
alt="Workspace creation disabled"
|
|
/>
|
|
<h1 className="m-0 text-24 font-semibold text-primary">
|
|
{isWorkspaceCreationDeniedByNodeDC
|
|
? "Workspace создаёт администратор."
|
|
: t("workspace_creation.errors.creation_disabled.title")}
|
|
</h1>
|
|
<p className="m-0 text-14 leading-6 text-secondary">
|
|
{isWorkspaceCreationDeniedByNodeDC
|
|
? workspacePolicy?.reason || "Дождитесь назначения в рабочее пространство администратором NODE.DC."
|
|
: t("workspace_creation.errors.creation_disabled.description")}
|
|
</p>
|
|
<div className="mt-6 flex w-full flex-col gap-3">
|
|
<Button variant="primary" className="nodedc-auth-primary-button" onClick={() => router.back()}>
|
|
{t("common.go_back")}
|
|
</Button>
|
|
<a href={getMailtoHref()} className={getButtonStyling("secondary", "base") + " nodedc-auth-secondary-button"}>
|
|
{t("workspace_creation.errors.creation_disabled.request_button")}
|
|
</a>
|
|
</div>
|
|
</section>
|
|
) : (
|
|
<section className="nodedc-auth-shell nodedc-create-workspace-card space-y-7">
|
|
<div className="space-y-3">
|
|
<h1 className="m-0 text-30 font-semibold leading-tight text-primary">Работайте во всех измерениях.</h1>
|
|
<p className="m-0 text-28 font-semibold leading-tight text-secondary">Создайте рабочее пространство.</p>
|
|
</div>
|
|
<CreateWorkspaceForm
|
|
variant="nodedc-auth"
|
|
onSubmit={onSubmit}
|
|
defaultValues={defaultValues}
|
|
setDefaultValues={setDefaultValues}
|
|
/>
|
|
</section>
|
|
)}
|
|
</main>
|
|
</div>
|
|
</AuthenticationWrapper>
|
|
);
|
|
});
|
|
|
|
export default CreateWorkspacePage;
|