diff --git a/admin/helpers/authentication.helper.tsx b/admin/helpers/authentication.helper.tsx
index 6bfccd45e..cc9058611 100644
--- a/admin/helpers/authentication.helper.tsx
+++ b/admin/helpers/authentication.helper.tsx
@@ -1,5 +1,7 @@
import { ReactNode } from "react";
import Link from "next/link";
+// helpers
+import { SUPPORT_EMAIL } from "./common.helper";
export enum EPageTypes {
PUBLIC = "PUBLIC",
@@ -38,6 +40,7 @@ export enum EAuthenticationErrorCodes {
ADMIN_AUTHENTICATION_FAILED = "5175",
ADMIN_USER_ALREADY_EXIST = "5180",
ADMIN_USER_DOES_NOT_EXIST = "5185",
+ ADMIN_USER_DEACTIVATED = "5190",
}
export type TAuthErrorInfo = {
@@ -99,6 +102,10 @@ const errorCodeMessages: {
),
},
+ [EAuthenticationErrorCodes.ADMIN_USER_DEACTIVATED]: {
+ title: `User account deactivated`,
+ message: () => `User account deactivated. Please contact ${!!SUPPORT_EMAIL ? SUPPORT_EMAIL : "administrator"}.`,
+ },
};
export const authErrorHandler = (
@@ -106,6 +113,7 @@ export const authErrorHandler = (
email?: string | undefined
): TAuthErrorInfo | undefined => {
const bannerAlertErrorCodes = [
+ EAuthenticationErrorCodes.ADMIN_ALREADY_EXIST,
EAuthenticationErrorCodes.REQUIRED_ADMIN_EMAIL_PASSWORD_FIRST_NAME,
EAuthenticationErrorCodes.INVALID_ADMIN_EMAIL,
EAuthenticationErrorCodes.INVALID_ADMIN_PASSWORD,
@@ -113,6 +121,7 @@ export const authErrorHandler = (
EAuthenticationErrorCodes.ADMIN_AUTHENTICATION_FAILED,
EAuthenticationErrorCodes.ADMIN_USER_ALREADY_EXIST,
EAuthenticationErrorCodes.ADMIN_USER_DOES_NOT_EXIST,
+ EAuthenticationErrorCodes.ADMIN_USER_DEACTIVATED,
];
if (bannerAlertErrorCodes.includes(errorCode))
diff --git a/admin/helpers/common.helper.ts b/admin/helpers/common.helper.ts
index e7aae0698..e282e5792 100644
--- a/admin/helpers/common.helper.ts
+++ b/admin/helpers/common.helper.ts
@@ -10,6 +10,8 @@ export const SPACE_BASE_PATH = process.env.NEXT_PUBLIC_SPACE_BASE_PATH || "";
export const WEB_BASE_URL = process.env.NEXT_PUBLIC_WEB_BASE_URL || "";
+export const SUPPORT_EMAIL = process.env.NEXT_PUBLIC_SUPPORT_EMAIL || "";
+
export const ASSET_PREFIX = ADMIN_BASE_PATH;
export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs));
diff --git a/admin/layouts/default-layout.tsx b/admin/layouts/default-layout.tsx
index 4a3724248..1be40ea12 100644
--- a/admin/layouts/default-layout.tsx
+++ b/admin/layouts/default-layout.tsx
@@ -7,8 +7,8 @@ import { useTheme } from "next-themes";
// logo/ images
import PlaneBackgroundPatternDark from "public/auth/background-pattern-dark.svg";
import PlaneBackgroundPattern from "public/auth/background-pattern.svg";
-import BlackHorizontalLogo from "public/plane-logos/black-horizontal-with-blue-logo.svg";
-import WhiteHorizontalLogo from "public/plane-logos/white-horizontal-with-blue-logo.svg";
+import BlackHorizontalLogo from "public/plane-logos/black-horizontal-with-blue-logo.png";
+import WhiteHorizontalLogo from "public/plane-logos/white-horizontal-with-blue-logo.png";
type TDefaultLayout = {
children: ReactNode;
diff --git a/admin/public/plane-logos/black-horizontal-with-blue-logo.png b/admin/public/plane-logos/black-horizontal-with-blue-logo.png
new file mode 100644
index 000000000..c14505a6f
Binary files /dev/null and b/admin/public/plane-logos/black-horizontal-with-blue-logo.png differ
diff --git a/admin/public/plane-logos/black-horizontal-with-blue-logo.svg b/admin/public/plane-logos/black-horizontal-with-blue-logo.svg
deleted file mode 100644
index ae79919fc..000000000
--- a/admin/public/plane-logos/black-horizontal-with-blue-logo.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
diff --git a/admin/public/plane-logos/white-horizontal-with-blue-logo.png b/admin/public/plane-logos/white-horizontal-with-blue-logo.png
new file mode 100644
index 000000000..97560fb9f
Binary files /dev/null and b/admin/public/plane-logos/white-horizontal-with-blue-logo.png differ
diff --git a/admin/public/plane-logos/white-horizontal-with-blue-logo.svg b/admin/public/plane-logos/white-horizontal-with-blue-logo.svg
deleted file mode 100644
index 1f09cc34a..000000000
--- a/admin/public/plane-logos/white-horizontal-with-blue-logo.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
diff --git a/apiserver/plane/app/serializers/user.py b/apiserver/plane/app/serializers/user.py
index 1fff8a90f..05d8665b5 100644
--- a/apiserver/plane/app/serializers/user.py
+++ b/apiserver/plane/app/serializers/user.py
@@ -33,6 +33,7 @@ class UserSerializer(BaseSerializer):
"is_bot",
"is_password_autoset",
"is_email_verified",
+ "is_active",
]
extra_kwargs = {"password": {"write_only": True}}
diff --git a/apiserver/plane/app/views/user/base.py b/apiserver/plane/app/views/user/base.py
index 5a75f8105..9a9cdde43 100644
--- a/apiserver/plane/app/views/user/base.py
+++ b/apiserver/plane/app/views/user/base.py
@@ -1,3 +1,6 @@
+# Python imports
+# import uuid
+
# Django imports
from django.db.models import Case, Count, IntegerField, Q, When
from django.contrib.auth import logout
@@ -26,6 +29,7 @@ from plane.db.models import (
User,
WorkspaceMember,
WorkspaceMemberInvite,
+ Session,
)
from plane.license.models import Instance, InstanceAdmin
from plane.utils.cache import cache_response, invalidate_cache
@@ -160,12 +164,13 @@ class UserEndpoint(BaseViewSet):
email=user.email,
).delete()
- # Deactivate the user
- user.is_active = False
+ # Delete all sessions
+ Session.objects.filter(user_id=request.user.id).delete()
# Profile updates
profile = Profile.objects.get(user=user)
+ # Reset onboarding
profile.last_workspace_id = None
profile.is_tour_completed = False
profile.is_onboarded = False
@@ -177,7 +182,12 @@ class UserEndpoint(BaseViewSet):
}
profile.save()
- # User log out
+ # Reset password
+ # user.is_password_autoset = True
+ # user.set_password(uuid.uuid4().hex)
+
+ # Deactivate the user
+ user.is_active = False
user.last_logout_ip = user_ip(request=request)
user.last_logout_time = timezone.now()
user.save()
diff --git a/apiserver/plane/authentication/adapter/oauth.py b/apiserver/plane/authentication/adapter/oauth.py
index b841db99d..60c2ea0c6 100644
--- a/apiserver/plane/authentication/adapter/oauth.py
+++ b/apiserver/plane/authentication/adapter/oauth.py
@@ -85,5 +85,6 @@ class OauthAdapter(Adapter):
"refresh_token_expired_at"
),
"last_connected_at": timezone.now(),
+ "id_token": self.token_data.get("id_token", ""),
},
)
diff --git a/apiserver/plane/authentication/provider/oauth/github.py b/apiserver/plane/authentication/provider/oauth/github.py
index edccea449..798863d8f 100644
--- a/apiserver/plane/authentication/provider/oauth/github.py
+++ b/apiserver/plane/authentication/provider/oauth/github.py
@@ -100,6 +100,7 @@ class GitHubOAuthProvider(OauthAdapter):
if token_response.get("refresh_token_expired_at")
else None
),
+ "id_token": token_response.get("id_token", ""),
}
)
diff --git a/apiserver/plane/authentication/provider/oauth/google.py b/apiserver/plane/authentication/provider/oauth/google.py
index 591295cb1..9c17a75af 100644
--- a/apiserver/plane/authentication/provider/oauth/google.py
+++ b/apiserver/plane/authentication/provider/oauth/google.py
@@ -98,6 +98,7 @@ class GoogleOAuthProvider(OauthAdapter):
if token_response.get("refresh_token_expired_at")
else None
),
+ "id_token": token_response.get("id_token", ""),
}
)
diff --git a/apiserver/plane/db/migrations/0066_account_id_token_cycle_logo_props_module_logo_props.py b/apiserver/plane/db/migrations/0066_account_id_token_cycle_logo_props_module_logo_props.py
new file mode 100644
index 000000000..2ad5b7481
--- /dev/null
+++ b/apiserver/plane/db/migrations/0066_account_id_token_cycle_logo_props_module_logo_props.py
@@ -0,0 +1,58 @@
+# Generated by Django 4.2.11 on 2024-05-22 15:04
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("db", "0065_auto_20240415_0937"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="account",
+ name="id_token",
+ field=models.TextField(blank=True),
+ ),
+ migrations.AddField(
+ model_name="cycle",
+ name="logo_props",
+ field=models.JSONField(default=dict),
+ ),
+ migrations.AddField(
+ model_name="module",
+ name="logo_props",
+ field=models.JSONField(default=dict),
+ ),
+ migrations.AddField(
+ model_name="issueview",
+ name="logo_props",
+ field=models.JSONField(default=dict),
+ ),
+ migrations.AddField(
+ model_name="inbox",
+ name="logo_props",
+ field=models.JSONField(default=dict),
+ ),
+ migrations.AddField(
+ model_name="dashboard",
+ name="logo_props",
+ field=models.JSONField(default=dict),
+ ),
+ migrations.AddField(
+ model_name="widget",
+ name="logo_props",
+ field=models.JSONField(default=dict),
+ ),
+ migrations.AddField(
+ model_name="issue",
+ name="description_binary",
+ field=models.BinaryField(null=True),
+ ),
+ migrations.AddField(
+ model_name="team",
+ name="logo_props",
+ field=models.JSONField(default=dict),
+ ),
+ ]
diff --git a/apiserver/plane/db/models/cycle.py b/apiserver/plane/db/models/cycle.py
index 1b4e8e75b..5128ecbc5 100644
--- a/apiserver/plane/db/models/cycle.py
+++ b/apiserver/plane/db/models/cycle.py
@@ -70,6 +70,7 @@ class Cycle(ProjectBaseModel):
external_id = models.CharField(max_length=255, blank=True, null=True)
progress_snapshot = models.JSONField(default=dict)
archived_at = models.DateTimeField(null=True)
+ logo_props = models.JSONField(default=dict)
class Meta:
verbose_name = "Cycle"
diff --git a/apiserver/plane/db/models/dashboard.py b/apiserver/plane/db/models/dashboard.py
index 7d483060f..f21557a54 100644
--- a/apiserver/plane/db/models/dashboard.py
+++ b/apiserver/plane/db/models/dashboard.py
@@ -31,6 +31,7 @@ class Dashboard(BaseModel):
verbose_name="Dashboard Type",
default="home",
)
+ logo_props = models.JSONField(default=dict)
def __str__(self):
"""Return name of the dashboard"""
@@ -53,6 +54,7 @@ class Widget(TimeAuditModel):
)
key = models.CharField(max_length=255)
filters = models.JSONField(default=dict)
+ logo_props = models.JSONField(default=dict)
def __str__(self):
"""Return name of the widget"""
diff --git a/apiserver/plane/db/models/inbox.py b/apiserver/plane/db/models/inbox.py
index 6d72029b6..f45e90042 100644
--- a/apiserver/plane/db/models/inbox.py
+++ b/apiserver/plane/db/models/inbox.py
@@ -12,6 +12,7 @@ class Inbox(ProjectBaseModel):
)
is_default = models.BooleanField(default=False)
view_props = models.JSONField(default=dict)
+ logo_props = models.JSONField(default=dict)
def __str__(self):
"""Return name of the Inbox"""
diff --git a/apiserver/plane/db/models/issue.py b/apiserver/plane/db/models/issue.py
index 41aacf194..bf5fb87c8 100644
--- a/apiserver/plane/db/models/issue.py
+++ b/apiserver/plane/db/models/issue.py
@@ -135,6 +135,7 @@ class Issue(ProjectBaseModel):
description = models.JSONField(blank=True, default=dict)
description_html = models.TextField(blank=True, default="
")
description_stripped = models.TextField(blank=True, null=True)
+ description_binary = models.BinaryField(null=True)
priority = models.CharField(
max_length=30,
choices=PRIORITY_CHOICES,
diff --git a/apiserver/plane/db/models/module.py b/apiserver/plane/db/models/module.py
index 7e58088dc..a6b55f246 100644
--- a/apiserver/plane/db/models/module.py
+++ b/apiserver/plane/db/models/module.py
@@ -93,6 +93,7 @@ class Module(ProjectBaseModel):
external_source = models.CharField(max_length=255, null=True, blank=True)
external_id = models.CharField(max_length=255, blank=True, null=True)
archived_at = models.DateTimeField(null=True)
+ logo_props = models.JSONField(default=dict)
class Meta:
unique_together = ["name", "project"]
diff --git a/apiserver/plane/db/models/user.py b/apiserver/plane/db/models/user.py
index f35520d8f..c083b631c 100644
--- a/apiserver/plane/db/models/user.py
+++ b/apiserver/plane/db/models/user.py
@@ -189,6 +189,7 @@ class Account(TimeAuditModel):
refresh_token = models.TextField(null=True, blank=True)
refresh_token_expired_at = models.DateTimeField(null=True)
last_connected_at = models.DateTimeField(default=timezone.now)
+ id_token = models.TextField(blank=True)
metadata = models.JSONField(default=dict)
class Meta:
diff --git a/apiserver/plane/db/models/view.py b/apiserver/plane/db/models/view.py
index 87f0899c3..8916bd406 100644
--- a/apiserver/plane/db/models/view.py
+++ b/apiserver/plane/db/models/view.py
@@ -52,6 +52,7 @@ def get_default_display_properties():
}
+# DEPRECATED TODO: - Remove in next release
class GlobalView(BaseModel):
workspace = models.ForeignKey(
"db.Workspace", on_delete=models.CASCADE, related_name="global_views"
@@ -87,7 +88,6 @@ class GlobalView(BaseModel):
return f"{self.name} <{self.workspace.name}>"
-# DEPRECATED TODO: - Remove in next release
class IssueView(WorkspaceBaseModel):
name = models.CharField(max_length=255, verbose_name="View Name")
description = models.TextField(verbose_name="View Description", blank=True)
@@ -101,6 +101,7 @@ class IssueView(WorkspaceBaseModel):
default=1, choices=((0, "Private"), (1, "Public"))
)
sort_order = models.FloatField(default=65535)
+ logo_props = models.JSONField(default=dict)
class Meta:
verbose_name = "Issue View"
diff --git a/apiserver/plane/db/models/workspace.py b/apiserver/plane/db/models/workspace.py
index fe39f2d09..f9cd681ec 100644
--- a/apiserver/plane/db/models/workspace.py
+++ b/apiserver/plane/db/models/workspace.py
@@ -244,6 +244,7 @@ class Team(BaseModel):
workspace = models.ForeignKey(
Workspace, on_delete=models.CASCADE, related_name="workspace_team"
)
+ logo_props = models.JSONField(default=dict)
def __str__(self):
"""Return name of the team"""
diff --git a/packages/ui/src/button/helper.tsx b/packages/ui/src/button/helper.tsx
index 0378b0334..ae9e85359 100644
--- a/packages/ui/src/button/helper.tsx
+++ b/packages/ui/src/button/helper.tsx
@@ -44,9 +44,9 @@ export const buttonStyling: IButtonStyling = {
disabled: `cursor-not-allowed !bg-custom-primary-60 hover:bg-custom-primary-60`,
},
"accent-primary": {
- default: `bg-custom-primary-10 text-custom-primary-100`,
- hover: `hover:bg-custom-primary-20 hover:text-custom-primary-200`,
- pressed: `focus:bg-custom-primary-20`,
+ default: `bg-custom-primary-100/20 text-custom-primary-100`,
+ hover: `hover:bg-custom-primary-100/10 hover:text-custom-primary-200`,
+ pressed: `focus:bg-custom-primary-100/10`,
disabled: `cursor-not-allowed !text-custom-primary-60`,
},
"outline-primary": {
diff --git a/space/app/loading.tsx b/space/app/loading.tsx
deleted file mode 100644
index d35e42a76..000000000
--- a/space/app/loading.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-"use client";
-import Image from "next/image";
-import { useTheme } from "next-themes";
-// assets
-import LogoSpinnerDark from "@/public/images/logo-spinner-dark.gif";
-import LogoSpinnerLight from "@/public/images/logo-spinner-light.gif";
-
-export default function LogoSpinner() {
- const { resolvedTheme } = useTheme();
-
- const logoSrc = resolvedTheme === "dark" ? LogoSpinnerDark : LogoSpinnerLight;
-
- return (
-
- );
-}
diff --git a/space/app/page.tsx b/space/app/page.tsx
index d03300a25..a6058fb8a 100644
--- a/space/app/page.tsx
+++ b/space/app/page.tsx
@@ -1,5 +1,6 @@
"use client";
+import { observer } from "mobx-react-lite";
// components
import { UserLoggedIn } from "@/components/account";
import { LogoSpinner } from "@/components/common";
@@ -7,7 +8,7 @@ import { AuthView } from "@/components/views";
// hooks
import { useUser } from "@/hooks/store";
-export default function HomePage() {
+const HomePage = observer(() => {
const { data: currentUser, isAuthenticated, isLoading } = useUser();
if (isLoading) return ;
@@ -15,4 +16,6 @@ export default function HomePage() {
if (currentUser && isAuthenticated) return ;
return ;
-}
+});
+
+export default HomePage;
diff --git a/space/components/account/user-logged-in.tsx b/space/components/account/user-logged-in.tsx
index a9930b5fd..33be330fa 100644
--- a/space/components/account/user-logged-in.tsx
+++ b/space/components/account/user-logged-in.tsx
@@ -6,7 +6,7 @@ import { UserAvatar } from "@/components/issues/navbar/user-avatar";
// hooks
import { useUser } from "@/hooks/store";
// assets
-import PlaneLogo from "@/public/plane-logos/black-horizontal-with-blue-logo.svg";
+import PlaneLogo from "@/public/plane-logos/black-horizontal-with-blue-logo.png";
import UserLoggedInImage from "@/public/user-logged-in.svg";
export const UserLoggedIn = () => {
diff --git a/space/components/instance/not-ready-view.tsx b/space/components/instance/not-ready-view.tsx
index f79778387..be46a9473 100644
--- a/space/components/instance/not-ready-view.tsx
+++ b/space/components/instance/not-ready-view.tsx
@@ -12,8 +12,8 @@ import { GOD_MODE_URL, SPACE_BASE_PATH } from "@/helpers/common.helper";
import PlaneTakeOffImage from "@/public/instance/plane-takeoff.png";
import PlaneBackgroundPatternDark from "public/auth/background-pattern-dark.svg";
import PlaneBackgroundPattern from "public/auth/background-pattern.svg";
-import BlackHorizontalLogo from "public/plane-logos/black-horizontal-with-blue-logo.svg";
-import WhiteHorizontalLogo from "public/plane-logos/white-horizontal-with-blue-logo.svg";
+import BlackHorizontalLogo from "public/plane-logos/black-horizontal-with-blue-logo.png";
+import WhiteHorizontalLogo from "public/plane-logos/white-horizontal-with-blue-logo.png";
export const InstanceNotReady: FC = () => {
const { resolvedTheme } = useTheme();
diff --git a/space/components/views/auth.tsx b/space/components/views/auth.tsx
index 88023dbef..538519696 100644
--- a/space/components/views/auth.tsx
+++ b/space/components/views/auth.tsx
@@ -11,8 +11,8 @@ import { SPACE_BASE_PATH } from "@/helpers/common.helper";
// images
import PlaneBackgroundPatternDark from "@/public/auth/background-pattern-dark.svg";
import PlaneBackgroundPattern from "@/public/auth/background-pattern.svg";
-import BlackHorizontalLogo from "public/plane-logos/black-horizontal-with-blue-logo.svg";
-import WhiteHorizontalLogo from "public/plane-logos/white-horizontal-with-blue-logo.svg";
+import BlackHorizontalLogo from "public/plane-logos/black-horizontal-with-blue-logo.png";
+import WhiteHorizontalLogo from "public/plane-logos/white-horizontal-with-blue-logo.png";
export const AuthView = observer(() => {
// hooks
@@ -37,7 +37,7 @@ export const AuthView = observer(() => {
-
diff --git a/space/helpers/authentication.helper.tsx b/space/helpers/authentication.helper.tsx
index e2be3c617..0e5ab0186 100644
--- a/space/helpers/authentication.helper.tsx
+++ b/space/helpers/authentication.helper.tsx
@@ -1,5 +1,7 @@
import { ReactNode } from "react";
import Link from "next/link";
+// helpers
+import { SUPPORT_EMAIL } from "./common.helper";
export enum EPageTypes {
INIT = "INIT",
@@ -152,7 +154,7 @@ const errorCodeMessages: {
// sign in
[EAuthenticationErrorCodes.USER_ACCOUNT_DEACTIVATED]: {
title: `User account deactivated`,
- message: () => Your account is deactivated. Contact support@plane.so.
,
+ message: () => `User account deactivated. Please contact ${!!SUPPORT_EMAIL ? SUPPORT_EMAIL : "administrator"}.`,
},
[EAuthenticationErrorCodes.USER_DOES_NOT_EXIST]: {
diff --git a/space/helpers/common.helper.ts b/space/helpers/common.helper.ts
index 52c61e4e2..6db73a4a1 100644
--- a/space/helpers/common.helper.ts
+++ b/space/helpers/common.helper.ts
@@ -8,6 +8,8 @@ export const ADMIN_BASE_PATH = process.env.NEXT_PUBLIC_ADMIN_BASE_PATH || "";
export const SPACE_BASE_PATH = process.env.NEXT_PUBLIC_SPACE_BASE_PATH || "";
+export const SUPPORT_EMAIL = process.env.NEXT_PUBLIC_SUPPORT_EMAIL || "";
+
export const WEB_BASE_URL = process.env.NEXT_PUBLIC_WEB_BASE_URL || "";
export const GOD_MODE_URL = encodeURI(`${ADMIN_BASE_URL}${ADMIN_BASE_PATH}`);
diff --git a/space/lib/instance-provider.tsx b/space/lib/instance-provider.tsx
index a4de61a16..8447d8a5f 100644
--- a/space/lib/instance-provider.tsx
+++ b/space/lib/instance-provider.tsx
@@ -16,8 +16,8 @@ import { useInstance, useUser } from "@/hooks/store";
// assets
import PlaneBackgroundPatternDark from "public/auth/background-pattern-dark.svg";
import PlaneBackgroundPattern from "public/auth/background-pattern.svg";
-import BlackHorizontalLogo from "public/plane-logos/black-horizontal-with-blue-logo.svg";
-import WhiteHorizontalLogo from "public/plane-logos/white-horizontal-with-blue-logo.svg";
+import BlackHorizontalLogo from "public/plane-logos/black-horizontal-with-blue-logo.png";
+import WhiteHorizontalLogo from "public/plane-logos/white-horizontal-with-blue-logo.png";
export const InstanceProvider = observer(({ children }: { children: ReactNode }) => {
const { fetchInstanceInfo, instance, error } = useInstance();
@@ -31,7 +31,11 @@ export const InstanceProvider = observer(({ children }: { children: ReactNode })
revalidateIfStale: false,
errorRetryCount: 0,
});
- useSWR("CURRENT_USER", () => fetchCurrentUser());
+ useSWR("CURRENT_USER", () => fetchCurrentUser(), {
+ shouldRetryOnError: false,
+ revalidateOnFocus: false,
+ revalidateIfStale: false,
+ });
if (!instance && !error)
return (
diff --git a/space/public/plane-logos/black-horizontal-with-blue-logo.png b/space/public/plane-logos/black-horizontal-with-blue-logo.png
new file mode 100644
index 000000000..c14505a6f
Binary files /dev/null and b/space/public/plane-logos/black-horizontal-with-blue-logo.png differ
diff --git a/space/public/plane-logos/black-horizontal-with-blue-logo.svg b/space/public/plane-logos/black-horizontal-with-blue-logo.svg
deleted file mode 100644
index ae79919fc..000000000
--- a/space/public/plane-logos/black-horizontal-with-blue-logo.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
diff --git a/space/public/plane-logos/white-horizontal-with-blue-logo.png b/space/public/plane-logos/white-horizontal-with-blue-logo.png
new file mode 100644
index 000000000..97560fb9f
Binary files /dev/null and b/space/public/plane-logos/white-horizontal-with-blue-logo.png differ
diff --git a/space/public/plane-logos/white-horizontal-with-blue-logo.svg b/space/public/plane-logos/white-horizontal-with-blue-logo.svg
deleted file mode 100644
index 1f09cc34a..000000000
--- a/space/public/plane-logos/white-horizontal-with-blue-logo.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-
diff --git a/web/components/instance/not-ready-view.tsx b/web/components/instance/not-ready-view.tsx
index 526030f56..68221283f 100644
--- a/web/components/instance/not-ready-view.tsx
+++ b/web/components/instance/not-ready-view.tsx
@@ -10,8 +10,8 @@ import PlaneTakeOffImage from "@/public/plane-takeoff.png";
// assets
import PlaneBackgroundPatternDark from "public/auth/background-pattern-dark.svg";
import PlaneBackgroundPattern from "public/auth/background-pattern.svg";
-import BlackHorizontalLogo from "public/plane-logos/black-horizontal-with-blue-logo.svg";
-import WhiteHorizontalLogo from "public/plane-logos/white-horizontal-with-blue-logo.svg";
+import BlackHorizontalLogo from "public/plane-logos/black-horizontal-with-blue-logo.png";
+import WhiteHorizontalLogo from "public/plane-logos/white-horizontal-with-blue-logo.png";
export const InstanceNotReady: FC = () => {
const { resolvedTheme } = useTheme();
diff --git a/web/components/issues/delete-issue-modal.tsx b/web/components/issues/delete-issue-modal.tsx
index dc7b64075..49c1a8700 100644
--- a/web/components/issues/delete-issue-modal.tsx
+++ b/web/components/issues/delete-issue-modal.tsx
@@ -13,11 +13,12 @@ type Props = {
handleClose: () => void;
dataId?: string | null | undefined;
data?: TIssue;
+ isSubIssue?: boolean;
onSubmit?: () => Promise;
};
export const DeleteIssueModal: React.FC = (props) => {
- const { dataId, data, isOpen, handleClose, onSubmit } = props;
+ const { dataId, data, isOpen, handleClose, isSubIssue = false, onSubmit } = props;
// states
const [isDeleting, setIsDeleting] = useState(false);
// store hooks
@@ -44,6 +45,11 @@ export const DeleteIssueModal: React.FC = (props) => {
if (onSubmit)
await onSubmit()
.then(() => {
+ setToast({
+ type: TOAST_TYPE.SUCCESS,
+ title: "Success!",
+ message: `${isSubIssue ? "Sub-issue" : "Issue"} deleted successfully`,
+ });
onClose();
})
.catch(() => {
diff --git a/web/components/issues/issue-layouts/empty-states/module.tsx b/web/components/issues/issue-layouts/empty-states/module.tsx
index 536bd985b..a75cec391 100644
--- a/web/components/issues/issue-layouts/empty-states/module.tsx
+++ b/web/components/issues/issue-layouts/empty-states/module.tsx
@@ -55,6 +55,7 @@ export const ModuleEmptyState: React.FC = observer((props) => {
const emptyStateType = isEmptyFilters ? EmptyStateType.PROJECT_EMPTY_FILTER : EmptyStateType.PROJECT_MODULE_ISSUES;
const additionalPath = activeLayout ?? "list";
+ const emptyStateSize = isEmptyFilters ? "lg" : "sm";
return (
<>
@@ -70,6 +71,7 @@ export const ModuleEmptyState: React.FC = observer((props) => {
= observer((prop
setToast({
type: TOAST_TYPE.SUCCESS,
title: "Success!",
- message: "Issue created successfully.",
+ message: `${is_draft_issue ? "Draft issue" : "Issue"} created successfully.`,
});
captureIssueEvent({
eventName: ISSUE_CREATED,
@@ -178,7 +178,7 @@ export const CreateUpdateIssueModal: React.FC = observer((prop
setToast({
type: TOAST_TYPE.ERROR,
title: "Error!",
- message: "Issue could not be created. Please try again.",
+ message: `${is_draft_issue ? "Draft issue" : "Issue"} could not be created. Please try again.`,
});
captureIssueEvent({
eventName: ISSUE_CREATED,
diff --git a/web/components/issues/sub-issues/root.tsx b/web/components/issues/sub-issues/root.tsx
index a88434e3b..b697ff20a 100644
--- a/web/components/issues/sub-issues/root.tsx
+++ b/web/components/issues/sub-issues/root.tsx
@@ -1,20 +1,22 @@
import { FC, useCallback, useEffect, useMemo, useState } from "react";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
+// icons
import { Plus, ChevronRight, Loader, Pencil } from "lucide-react";
+// types
import { IUser, TIssue } from "@plane/types";
-// hooks
+// ui
import { CircularProgressIndicator, CustomMenu, LayersIcon, TOAST_TYPE, setToast } from "@plane/ui";
+// components
import { ExistingIssuesListModal } from "@/components/core";
import { CreateUpdateIssueModal, DeleteIssueModal } from "@/components/issues";
+// helpers
import { cn } from "@/helpers/common.helper";
import { copyTextToClipboard } from "@/helpers/string.helper";
+// hooks
import { useEventTracker, useIssueDetail } from "@/hooks/store";
-// components
+// local components
import { IssueList } from "./issues-list";
-// ui
-// helpers
-// types
export interface ISubIssuesRoot {
workspaceSlug: string;
@@ -248,11 +250,6 @@ export const SubIssuesRoot: FC = observer((props) => {
try {
setSubIssueHelpers(parentIssueId, "issue_loader", issueId);
await deleteSubIssue(workspaceSlug, projectId, parentIssueId, issueId);
- setToast({
- type: TOAST_TYPE.SUCCESS,
- title: "Error!",
- message: "Issue deleted successfully",
- });
captureIssueEvent({
eventName: "Sub-issue deleted",
payload: { id: issueId, state: "SUCCESS", element: "Issue detail page" },
@@ -535,6 +532,7 @@ export const SubIssuesRoot: FC = observer((props) => {
issueCrudState?.delete?.issue?.id as string
)
}
+ isSubIssue
/>
)}
>
diff --git a/web/components/onboarding/create-or-join-workspaces.tsx b/web/components/onboarding/create-or-join-workspaces.tsx
index 1f0bd5c69..b88857186 100644
--- a/web/components/onboarding/create-or-join-workspaces.tsx
+++ b/web/components/onboarding/create-or-join-workspaces.tsx
@@ -6,7 +6,7 @@ import { useTheme } from "next-themes";
// types
import { IWorkspaceMemberInvitation, TOnboardingSteps } from "@plane/types";
// components
-import { Invitations, OnboardingHeader, SwitchOrDeleteAccountDropdown, CreateWorkspace } from "@/components/onboarding";
+import { Invitations, OnboardingHeader, SwitchAccountDropdown, CreateWorkspace } from "@/components/onboarding";
// hooks
import { useUser } from "@/hooks/store";
// assets
@@ -55,7 +55,7 @@ export const CreateOrJoinWorkspaces: React.FC = observer((props) => {
@@ -79,7 +79,7 @@ export const CreateOrJoinWorkspaces: React.FC
= observer((props) => {
-
+
Promise;
@@ -366,7 +366,7 @@ export const InviteMembers: React.FC = (props) => {
{/* Since this will always be the last step */}
-
+
@@ -433,7 +433,7 @@ export const InviteMembers: React.FC
= (props) => {
-
+
= observer((props) => {
@@ -567,7 +567,7 @@ export const ProfileSetup: React.FC
= observer((props) => {
-
+
{profileSetupStep === EProfileSetupSteps.USER_PERSONALIZATION ? (
= observer((props) => {
+export const SwitchAccountDropdown: FC = observer((props) => {
const { fullName } = props;
// states
- const [showDeleteAccountModal, setShowDeleteAccountModal] = useState(false);
+ const [showSwitchAccountModal, setShowSwitchAccountModal] = useState(false);
// store hooks
const { data: user } = useUser();
@@ -30,7 +30,7 @@ export const SwitchOrDeleteAccountDropdown: FC
- setShowDeleteAccountModal(false)} />
+ setShowSwitchAccountModal(false)} />
{user?.avatar && (
setShowDeleteAccountModal(true)}
+ onClick={() => setShowSwitchAccountModal(true)}
>
Wrong e-mail address?
diff --git a/web/components/onboarding/switch-delete-account-modal.tsx b/web/components/onboarding/switch-account-modal.tsx
similarity index 61%
rename from web/components/onboarding/switch-delete-account-modal.tsx
rename to web/components/onboarding/switch-account-modal.tsx
index bfa17387f..35f23588d 100644
--- a/web/components/onboarding/switch-delete-account-modal.tsx
+++ b/web/components/onboarding/switch-account-modal.tsx
@@ -1,34 +1,31 @@
import React, { useState } from "react";
import { useRouter } from "next/router";
import { useTheme } from "next-themes";
-import { mutate } from "swr";
-import { Trash2 } from "lucide-react";
+import { ArrowRightLeft } from "lucide-react";
import { Dialog, Transition } from "@headlessui/react";
-// hooks
-import { Button, TOAST_TYPE, setToast } from "@plane/ui";
-import { useUser } from "@/hooks/store";
// ui
+import { Button, TOAST_TYPE, setToast } from "@plane/ui";
+// hooks
+import { useUser } from "@/hooks/store";
type Props = {
isOpen: boolean;
onClose: () => void;
};
-export const SwitchOrDeleteAccountModal: React.FC = (props) => {
+export const SwitchAccountModal: React.FC = (props) => {
const { isOpen, onClose } = props;
// states
const [switchingAccount, setSwitchingAccount] = useState(false);
- const [isDeactivating, setIsDeactivating] = useState(false);
// router
const router = useRouter();
// store hooks
- const { signOut, deactivateAccount } = useUser();
+ const { data: userData, signOut } = useUser();
const { setTheme } = useTheme();
const handleClose = () => {
setSwitchingAccount(false);
- setIsDeactivating(false);
onClose();
};
@@ -51,32 +48,6 @@ export const SwitchOrDeleteAccountModal: React.FC = (props) => {
.finally(() => setSwitchingAccount(false));
};
- const handleDeactivateAccount = async () => {
- setIsDeactivating(true);
-
- await deactivateAccount()
- .then(() => {
- setToast({
- type: TOAST_TYPE.SUCCESS,
- title: "Success!",
- message: "Account deleted successfully.",
- });
- mutate("CURRENT_USER_DETAILS", null);
- signOut();
- setTheme("system");
- router.push("/");
- handleClose();
- })
- .catch((err: any) =>
- setToast({
- type: TOAST_TYPE.ERROR,
- title: "Error!",
- message: err?.error,
- })
- )
- .finally(() => setIsDeactivating(false));
- };
-
return (