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 7a17853c3..527597ddc 100644 --- a/apiserver/plane/db/models/issue.py +++ b/apiserver/plane/db/models/issue.py @@ -128,6 +128,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 ( -
-
- logo -
-
- ); -} 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 ( @@ -104,32 +75,30 @@ export const SwitchOrDeleteAccountModal: React.FC = (props) => { leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" > -
-
-
-
-