- {!isPrivateProject ? `You are not a member of this project yet.` : `You are not a member of this project.`}
-
-
-
-
- {!isPrivateProject
- ? `Click the button below to join it.`
- : `This is a private project. \n We can't tell you more about this project to protect confidentiality.`}
-
-
- {!isPrivateProject && (
-
- }
- loading={isJoiningProject}
- onClick={handleJoin}
- >
- {isJoiningProject ? "Taking you in" : "Click to join"}
-
-
- )}
-
- );
-}
diff --git a/apps/web/core/components/auth-screens/project/project-access-restriction.tsx b/apps/web/core/components/auth-screens/project/project-access-restriction.tsx
new file mode 100644
index 000000000..631afc5c4
--- /dev/null
+++ b/apps/web/core/components/auth-screens/project/project-access-restriction.tsx
@@ -0,0 +1,70 @@
+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 (
+
+
+
+ );
+
+ // Show no access screen if:
+ // - User lacks permission to access the private project (403 Forbidden)
+ if (errorStatusCode === 403) {
+ return (
+
+
+
+ );
+ }
+
+ // Show empty state screen if:
+ // - Project not found (404 Not Found)
+ // - Any other error status code
+ return (
+
+
);
+ }
return <>{children}>;
});
diff --git a/apps/web/core/services/project/project.service.ts b/apps/web/core/services/project/project.service.ts
index 266ffe95d..5915c7608 100644
--- a/apps/web/core/services/project/project.service.ts
+++ b/apps/web/core/services/project/project.service.ts
@@ -57,7 +57,7 @@ export class ProjectService extends APIService {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`)
.then((response) => response?.data)
.catch((error) => {
- throw error?.response?.data;
+ throw error?.response;
});
}
diff --git a/packages/i18n/src/locales/cs/empty-state.ts b/packages/i18n/src/locales/cs/empty-state.ts
index 4e552ea0b..452535d9d 100644
--- a/packages/i18n/src/locales/cs/empty-state.ts
+++ b/packages/i18n/src/locales/cs/empty-state.ts
@@ -24,6 +24,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Vypadá to, že nemáte přístup k tomuto projektu",
+ restricted_description: "Kontaktujte administrátora a požádejte o přístup, abyste zde mohli pokračovat.",
+ join_description: "Klikněte na tlačítko níže pro připojení k projektu.",
+ cta_primary: "Připojit se k projektu",
+ cta_loading: "Připojování k projektu",
+ },
+ invalid_project: {
+ title: "Projekt nebyl nalezen",
+ description: "Projekt, který hledáte, neexistuje.",
+ },
work_items: {
title: "Začněte s vaší první pracovní položkou.",
description:
diff --git a/packages/i18n/src/locales/de/empty-state.ts b/packages/i18n/src/locales/de/empty-state.ts
index f5b2fae25..55dfe5800 100644
--- a/packages/i18n/src/locales/de/empty-state.ts
+++ b/packages/i18n/src/locales/de/empty-state.ts
@@ -26,6 +26,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Es scheint, als hätten Sie keinen Zugriff auf dieses Projekt",
+ restricted_description: "Kontaktieren Sie den Administrator, um Zugriff anzufordern, damit Sie hier fortfahren können.",
+ join_description: "Klicken Sie unten auf die Schaltfläche, um beizutreten.",
+ cta_primary: "Projekt beitreten",
+ cta_loading: "Projekt wird beigetreten",
+ },
+ invalid_project: {
+ title: "Projekt nicht gefunden",
+ description: "Das gesuchte Projekt existiert nicht.",
+ },
work_items: {
title: "Beginnen Sie mit Ihrem ersten Arbeitselement.",
description:
diff --git a/packages/i18n/src/locales/en/empty-state.ts b/packages/i18n/src/locales/en/empty-state.ts
index 8ef996f4f..8f181883a 100644
--- a/packages/i18n/src/locales/en/empty-state.ts
+++ b/packages/i18n/src/locales/en/empty-state.ts
@@ -24,6 +24,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Seems like you don’t have access to this Project",
+ restricted_description: "Contact admin to request for access and you can continue here.",
+ join_description: "Click the button below to join it.",
+ cta_primary: "Join project",
+ cta_loading: "Joining project",
+ },
+ invalid_project: {
+ title: "Project not found",
+ description: "The project you are looking for does not exist.",
+ },
work_items: {
title: "Start with your first work item.",
description:
diff --git a/packages/i18n/src/locales/es/empty-state.ts b/packages/i18n/src/locales/es/empty-state.ts
index 0c062cdb4..6ef770152 100644
--- a/packages/i18n/src/locales/es/empty-state.ts
+++ b/packages/i18n/src/locales/es/empty-state.ts
@@ -26,6 +26,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Parece que no tienes acceso a este proyecto",
+ restricted_description: "Contacta con el administrador para solicitar acceso y podrás continuar aquí.",
+ join_description: "Haz clic en el botón de abajo para unirte.",
+ cta_primary: "Unirse al proyecto",
+ cta_loading: "Uniéndose al proyecto",
+ },
+ invalid_project: {
+ title: "Proyecto no encontrado",
+ description: "El proyecto que buscas no existe.",
+ },
work_items: {
title: "Comienza con tu primer elemento de trabajo.",
description:
diff --git a/packages/i18n/src/locales/fr/empty-state.ts b/packages/i18n/src/locales/fr/empty-state.ts
index 78c0202e1..3c7fc2816 100644
--- a/packages/i18n/src/locales/fr/empty-state.ts
+++ b/packages/i18n/src/locales/fr/empty-state.ts
@@ -27,6 +27,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Il semble que vous n’ayez pas accès à ce projet",
+ restricted_description: "Contactez l’administrateur pour demander l’accès afin de pouvoir continuer ici.",
+ join_description: "Cliquez sur le bouton ci-dessous pour rejoindre le projet.",
+ cta_primary: "Rejoindre le projet",
+ cta_loading: "Rejoindre le projet…",
+ },
+ invalid_project: {
+ title: "Projet non trouvé",
+ description: "Le projet que vous recherchez n’existe pas.",
+ },
work_items: {
title: "Commencez avec votre premier élément de travail.",
description:
diff --git a/packages/i18n/src/locales/id/empty-state.ts b/packages/i18n/src/locales/id/empty-state.ts
index 8224ec78e..11c900878 100644
--- a/packages/i18n/src/locales/id/empty-state.ts
+++ b/packages/i18n/src/locales/id/empty-state.ts
@@ -25,6 +25,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Sepertinya Anda tidak memiliki akses ke Proyek ini",
+ restricted_description: "Hubungi admin untuk meminta akses agar Anda dapat melanjutkan di sini.",
+ join_description: "Klik tombol di bawah ini untuk bergabung.",
+ cta_primary: "Bergabung dengan proyek",
+ cta_loading: "Sedang bergabung dengan proyek",
+ },
+ invalid_project: {
+ title: "Proyek tidak ditemukan",
+ description: "Proyek yang Anda cari tidak ada.",
+ },
work_items: {
title: "Mulai dengan item kerja pertama Anda.",
description:
diff --git a/packages/i18n/src/locales/it/empty-state.ts b/packages/i18n/src/locales/it/empty-state.ts
index 279241ebb..fa7a3ee84 100644
--- a/packages/i18n/src/locales/it/empty-state.ts
+++ b/packages/i18n/src/locales/it/empty-state.ts
@@ -27,6 +27,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Sembra che tu non abbia accesso a questo progetto",
+ restricted_description: "Contatta l'amministratore per richiedere l'accesso e potrai continuare qui.",
+ join_description: "Clicca sul pulsante qui sotto per unirti.",
+ cta_primary: "Unisciti al progetto",
+ cta_loading: "Unione al progetto in corso",
+ },
+ invalid_project: {
+ title: "Progetto non trovato",
+ description: "Il progetto che stai cercando non esiste.",
+ },
work_items: {
title: "Inizia con il tuo primo elemento di lavoro.",
description:
diff --git a/packages/i18n/src/locales/ja/empty-state.ts b/packages/i18n/src/locales/ja/empty-state.ts
index 6463c5ccf..0bf5ffbb2 100644
--- a/packages/i18n/src/locales/ja/empty-state.ts
+++ b/packages/i18n/src/locales/ja/empty-state.ts
@@ -24,6 +24,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "このプロジェクトへのアクセス権がないようです",
+ restricted_description: "管理者に連絡してアクセス権をリクエストすると、ここで作業を続けられます。",
+ join_description: "下のボタンをクリックして参加してください。",
+ cta_primary: "プロジェクトに参加",
+ cta_loading: "プロジェクトに参加中",
+ },
+ invalid_project: {
+ title: "プロジェクトが見つかりません",
+ description: "お探しのプロジェクトは存在しません。",
+ },
work_items: {
title: "最初の作業項目から始めましょう。",
description:
diff --git a/packages/i18n/src/locales/ko/empty-state.ts b/packages/i18n/src/locales/ko/empty-state.ts
index 093091f65..cb769a180 100644
--- a/packages/i18n/src/locales/ko/empty-state.ts
+++ b/packages/i18n/src/locales/ko/empty-state.ts
@@ -24,6 +24,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "이 프로젝트에 접근할 수 없는 것 같습니다",
+ restricted_description: "관리자에게 접근 권한을 요청하시면 여기서 계속 진행하실 수 있습니다.",
+ join_description: "아래 버튼을 클릭하여 프로젝트에 참여하세요.",
+ cta_primary: "프로젝트 참여",
+ cta_loading: "프로젝트 참여 중",
+ },
+ invalid_project: {
+ title: "프로젝트를 찾을 수 없습니다",
+ description: "찾으시는 프로젝트가 존재하지 않습니다.",
+ },
work_items: {
title: "첫 번째 작업 항목으로 시작하세요.",
description:
diff --git a/packages/i18n/src/locales/pl/empty-state.ts b/packages/i18n/src/locales/pl/empty-state.ts
index 30fc30a6a..7ab817673 100644
--- a/packages/i18n/src/locales/pl/empty-state.ts
+++ b/packages/i18n/src/locales/pl/empty-state.ts
@@ -24,6 +24,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Wygląda na to, że nie masz dostępu do tego projektu",
+ restricted_description: "Skontaktuj się z administratorem, aby poprosić o dostęp i móc kontynuować tutaj.",
+ join_description: "Kliknij przycisk poniżej, aby dołączyć.",
+ cta_primary: "Dołącz do projektu",
+ cta_loading: "Dołączanie do projektu",
+ },
+ invalid_project: {
+ title: "Projekt nie został znaleziony",
+ description: "Projekt, którego szukasz, nie istnieje.",
+ },
work_items: {
title: "Zacznij od swojego pierwszego elementu roboczego.",
description:
diff --git a/packages/i18n/src/locales/pt-BR/empty-state.ts b/packages/i18n/src/locales/pt-BR/empty-state.ts
index 8d92f4ff1..9ceb00fe5 100644
--- a/packages/i18n/src/locales/pt-BR/empty-state.ts
+++ b/packages/i18n/src/locales/pt-BR/empty-state.ts
@@ -26,6 +26,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Parece que você não tem acesso a este projeto",
+ restricted_description: "Entre em contato com o administrador para solicitar acesso e você poderá continuar aqui.",
+ join_description: "Clique no botão abaixo para participar.",
+ cta_primary: "Participar do projeto",
+ cta_loading: "Participando do projeto",
+ },
+ invalid_project: {
+ title: "Projeto não encontrado",
+ description: "O projeto que você está procurando não existe.",
+ },
work_items: {
title: "Comece com seu primeiro item de trabalho.",
description:
diff --git a/packages/i18n/src/locales/ro/empty-state.ts b/packages/i18n/src/locales/ro/empty-state.ts
index c123d82ab..7591096b1 100644
--- a/packages/i18n/src/locales/ro/empty-state.ts
+++ b/packages/i18n/src/locales/ro/empty-state.ts
@@ -25,6 +25,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Se pare că nu aveți acces la acest proiect",
+ restricted_description: "Contactați administratorul pentru a solicita accesul și veți putea continua aici.",
+ join_description: "Faceți clic pe butonul de mai jos pentru a vă alătura.",
+ cta_primary: "Alăturați-vă proiectului",
+ cta_loading: "Se alătură proiectului",
+ },
+ invalid_project: {
+ title: "Proiect negăsit",
+ description: "Proiectul pe care îl căutați nu există.",
+ },
work_items: {
title: "Începeți cu primul dvs. element de lucru.",
description:
diff --git a/packages/i18n/src/locales/ru/empty-state.ts b/packages/i18n/src/locales/ru/empty-state.ts
index eebe5d032..748ffb069 100644
--- a/packages/i18n/src/locales/ru/empty-state.ts
+++ b/packages/i18n/src/locales/ru/empty-state.ts
@@ -25,6 +25,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Похоже, у вас нет доступа к этому проекту",
+ restricted_description: "Свяжитесь с администратором, чтобы запросить доступ, и вы сможете продолжить здесь.",
+ join_description: "Нажмите кнопку ниже, чтобы присоединиться.",
+ cta_primary: "Присоединиться к проекту",
+ cta_loading: "Присоединение к проекту",
+ },
+ invalid_project: {
+ title: "Проект не найден",
+ description: "Проект, который вы ищете, не существует.",
+ },
work_items: {
title: "Начните с вашего первого рабочего элемента.",
description:
diff --git a/packages/i18n/src/locales/sk/empty-state.ts b/packages/i18n/src/locales/sk/empty-state.ts
index 29ccb63bd..b950fd701 100644
--- a/packages/i18n/src/locales/sk/empty-state.ts
+++ b/packages/i18n/src/locales/sk/empty-state.ts
@@ -24,6 +24,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Zdá sa, že nemáte prístup k tomuto projektu",
+ restricted_description: "Kontaktujte administrátora, aby ste požiadali o prístup, a potom tu môžete pokračovať.",
+ join_description: "Kliknite na tlačidlo nižšie, aby ste sa pripojili.",
+ cta_primary: "Pripojiť sa k projektu",
+ cta_loading: "Pripájanie k projektu",
+ },
+ invalid_project: {
+ title: "Projekt nebol nájdený",
+ description: "Projekt, ktorý hľadáte, neexistuje.",
+ },
work_items: {
title: "Začnite s vašou prvou pracovnou položkou.",
description:
diff --git a/packages/i18n/src/locales/tr-TR/empty-state.ts b/packages/i18n/src/locales/tr-TR/empty-state.ts
index e1f74039a..0f1a257ac 100644
--- a/packages/i18n/src/locales/tr-TR/empty-state.ts
+++ b/packages/i18n/src/locales/tr-TR/empty-state.ts
@@ -24,6 +24,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Görünüşe göre bu projeye erişiminiz yok",
+ restricted_description: "Erişim talep etmek için yöneticiyle iletişime geçin, sonra burada devam edebilirsiniz.",
+ join_description: "Katılmak için aşağıdaki butona tıklayın.",
+ cta_primary: "Projeye katıl",
+ cta_loading: "Projeye katılınıyor",
+ },
+ invalid_project: {
+ title: "Proje bulunamadı",
+ description: "Aradığınız proje mevcut değil.",
+ },
work_items: {
title: "İlk iş öğenizle başlayın.",
description:
diff --git a/packages/i18n/src/locales/ua/empty-state.ts b/packages/i18n/src/locales/ua/empty-state.ts
index 83dc3fb31..95ab8f790 100644
--- a/packages/i18n/src/locales/ua/empty-state.ts
+++ b/packages/i18n/src/locales/ua/empty-state.ts
@@ -25,6 +25,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Схоже, у вас немає доступу до цього проєкту",
+ restricted_description: "Зверніться до адміністратора, щоб запросити доступ, і ви зможете продовжити тут.",
+ join_description: "Натисніть кнопку нижче, щоб приєднатися.",
+ cta_primary: "Приєднатися до проєкту",
+ cta_loading: "Приєднання до проєкту",
+ },
+ invalid_project: {
+ title: "Проєкт не знайдено",
+ description: "Проєкт, який ви шукаєте, не існує.",
+ },
work_items: {
title: "Почніть з вашого першого робочого елемента.",
description:
diff --git a/packages/i18n/src/locales/vi-VN/empty-state.ts b/packages/i18n/src/locales/vi-VN/empty-state.ts
index 367b2f4c9..dbee0d4c1 100644
--- a/packages/i18n/src/locales/vi-VN/empty-state.ts
+++ b/packages/i18n/src/locales/vi-VN/empty-state.ts
@@ -25,6 +25,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "Có vẻ như bạn không có quyền truy cập vào Dự án này",
+ restricted_description: "Liên hệ với quản trị viên để yêu cầu quyền truy cập và bạn có thể tiếp tục tại đây.",
+ join_description: "Nhấn nút bên dưới để tham gia.",
+ cta_primary: "Tham gia dự án",
+ cta_loading: "Đang tham gia dự án",
+ },
+ invalid_project: {
+ title: "Không tìm thấy dự án",
+ description: "Dự án bạn đang tìm kiếm không tồn tại.",
+ },
work_items: {
title: "Bắt đầu với mục công việc đầu tiên của bạn.",
description:
diff --git a/packages/i18n/src/locales/zh-CN/empty-state.ts b/packages/i18n/src/locales/zh-CN/empty-state.ts
index 67ffd5dde..c2028e2e2 100644
--- a/packages/i18n/src/locales/zh-CN/empty-state.ts
+++ b/packages/i18n/src/locales/zh-CN/empty-state.ts
@@ -24,6 +24,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "您似乎无权访问该项目",
+ restricted_description: "请联系管理员申请访问权限,通过后您可以在此继续。",
+ join_description: "点击下方按钮加入该项目。",
+ cta_primary: "加入项目",
+ cta_loading: "正在加入项目",
+ },
+ invalid_project: {
+ title: "未找到项目",
+ description: "您查找的项目不存在。",
+ },
work_items: {
title: "从您的第一个工作项开始。",
description: "工作项是项目的构建块 — 分配负责人、设置优先级并轻松跟踪进度。",
diff --git a/packages/i18n/src/locales/zh-TW/empty-state.ts b/packages/i18n/src/locales/zh-TW/empty-state.ts
index 77e201bd1..8644cadf2 100644
--- a/packages/i18n/src/locales/zh-TW/empty-state.ts
+++ b/packages/i18n/src/locales/zh-TW/empty-state.ts
@@ -24,6 +24,17 @@ export default {
},
},
project_empty_state: {
+ no_access: {
+ title: "您似乎無權存取此專案",
+ restricted_description: "請聯絡管理員以申請存取權,核准後即可在此繼續。",
+ join_description: "點擊下方按鈕加入專案。",
+ cta_primary: "加入專案",
+ cta_loading: "正在加入專案",
+ },
+ invalid_project: {
+ title: "找不到專案",
+ description: "您所查找的專案不存在。",
+ },
work_items: {
title: "從您的第一個工作項開始。",
description: "工作項是專案的建構模組 — 指派負責人、設定優先順序並輕鬆追蹤進度。",