snapshot of https://github.com/makeplane/plane.git @ d868349a55de79979eb8b98701bf1702c67ad634 (2026-09-15)
Some checks failed
CodeQL / Analyze (javascript) (push) Failing after 16s
CodeQL / Analyze (python) (push) Failing after 3s
i18n sync check / check:sync (push) Failing after 3s
React Doctor / react-doctor (push) Failing after 16s
Branch Build CE / Build-Push Admin Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Admin Manifest (push) Has been cancelled
Branch Build CE / Build-Push Web Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Web Manifest (push) Has been cancelled
Branch Build CE / Build-Push Space Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Proxy Manifest (push) Has been cancelled
Branch Build CE / Merge Space Manifest (push) Has been cancelled
Branch Build CE / Prepare AIO Assets (push) Has been cancelled
Branch Build CE / Build Setup (push) Has been cancelled
Branch Build CE / Build-Push Live Collaboration Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge Live Collaboration Manifest (push) Has been cancelled
Branch Build CE / Build-Push API Server Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge API Server Manifest (push) Has been cancelled
Branch Build CE / Build-Push Proxy Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Build-Push AIO Docker Image (${{ matrix.arch }}) (push) Has been cancelled
Branch Build CE / Merge AIO Manifest (push) Has been cancelled
Branch Build CE / Upload Build Assets (push) Has been cancelled
Branch Build CE / Build Release (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-15 15:14:58 +05:00
commit 23059a1de3
5252 changed files with 573834 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React from "react";
import { AuthRoot } from "@/components/account/auth-forms/auth-root";
import type { EAuthModes } from "@/helpers/authentication.helper";
import { AuthFooter } from "./footer";
import { AuthHeader } from "./header";
type AuthBaseProps = {
authType: EAuthModes;
};
export function AuthBase({ authType }: AuthBaseProps) {
return (
<div className="relative z-10 flex h-screen w-screen flex-col items-center overflow-hidden overflow-y-auto px-8 pt-6 pb-10">
<AuthHeader type={authType} />
<AuthRoot authMode={authType} />
<AuthFooter />
</div>
);
}

View File

@@ -0,0 +1,45 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React from "react";
import { AccentureLogo, DolbyLogo, SonyLogo, ZerodhaLogo } from "@plane/propel/icons";
const BRAND_LOGOS: {
id: string;
icon: React.ReactNode;
}[] = [
{
id: "zerodha",
icon: <ZerodhaLogo className="h-7 w-24 text-[#387ED1]" />,
},
{
id: "sony",
icon: <SonyLogo className="h-7 w-16 dark:text-on-color" />,
},
{
id: "dolby",
icon: <DolbyLogo className="h-7 w-16 dark:text-on-color" />,
},
{
id: "accenture",
icon: <AccentureLogo className="h-7 w-24 dark:text-on-color" />,
},
];
export function AuthFooter() {
return (
<div className="flex flex-col items-center gap-6">
<span className="text-13 whitespace-nowrap text-tertiary">Join 10,000+ teams building with Plane</span>
<div className="flex w-full flex-wrap items-center justify-center gap-x-10 gap-y-4">
{BRAND_LOGOS.map((brand) => (
<div className="flex h-7 flex-1 items-center justify-center" key={brand.id}>
{brand.icon}
</div>
))}
</div>
</div>
);
}

View File

@@ -0,0 +1,80 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React from "react";
import { observer } from "mobx-react";
import Link from "next/link";
import { useTranslation } from "@plane/i18n";
import { PlaneLockup } from "@plane/propel/icons";
import { PageHead } from "@/components/core/page-title";
import { EAuthModes } from "@/helpers/authentication.helper";
import { useInstance } from "@/hooks/store/use-instance";
const authContentMap = {
[EAuthModes.SIGN_IN]: {
pageTitle: "Sign up",
text: "auth.common.new_to_plane",
linkText: "Sign up",
linkHref: "/sign-up",
},
[EAuthModes.SIGN_UP]: {
pageTitle: "Sign in",
text: "auth.common.already_have_an_account",
linkText: "Sign in",
linkHref: "/sign-in",
},
};
type AuthHeaderProps = {
type: EAuthModes;
};
export const AuthHeader = observer(function AuthHeader({ type }: AuthHeaderProps) {
const { t } = useTranslation();
// store
const { config } = useInstance();
// derived values
const enableSignUpConfig = config?.enable_signup ?? false;
return (
<AuthHeaderBase
pageTitle={t(authContentMap[type].pageTitle)}
additionalAction={
enableSignUpConfig && (
<div className="flex flex-col items-end text-center text-13 font-medium text-tertiary sm:flex-row sm:items-center sm:gap-2">
<span className="text-body-sm-regular text-tertiary">{t(authContentMap[type].text)}</span>
<Link
href={authContentMap[type].linkHref}
className="text-body-sm-semibold text-accent-primary hover:underline"
>
{t(authContentMap[type].linkText)}
</Link>
</div>
)
}
/>
);
});
type TAuthHeaderBase = {
pageTitle: string;
additionalAction?: React.ReactNode;
};
export function AuthHeaderBase(props: TAuthHeaderBase) {
const { pageTitle, additionalAction } = props;
return (
<>
<PageHead title={pageTitle + " - Plane"} />
<div className="sticky top-0 flex w-full flex-shrink-0 items-center justify-between gap-6">
<Link href="/">
<PlaneLockup height={20} width={95} className="text-primary" />
</Link>
{additionalAction}
</div>
</>
);
}

View File

@@ -0,0 +1,42 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import React from "react";
import { observer } from "mobx-react";
// assets
import { cn } from "@plane/utils";
import ProjectNotAuthorizedImg from "@/app/assets/auth/project-not-authorized.svg?url";
import Unauthorized from "@/app/assets/auth/unauthorized.svg?url";
import WorkspaceNotAuthorizedImg from "@/app/assets/auth/workspace-not-authorized.svg?url";
// layouts
import DefaultLayout from "@/layouts/default-layout";
type Props = {
actionButton?: React.ReactNode;
section?: "settings" | "general";
isProjectView?: boolean;
className?: string;
};
export const NotAuthorizedView = observer(function NotAuthorizedView(props: Props) {
const { actionButton, section = "general", isProjectView = false, className } = props;
// assets
const settingAsset = isProjectView ? ProjectNotAuthorizedImg : WorkspaceNotAuthorizedImg;
const asset = section === "settings" ? settingAsset : Unauthorized;
return (
<DefaultLayout className={cn("bg-surface-1", className)}>
<div className="flex h-full w-full flex-col items-center justify-center gap-y-5 text-center">
<div className="h-44 w-72">
<img src={asset} className="h-[176px] w-[288px] object-contain" alt="ProjectSettingImg" />
</div>
<h1 className="text-18 font-medium text-primary">Oops! You are not authorized to view this page</h1>
{actionButton}
</div>
</DefaultLayout>
);
});

View File

@@ -0,0 +1,76 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import { observer } from "mobx-react";
// plane imports
import { useTranslation } from "@plane/i18n";
import { EmptyStateDetailed } from "@plane/propel/empty-state";
type TProps = {
isWorkspaceAdmin: boolean;
handleJoinProject: () => void;
isJoinButtonDisabled: boolean;
errorStatusCode: number | undefined;
};
export const ProjectAccessRestriction = observer(function ProjectAccessRestriction(props: TProps) {
const { isWorkspaceAdmin, handleJoinProject, isJoinButtonDisabled, errorStatusCode } = props;
// plane hooks
const { t } = useTranslation();
// Show join project screen if:
// - User lacks project membership (409 Conflict)
// - User lacks permission to access the private project (403 Forbidden) but is a workspace admin (can join any project)
if (errorStatusCode === 409 || (errorStatusCode === 403 && isWorkspaceAdmin))
return (
<div className="grid h-full w-full place-items-center bg-surface-1">
<EmptyStateDetailed
title={t("project_empty_state.no_access.title")}
description={t("project_empty_state.no_access.join_description")}
assetKey="no-access"
assetClassName="size-40"
actions={[
{
label: isJoinButtonDisabled
? t("project_empty_state.no_access.cta_loading")
: t("project_empty_state.no_access.cta_primary"),
onClick: handleJoinProject,
disabled: isJoinButtonDisabled,
},
]}
/>
</div>
);
// Show no access screen if:
// - User lacks permission to access the private project (403 Forbidden)
if (errorStatusCode === 403) {
return (
<div className="grid h-full w-full place-items-center bg-surface-1">
<EmptyStateDetailed
title={t("project_empty_state.no_access.title")}
description={t("project_empty_state.no_access.restricted_description")}
assetKey="no-access"
assetClassName="size-40"
/>
</div>
);
}
// Show empty state screen if:
// - Project not found (404 Not Found)
// - Any other error status code
return (
<div className="grid h-full w-full place-items-center bg-surface-1">
<EmptyStateDetailed
title={t("project_empty_state.invalid_project.title")}
description={t("project_empty_state.invalid_project.description")}
assetKey="project"
assetClassName="size-40"
/>
</div>
);
});

View File

@@ -0,0 +1,41 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import Link from "next/link";
// ui
import { Button } from "@plane/propel/button";
// layouts
import DefaultLayout from "@/layouts/default-layout";
export function NotAWorkspaceMember() {
return (
<DefaultLayout>
<div className="grid h-full place-items-center p-4">
<div className="space-y-8 text-center">
<div className="space-y-2">
<h3 className="text-16 font-semibold">Not Authorized!</h3>
<p className="mx-auto w-1/2 text-13 text-secondary">
You{"'"}re not a member of this workspace. Please contact the workspace admin to get an invitation or
check your pending invitations.
</p>
</div>
<div className="flex items-center justify-center gap-2">
<Link href="/invitations">
<span>
<Button variant="secondary">Check pending invites</Button>
</span>
</Link>
<Link href="/create-workspace">
<span>
<Button variant="primary">Create new workspace</Button>
</span>
</Link>
</div>
</div>
</div>
</DefaultLayout>
);
}