mirror of
https://github.com/makeplane/plane
synced 2025-08-07 19:59:33 +00:00
Compare commits
5 Commits
chore-refa
...
feat-works
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e4ecf0c6e | ||
|
|
dd24b95eea | ||
|
|
bc17897ff3 | ||
|
|
84e2fe7d06 | ||
|
|
62a397a4b4 |
@@ -500,6 +500,13 @@
|
||||
"export": "Exportovat",
|
||||
"member": "{count, plural, one{# člen} few{# členové} other{# členů}}",
|
||||
"new_password_must_be_different_from_old_password": "Nové heslo musí být odlišné od starého hesla",
|
||||
"choose_workspace_for_integration": "Vyberte pracovní prostor pro připojení této aplikace",
|
||||
"integrations_description": "Aplikace, které pracují s Plane, musí být připojeny k pracovnímu prostoru, kde jste správce.",
|
||||
"create_a_new_workspace": "Vytvořit nový pracovní prostor",
|
||||
"no_workspaces_to_connect": "Žádné pracovní prostory k připojení",
|
||||
"no_workspaces_to_connect_description": "Musíte vytvořit pracovní prostor, abyste mohli připojit integraci a šablony",
|
||||
"learn_more_about_workspaces": "Zjistit více o pracovních prostorech",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Vytvořeno dne",
|
||||
|
||||
@@ -500,6 +500,13 @@
|
||||
"export": "Exportieren",
|
||||
"member": "{count, plural, one{# Mitglied} few{# Mitglieder} other{# Mitglieder}}",
|
||||
"new_password_must_be_different_from_old_password": "Das neue Passwort muss von dem alten Passwort abweichen",
|
||||
"choose_workspace_for_integration": "Wählen Sie einen Arbeitsbereich aus, um diese App zu verbinden",
|
||||
"integrations_description": "Apps, die mit Plane arbeiten, müssen einen Arbeitsbereich verbinden, in dem Sie ein Administrator sind.",
|
||||
"create_a_new_workspace": "Neuen Arbeitsbereich erstellen",
|
||||
"learn_more_about_workspaces": "Mehr über Arbeitsbereiche erfahren",
|
||||
"no_workspaces_to_connect": "Keine Arbeitsbereiche zum Verbinden",
|
||||
"no_workspaces_to_connect_description": "Sie müssen einen Arbeitsbereich erstellen, um Integrationen und Vorlagen zu verbinden",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Erstellt am",
|
||||
|
||||
@@ -334,6 +334,13 @@
|
||||
"new_password_must_be_different_from_old_password": "New password must be different from old password",
|
||||
"edited": "edited",
|
||||
"bot": "Bot",
|
||||
"choose_workspace_for_integration": "Choose a workspace to connect this app to",
|
||||
"integrations_description": "Apps that work with Plane must connect to a workspace where you are an admin.",
|
||||
"create_a_new_workspace": "Create a new workspace",
|
||||
"learn_more_about_workspaces": "Learn more about workspaces",
|
||||
"no_workspaces_to_connect": "No workspaces to connect",
|
||||
"no_workspaces_to_connect_description": "You will need to create a workspace to be able to connect integrations and templates",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Created at",
|
||||
|
||||
@@ -504,6 +504,13 @@
|
||||
"new_password_must_be_different_from_old_password": "La nueva contraseña debe ser diferente a la contraseña anterior",
|
||||
"edited": "Modificado",
|
||||
"bot": "Bot",
|
||||
"choose_workspace_for_integration": "Elige un espacio de trabajo para conectar esta app",
|
||||
"integrations_description": "Las apps que funcionan con Plane deben conectarse a un espacio de trabajo donde eres administrador.",
|
||||
"create_a_new_workspace": "Crear un nuevo espacio de trabajo",
|
||||
"learn_more_about_workspaces": "Aprende más sobre espacios de trabajo",
|
||||
"no_workspaces_to_connect": "No hay espacios de trabajo para conectar",
|
||||
"no_workspaces_to_connect_description": "Necesitarás crear un espacio de trabajo para poder conectar integraciones y plantillas",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Creado el",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "Le nouveau mot de passe doit être différent du mot de passe précédent",
|
||||
"edited": "Modifié",
|
||||
"bot": "Bot",
|
||||
"choose_workspace_for_integration": "Choisissez un espace de travail pour connecter cette application",
|
||||
"integrations_description": "Les applications qui fonctionnent avec Plane doivent se connecter à un espace de travail où vous êtes administrateur.",
|
||||
"create_a_new_workspace": "Créer un nouvel espace de travail",
|
||||
"learn_more_about_workspaces": "En savoir plus sur les espaces de travail",
|
||||
"no_workspaces_to_connect": "Aucun espace de travail à connecter",
|
||||
"no_workspaces_to_connect_description": "Vous devez créer un espace de travail pour pouvoir connecter des intégrations et des modèles",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Créé le",
|
||||
|
||||
@@ -500,6 +500,13 @@
|
||||
"export": "Ekspor",
|
||||
"member": "{count, plural, one{# anggota} other{# anggota}}",
|
||||
"new_password_must_be_different_from_old_password": "Kata sandi baru harus berbeda dari kata sandi lama",
|
||||
"choose_workspace_for_integration": "Pilih ruang kerja untuk menghubungkan aplikasi ini",
|
||||
"integrations_description": "Aplikasi yang bekerja dengan Plane harus menghubungkan ke ruang kerja di mana Anda adalah admin.",
|
||||
"create_a_new_workspace": "Buat ruang kerja baru",
|
||||
"learn_more_about_workspaces": "Pelajari lebih lanjut tentang ruang kerja",
|
||||
"no_workspaces_to_connect": "Tidak ada ruang kerja untuk menghubungkan",
|
||||
"no_workspaces_to_connect_description": "Anda perlu membuat ruang kerja untuk dapat menghubungkan integrasi dan template",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Dibuat pada",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "La nuova password deve essere diversa dalla password precedente",
|
||||
"edited": "Modificato",
|
||||
"bot": "Bot",
|
||||
"choose_workspace_for_integration": "Scegli uno spazio di lavoro per connettere questa app",
|
||||
"integrations_description": "Le app che funzionano con Plane devono connettersi a uno spazio di lavoro dove sei amministratore.",
|
||||
"create_a_new_workspace": "Crea uno spazio di lavoro nuovo",
|
||||
"learn_more_about_workspaces": "Scopri di più sui tuoi spazi di lavoro",
|
||||
"no_workspaces_to_connect": "Nessuno spazio di lavoro per connettere",
|
||||
"no_workspaces_to_connect_description": "Devi creare uno spazio di lavoro per poter connettere le integrazioni e i modelli",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Creato il",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "新しいパスワードは古いパスワードと異なる必要があります",
|
||||
"edited": "編集済み",
|
||||
"bot": "ボット",
|
||||
"choose_workspace_for_integration": "このアプリケーションに接続するワークスペースを選択してください",
|
||||
"integrations_description": "Planeのアプリケーションは、管理者であるワークスペースに接続する必要があります。",
|
||||
"create_a_new_workspace": "新しいワークスペースを作成",
|
||||
"learn_more_about_workspaces": "ワークスペースについて詳しくはこちら",
|
||||
"no_workspaces_to_connect": "接続するワークスペースがありません",
|
||||
"no_workspaces_to_connect_description": "接続するワークスペースを作成する必要があります",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "作成日時",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "새 비밀번호는 이전 비밀번호와 다르게 설정해야 합니다",
|
||||
"edited": "수정됨",
|
||||
"bot": "봇",
|
||||
"choose_workspace_for_integration": "이 앱에 연결할 작업 공간을 선택하세요",
|
||||
"integrations_description": "Plane의 앱은 관리자인 작업 공간에 연결해야 합니다.",
|
||||
"create_a_new_workspace": "새 작업 공간 만들기",
|
||||
"learn_more_about_workspaces": "작업 공간에 대해 자세히 알아보기",
|
||||
"no_workspaces_to_connect": "연결할 작업 공간이 없습니다",
|
||||
"no_workspaces_to_connect_description": "연결할 작업 공간을 만들어야 합니다",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "생성일",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "Nowe hasło musi być innym niż stare hasło",
|
||||
"edited": "Edytowano",
|
||||
"bot": "Bot",
|
||||
"choose_workspace_for_integration": "Wybierz przestrzeń roboczą do połączenia tej aplikacji",
|
||||
"integrations_description": "Aplikacje, które działają z Plane, muszą być połączone z przestrzenią roboczą, w której jesteś administratorem.",
|
||||
"create_a_new_workspace": "Utwórz nową przestrzeń roboczą",
|
||||
"learn_more_about_workspaces": "Dowiedz się więcej o przestrzeniach roboczych",
|
||||
"no_workspaces_to_connect": "Brak przestrzeni roboczych do połączenia",
|
||||
"no_workspaces_to_connect_description": "Musisz utworzyć przestrzeń roboczą, aby móc połączyć integracje i szablony",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Utworzono dnia",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "Nova senha deve ser diferente da senha antiga",
|
||||
"edited": "editado",
|
||||
"bot": "robô",
|
||||
"choose_workspace_for_integration": "Escolha um espaço de trabalho para conectar esta aplicação",
|
||||
"integrations_description": "Aplicações que funcionam com Plane devem se conectar a um espaço de trabalho onde você é administrador.",
|
||||
"create_a_new_workspace": "Criar um novo espaço de trabalho",
|
||||
"no_workspaces_to_connect": "Nenhum espaço de trabalho para conectar",
|
||||
"no_workspaces_to_connect_description": "Você precisa criar um espaço de trabalho para poder conectar integrações e templates",
|
||||
"learn_more_about_workspaces": "Saiba mais sobre espaços de trabalho",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Criado em",
|
||||
|
||||
@@ -500,6 +500,13 @@
|
||||
"export": "Exportă",
|
||||
"member": "{count, plural, one{# membru} other{# membri}}",
|
||||
"new_password_must_be_different_from_old_password": "Parola nouă trebuie să fie diferită de parola veche",
|
||||
"choose_workspace_for_integration": "Alegeți un spațiu de lucru pentru a conecta această aplicație",
|
||||
"integrations_description": "Aplicațiile care funcționează cu Plane trebuie să se conecteze la un spațiu de lucru unde sunteți administrator.",
|
||||
"create_a_new_workspace": "Creați un nou spațiu de lucru",
|
||||
"no_workspaces_to_connect": "Nu există spații de lucru pentru a conecta",
|
||||
"no_workspaces_to_connect_description": "Trebuie să creați un spațiu de lucru pentru a putea conecta integrări și modele",
|
||||
"learn_more_about_workspaces": "Află mai multe despre spațiile de lucru",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Creat la",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "Новое пароль должен отличаться от старого пароля",
|
||||
"edited": "Редактировано",
|
||||
"bot": "Бот",
|
||||
"choose_workspace_for_integration": "Выберите рабочее пространство для подключения этого приложения",
|
||||
"integrations_description": "Приложения, которые работают с Plane, должны быть подключены к рабочему пространству, где вы являетесь администратором.",
|
||||
"create_a_new_workspace": "Создать новое рабочее пространство",
|
||||
"learn_more_about_workspaces": "Узнать больше о рабочих пространствах",
|
||||
"no_workspaces_to_connect": "Нет рабочих пространств для подключения",
|
||||
"no_workspaces_to_connect_description": "Вы должны создать рабочее пространство, чтобы подключить интеграции и шаблоны",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Дата создания",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "Nové heslo musí byť odlišné od starého hesla",
|
||||
"edited": "Upravené",
|
||||
"bot": "Bot",
|
||||
"choose_workspace_for_integration": "Vyberte pracovný priestor pre pripojenie tejto aplikácie",
|
||||
"integrations_description": "Aplikácie, ktoré fungujú s Plane, musia byť pripojené k pracovnom priestoru, kde ste správca.",
|
||||
"create_a_new_workspace": "Vytvoriť nový pracovný priestor",
|
||||
"learn_more_about_workspaces": "Zjistit více o pracovních prostorech",
|
||||
"no_workspaces_to_connect": "Žádné pracovní prostory k připojení",
|
||||
"no_workspaces_to_connect_description": "Musíte vytvořit pracovní prostor, abyste mohli připojit integraci a šablony",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Vytvorené dňa",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "Yeni şifre eski şifreden farklı olmalı",
|
||||
"edited": "düzenlendi",
|
||||
"bot": "Bot",
|
||||
"choose_workspace_for_integration": "Bu uygulamayı bağlamak için bir çalışma alanı seçin",
|
||||
"integrations_description": "Plane ile çalışan uygulamalar, yönetici olduğunuz bir çalışma alanına bağlanmalıdır.",
|
||||
"create_a_new_workspace": "Yeni bir çalışma alanı oluştur",
|
||||
"learn_more_about_workspaces": "Çalışma alanları hakkında daha fazla bilgi edinin",
|
||||
"no_workspaces_to_connect": "Bağlamak için çalışma alanı yok",
|
||||
"no_workspaces_to_connect_description": "Bir çalışma alanı oluşturmak için lütfen bu sayfaya dönün",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Oluşturulma tarihi",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "Новий пароль повинен бути відмінним від старого пароля",
|
||||
"edited": "Редагувано",
|
||||
"bot": "Бот",
|
||||
"choose_workspace_for_integration": "Виберіть робочий простір для підключення цієї програми",
|
||||
"integrations_description": "Програми, які працюють з Plane, повинні бути підключені до робочого простору, де ви є адміністратором.",
|
||||
"create_a_new_workspace": "Створити новий робочий простір",
|
||||
"learn_more_about_workspaces": "Дізнатися більше про робочі простори",
|
||||
"no_workspaces_to_connect": "Немає робочих просторів для підключення",
|
||||
"no_workspaces_to_connect_description": "Ви повинні створити робочий простір, щоб підключити інтеграції та шаблони",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Створено",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "Mật khẩu mới phải khác mật khẩu cũ",
|
||||
"edited": "đã chỉnh sửa",
|
||||
"bot": "bot",
|
||||
"choose_workspace_for_integration": "Chọn không gian làm việc để kết nối ứng dụng này",
|
||||
"integrations_description": "Ứng dụng làm việc với Plane phải kết nối với không gian làm việc mà bạn là quản trị viên.",
|
||||
"create_a_new_workspace": "Tạo không gian làm việc mới",
|
||||
"learn_more_about_workspaces": "Tìm hiểu thêm về không gian làm việc",
|
||||
"no_workspaces_to_connect": "Không có không gian làm việc để kết nối",
|
||||
"no_workspaces_to_connect_description": "Bạn cần tạo không gian làm việc để kết nối ứng dụng này",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "Thời gian tạo",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "新密码必须不同于旧密码",
|
||||
"edited": "已编辑",
|
||||
"bot": "机器人",
|
||||
"choose_workspace_for_integration": "选择工作区以连接此应用程序",
|
||||
"integrations_description": "与 Plane 一起工作的应用程序必须连接到您是管理员的工作区",
|
||||
"create_a_new_workspace": "创建新的工作区",
|
||||
"learn_more_about_workspaces": "了解更多关于工作区的信息",
|
||||
"no_workspaces_to_connect": "没有工作区可连接",
|
||||
"no_workspaces_to_connect_description": "您需要创建工作区才能连接此应用程序",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "创建时间",
|
||||
|
||||
@@ -502,6 +502,13 @@
|
||||
"new_password_must_be_different_from_old_password": "新密碼必須與舊密碼不同",
|
||||
"edited": "已編輯",
|
||||
"bot": "機器人",
|
||||
"choose_workspace_for_integration": "選擇工作區以連接此應用程式",
|
||||
"integrations_description": "與 Plane 一起工作的應用程式必須連接到您是管理員的工作區",
|
||||
"create_a_new_workspace": "建立新的工作區",
|
||||
"learn_more_about_workspaces": "了解更多關於工作區的資訊",
|
||||
"no_workspaces_to_connect": "沒有工作區可連接",
|
||||
"no_workspaces_to_connect_description": "您需要建立工作區才能連接整合和模板",
|
||||
|
||||
"project_view": {
|
||||
"sort_by": {
|
||||
"created_at": "建立時間",
|
||||
|
||||
9
web/app/workspaces/layout.tsx
Normal file
9
web/app/workspaces/layout.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Workspaces",
|
||||
};
|
||||
|
||||
export default function WorkspacesLayout({ children }: { children: React.ReactNode }) {
|
||||
return children;
|
||||
}
|
||||
45
web/app/workspaces/page.tsx
Normal file
45
web/app/workspaces/page.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
import { useTheme } from "next-themes";
|
||||
|
||||
// hooks
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { WorkspacePicker } from "@/components/common/workspace-picker";
|
||||
import { useUser } from "@/hooks/store";
|
||||
// services
|
||||
import { AuthenticationWrapper } from "@/lib/wrappers";
|
||||
// images
|
||||
import BlackHorizontalLogo from "@/public/plane-logos/black-horizontal-with-blue-logo.png";
|
||||
import WhiteHorizontalLogo from "@/public/plane-logos/white-horizontal-with-blue-logo.png";
|
||||
|
||||
const WorkspacePickerPage = observer(() => {
|
||||
// hooks
|
||||
const { t } = useTranslation();
|
||||
const { data: currentUser } = useUser();
|
||||
// next-themes
|
||||
const { resolvedTheme } = useTheme();
|
||||
const logo = resolvedTheme === "light" ? BlackHorizontalLogo : WhiteHorizontalLogo;
|
||||
|
||||
return (
|
||||
<AuthenticationWrapper>
|
||||
<div className="flex flex-col h-full gap-y-2 pb-20">
|
||||
<div className="flex items-center justify-between p-10 lg:px-20 xl:px-36">
|
||||
<Link href="/" className="bg-custom-background-100 px-3">
|
||||
<div className="h-[30px] w-[133px]">
|
||||
<Image src={logo} alt="Plane logo" />
|
||||
</div>
|
||||
</Link>
|
||||
<div className="text-sm text-custom-text-100">{currentUser?.email}</div>
|
||||
</div>
|
||||
<WorkspacePicker />
|
||||
</div>
|
||||
</AuthenticationWrapper>
|
||||
);
|
||||
});
|
||||
|
||||
export default WorkspacePickerPage;
|
||||
49
web/core/components/common/workspace-logo.tsx
Normal file
49
web/core/components/common/workspace-logo.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
import { getFileURL } from "@/helpers/file.helper";
|
||||
|
||||
interface IWorkspaceLogoProps {
|
||||
workspace: {
|
||||
logo_url: string;
|
||||
name: string;
|
||||
};
|
||||
className?: string;
|
||||
size?: "sm" | "md" | "lg";
|
||||
}
|
||||
|
||||
const WorkspaceLogo = (props: IWorkspaceLogoProps) => {
|
||||
const { workspace, className, size = "md" } = props;
|
||||
const sizeClass = size === "sm" ? "h-6 w-6 text-sm" : size === "md" ? "h-8 w-8 text-sm" : "h-10 w-10 text-base";
|
||||
return (
|
||||
<div className={cn("flex gap-3 items-center", className)}>
|
||||
{workspace.logo_url && workspace.logo_url !== "" ? (
|
||||
<div className={cn("relative my-auto flex rounded", sizeClass)}>
|
||||
<img
|
||||
src={getFileURL(workspace.logo_url)}
|
||||
className={cn("absolute left-0 top-0 h-full w-full rounded-md object-cover", sizeClass)}
|
||||
alt="Workspace Logo"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<span
|
||||
className={cn(
|
||||
"relative flex h-8 w-8 flex-shrink-0 items-center justify-center p-2 text-base uppercase font-medium border-custom-border-200",
|
||||
{ "rounded-md bg-custom-primary-500 text-white": !workspace?.logo_url },
|
||||
sizeClass
|
||||
)}
|
||||
>
|
||||
{workspace?.logo_url && workspace.logo_url !== "" ? (
|
||||
<img
|
||||
src={getFileURL(workspace.logo_url)}
|
||||
className="absolute left-0 top-0 h-full w-full rounded object-cover"
|
||||
alt={"workspace_logo"}
|
||||
/>
|
||||
) : (
|
||||
(workspace?.name?.[0] ?? "...")
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WorkspaceLogo;
|
||||
111
web/core/components/common/workspace-picker/index.tsx
Normal file
111
web/core/components/common/workspace-picker/index.tsx
Normal file
@@ -0,0 +1,111 @@
|
||||
import { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { useTheme } from "next-themes";
|
||||
import { Check } from "lucide-react";
|
||||
import { useTranslation } from "@plane/i18n";
|
||||
import { getButtonStyling, Loader } from "@plane/ui";
|
||||
import { cn } from "@plane/utils";
|
||||
import { useWorkspace } from "@/hooks/store";
|
||||
import DarkImage from "@/public/empty-state/marketplace/empty-workspace-dark.png";
|
||||
import LightImage from "@/public/empty-state/marketplace/empty-workspace-light.png";
|
||||
import WorkspaceLogo from "../workspace-logo";
|
||||
|
||||
export const WorkspacePicker = () => {
|
||||
// router
|
||||
const searchParams = useSearchParams();
|
||||
const nextPath = searchParams.get("next_path");
|
||||
// store
|
||||
const { loader, currentUserAdminWorkspaces } = useWorkspace();
|
||||
const { t } = useTranslation();
|
||||
// state
|
||||
const [selectedWorkspace, setSelectedWorkspace] = useState<string | null>(null);
|
||||
// hook
|
||||
const { resolvedTheme } = useTheme();
|
||||
const image = resolvedTheme === "dark" ? DarkImage : LightImage;
|
||||
|
||||
if (!loader && currentUserAdminWorkspaces?.length === 0) {
|
||||
return (
|
||||
<div className="relative flex flex-col gap-4 h-full w-full justify-center px-8 pb-8 items-center">
|
||||
<div className="text-3xl font-bold text-center">{t("no_workspaces_to_connect")}</div>
|
||||
<div className="font-medium text-custom-text-300 max-w-[450px] text-center">
|
||||
{t("no_workspaces_to_connect_description")}
|
||||
</div>
|
||||
<div className="overflow-y-auto vertical-scrollbar scrollbar-sm mb-10 w-full md:w-fit">
|
||||
<div className="w-full flex flex-col gap-2 items-center md:w-[450px]">
|
||||
<Image src={image} alt="empty workspace" />
|
||||
<div className="flex gap-2 flex-col md:flex-row">
|
||||
<Link
|
||||
href="https://plane.so/"
|
||||
target="_blank"
|
||||
className={cn(
|
||||
getButtonStyling("outline-primary", "md"),
|
||||
"border-custom-border-200 text-custom-text-100"
|
||||
)}
|
||||
>
|
||||
{t("learn_more_about_workspaces")}
|
||||
</Link>
|
||||
<Link
|
||||
href="/create-workspace"
|
||||
className={cn("text-sm text-custom-text-300 w-full", getButtonStyling("primary", "md"))}
|
||||
>
|
||||
{t("create_a_new_workspace")}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative flex flex-col gap-4 h-full w-full justify-center px-8 pb-8 items-center">
|
||||
<div className="text-3xl font-bold text-center">{t("choose_workspace_for_integration")}</div>
|
||||
<div className="font-medium text-custom-text-300 max-w-[450px] text-center">{t("integrations_description")}</div>
|
||||
<div className="overflow-y-auto vertical-scrollbar scrollbar-sm mb-10 w-full md:w-fit">
|
||||
<div className="w-full flex flex-col md:w-[450px] bg-custom-background-90 rounded p-4 gap-2 border-[0.5px] border-custom-border-200">
|
||||
{loader && (
|
||||
<Loader className="w-full flex flex-col gap-2">
|
||||
{Array.from({ length: 4 }).map((_, index) => (
|
||||
<Loader.Item key={index} height="43px" />
|
||||
))}
|
||||
</Loader>
|
||||
)}
|
||||
{!loader &&
|
||||
currentUserAdminWorkspaces?.map((workspace) => (
|
||||
<div key={workspace.id} className="w-full bg-custom-background-100 rounded">
|
||||
<Link
|
||||
href={`/${workspace.slug}${nextPath || ""}`}
|
||||
className={cn(
|
||||
"rounded p-2.5 flex items-center gap-2 border-[0.5px] border-custom-border-200 transition-all duration-200",
|
||||
"hover:bg-custom-primary-100/20 hover:border-custom-primary-100",
|
||||
{
|
||||
"bg-custom-primary-100/20 border-custom-primary-100": selectedWorkspace === workspace.id,
|
||||
}
|
||||
)}
|
||||
onClick={() => setSelectedWorkspace(workspace.id)}
|
||||
>
|
||||
<div className="flex gap-2 items-center">
|
||||
<WorkspaceLogo
|
||||
workspace={{
|
||||
logo_url: workspace.logo_url ?? "",
|
||||
name: workspace.name,
|
||||
}}
|
||||
size="sm"
|
||||
/>
|
||||
<div className="text-sm text-custom-text-200 font-medium">{workspace.name}</div>
|
||||
</div>
|
||||
{selectedWorkspace === workspace.id && (
|
||||
<div className="ml-auto size-[14px] bg-custom-primary-100 rounded-full flex items-center justify-center">
|
||||
<Check className="text-white w-[10px] h-[10px] m-auto" />
|
||||
</div>
|
||||
)}
|
||||
</Link>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -3,6 +3,7 @@ import set from "lodash/set";
|
||||
import { action, computed, observable, makeObservable, runInAction } from "mobx";
|
||||
// types
|
||||
import { computedFn } from "mobx-utils";
|
||||
import { EUserPermissions } from "@plane/constants";
|
||||
import { IWorkspaceSidebarNavigationItem, IWorkspace, IWorkspaceSidebarNavigation } from "@plane/types";
|
||||
// services
|
||||
import { WorkspaceService } from "@/plane-web/services";
|
||||
@@ -20,6 +21,7 @@ export interface IWorkspaceRootStore {
|
||||
// computed
|
||||
currentWorkspace: IWorkspace | null;
|
||||
workspacesCreatedByCurrentUser: IWorkspace[] | null;
|
||||
currentUserAdminWorkspaces: IWorkspace[] | null;
|
||||
navigationPreferencesMap: Record<string, IWorkspaceSidebarNavigation>;
|
||||
// computed actions
|
||||
getWorkspaceBySlug: (workspaceSlug: string) => IWorkspace | null;
|
||||
@@ -68,6 +70,7 @@ export class WorkspaceRootStore implements IWorkspaceRootStore {
|
||||
// computed
|
||||
currentWorkspace: computed,
|
||||
workspacesCreatedByCurrentUser: computed,
|
||||
currentUserAdminWorkspaces: computed,
|
||||
// computed actions
|
||||
getWorkspaceBySlug: action,
|
||||
getWorkspaceById: action,
|
||||
@@ -113,6 +116,17 @@ export class WorkspaceRootStore implements IWorkspaceRootStore {
|
||||
return userWorkspaces || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* computed value of all the workspaces where current user is admin
|
||||
*/
|
||||
get currentUserAdminWorkspaces() {
|
||||
if (!this.workspaces) return null;
|
||||
const user = this.user.data;
|
||||
if (!user) return null;
|
||||
const userWorkspaces = Object.values(this.workspaces ?? {})?.filter((w) => w.role === EUserPermissions.ADMIN);
|
||||
return userWorkspaces || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* get workspace info from the array of workspaces in the store using workspace slug
|
||||
* @param workspaceSlug
|
||||
|
||||
BIN
web/public/empty-state/marketplace/empty-workspace-dark.png
Normal file
BIN
web/public/empty-state/marketplace/empty-workspace-dark.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 92 KiB |
BIN
web/public/empty-state/marketplace/empty-workspace-light.png
Normal file
BIN
web/public/empty-state/marketplace/empty-workspace-light.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 245 KiB |
Reference in New Issue
Block a user