Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7052a1e867 | ||
|
|
fee4527c46 | ||
|
|
f71a46b893 | ||
|
|
ec478a8979 | ||
|
|
e07d91e857 | ||
|
|
9ccb3e321a | ||
|
|
f2c046dff9 | ||
|
|
2a378b3bc1 |
@@ -111,3 +111,4 @@ build/
|
||||
.react-router/
|
||||
AGENTS.md
|
||||
temp/
|
||||
scripts/
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
"uuid": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dotenvx/dotenvx": "catalog:",
|
||||
"@plane/eslint-config": "workspace:*",
|
||||
"@plane/tailwind-config": "workspace:*",
|
||||
"@plane/typescript-config": "workspace:*",
|
||||
@@ -57,7 +58,6 @@
|
||||
"@types/node": "catalog:",
|
||||
"@types/react": "catalog:",
|
||||
"@types/react-dom": "catalog:",
|
||||
"dotenv": "^16.4.5",
|
||||
"typescript": "catalog:",
|
||||
"vite": "catalog:",
|
||||
"vite-tsconfig-paths": "^5.1.4"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import path from "node:path";
|
||||
import * as dotenv from "@dotenvx/dotenvx";
|
||||
import { reactRouter } from "@react-router/dev/vite";
|
||||
import dotenv from "dotenv";
|
||||
import { defineConfig } from "vite";
|
||||
import tsconfigPaths from "vite-tsconfig-paths";
|
||||
import { joinUrlPath } from "@plane/utils";
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
# Generated by Django 4.2.25 on 2025-12-02 14:16
|
||||
|
||||
from django.db import migrations, models
|
||||
import plane.db.models.workspace
|
||||
|
||||
|
||||
def get_default_feature_tours():
|
||||
return {
|
||||
"work_items": True,
|
||||
"cycles": True,
|
||||
"modules": True,
|
||||
"intake": True,
|
||||
"pages": True,
|
||||
}
|
||||
|
||||
def populate_feature_tours(apps, _schema_editor):
|
||||
WorkspaceUserProperties = apps.get_model('db', 'WorkspaceUserProperties')
|
||||
default_value = get_default_feature_tours()
|
||||
# Use bulk update for better performance
|
||||
WorkspaceUserProperties.objects.all().update(feature_tours=default_value)
|
||||
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('db', '0112_auto_20251124_0603'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='profile',
|
||||
name='is_navigation_tour_completed',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='workspaceuserproperties',
|
||||
name='feature_tours',
|
||||
field=models.JSONField(default=plane.db.models.workspace.get_default_feature_tours),
|
||||
),
|
||||
migrations.RunPython(populate_feature_tours, reverse_code=migrations.RunPython.noop),
|
||||
]
|
||||
@@ -214,9 +214,6 @@ class Profile(TimeAuditModel):
|
||||
goals = models.JSONField(default=dict)
|
||||
background_color = models.CharField(max_length=255, default=get_random_color)
|
||||
|
||||
# navigation tour
|
||||
is_navigation_tour_completed = models.BooleanField(default=False)
|
||||
|
||||
# marketing
|
||||
has_marketing_email_consent = models.BooleanField(default=False)
|
||||
|
||||
|
||||
@@ -112,16 +112,6 @@ def slug_validator(value):
|
||||
raise ValidationError("Slug is not valid")
|
||||
|
||||
|
||||
def get_default_feature_tours():
|
||||
return {
|
||||
"work_items": False,
|
||||
"cycles": False,
|
||||
"modules": False,
|
||||
"intake": False,
|
||||
"pages": False,
|
||||
}
|
||||
|
||||
|
||||
class Workspace(BaseModel):
|
||||
TIMEZONE_CHOICES = tuple(zip(pytz.common_timezones, pytz.common_timezones))
|
||||
|
||||
@@ -335,7 +325,6 @@ class WorkspaceUserProperties(BaseModel):
|
||||
choices=NavigationControlPreference.choices,
|
||||
default=NavigationControlPreference.ACCORDION,
|
||||
)
|
||||
feature_tours = models.JSONField(default=get_default_feature_tours)
|
||||
|
||||
class Meta:
|
||||
unique_together = ["workspace", "user", "deleted_at"]
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
},
|
||||
"author": "Plane Software Inc.",
|
||||
"dependencies": {
|
||||
"@dotenvx/dotenvx": "^1.49.0",
|
||||
"@dotenvx/dotenvx": "catalog:",
|
||||
"@hocuspocus/extension-database": "2.15.2",
|
||||
"@hocuspocus/extension-logger": "2.15.2",
|
||||
"@hocuspocus/extension-redis": "2.15.2",
|
||||
@@ -41,8 +41,7 @@
|
||||
"axios": "catalog:",
|
||||
"compression": "1.8.1",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.21.2",
|
||||
"express": "catalog:",
|
||||
"express-ws": "^5.0.2",
|
||||
"helmet": "^7.1.0",
|
||||
"ioredis": "5.7.0",
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"uuid": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dotenvx/dotenvx": "catalog:",
|
||||
"@plane/eslint-config": "workspace:*",
|
||||
"@plane/tailwind-config": "workspace:*",
|
||||
"@plane/typescript-config": "workspace:*",
|
||||
@@ -61,7 +62,6 @@
|
||||
"@types/node": "catalog:",
|
||||
"@types/react": "catalog:",
|
||||
"@types/react-dom": "catalog:",
|
||||
"dotenv": "^16.4.5",
|
||||
"typescript": "catalog:",
|
||||
"vite": "catalog:",
|
||||
"vite-tsconfig-paths": "^5.1.4"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import path from "node:path";
|
||||
import * as dotenv from "@dotenvx/dotenvx";
|
||||
import { reactRouter } from "@react-router/dev/vite";
|
||||
import dotenv from "dotenv";
|
||||
import { defineConfig } from "vite";
|
||||
import tsconfigPaths from "vite-tsconfig-paths";
|
||||
import { joinUrlPath } from "@plane/utils";
|
||||
|
||||
@@ -1,17 +1,41 @@
|
||||
// components
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams, usePathname } from "next/navigation";
|
||||
import { cn } from "@plane/utils";
|
||||
import { TopNavPowerK } from "@/components/navigation";
|
||||
import { HelpMenuRoot } from "@/components/workspace/sidebar/help-section/root";
|
||||
import { UserMenuRoot } from "@/components/workspace/sidebar/user-menu-root";
|
||||
import { WorkspaceMenuRoot } from "@/components/workspace/sidebar/workspace-menu-root";
|
||||
import { useAppRailPreferences } from "@/hooks/use-navigation-preferences";
|
||||
import { Tooltip } from "@plane/propel/tooltip";
|
||||
import { AppSidebarItem } from "@/components/sidebar/sidebar-item";
|
||||
import { InboxIcon } from "@plane/propel/icons";
|
||||
import useSWR from "swr";
|
||||
import { useWorkspaceNotifications } from "@/hooks/store/notifications";
|
||||
|
||||
export const TopNavigationRoot = observer(() => {
|
||||
// router
|
||||
const { workspaceSlug, projectId, workItem } = useParams();
|
||||
const pathname = usePathname();
|
||||
|
||||
// store hooks
|
||||
const { unreadNotificationsCount, getUnreadNotificationsCount } = useWorkspaceNotifications();
|
||||
const { preferences } = useAppRailPreferences();
|
||||
|
||||
const showLabel = preferences.displayMode === "icon_with_label";
|
||||
|
||||
// Fetch notification count
|
||||
useSWR(
|
||||
workspaceSlug ? "WORKSPACE_UNREAD_NOTIFICATION_COUNT" : null,
|
||||
workspaceSlug ? () => getUnreadNotificationsCount(workspaceSlug.toString()) : null
|
||||
);
|
||||
|
||||
// Calculate notification count
|
||||
const isMentionsEnabled = unreadNotificationsCount.mention_unread_notifications_count > 0;
|
||||
const totalNotifications = isMentionsEnabled
|
||||
? unreadNotificationsCount.mention_unread_notifications_count
|
||||
: unreadNotificationsCount.total_unread_notifications_count;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn("flex items-center min-h-11 w-full px-3.5 z-[27] transition-all duration-300", {
|
||||
@@ -28,6 +52,23 @@ export const TopNavigationRoot = observer(() => {
|
||||
</div>
|
||||
{/* Additional Actions */}
|
||||
<div className="shrink-0 flex-1 flex gap-1 items-center justify-end">
|
||||
<Tooltip tooltipContent="Inbox" position="bottom">
|
||||
<AppSidebarItem
|
||||
variant="link"
|
||||
item={{
|
||||
href: `/${workspaceSlug?.toString()}/notifications/`,
|
||||
icon: (
|
||||
<div className="relative">
|
||||
<InboxIcon className="size-5" />
|
||||
{totalNotifications > 0 && (
|
||||
<span className="absolute -top-0 -right-0 size-2 rounded-full bg-red-500" />
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
isActive: pathname?.includes("/notifications/"),
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
<HelpMenuRoot />
|
||||
<div className="flex items-center justify-center size-8 hover:bg-custom-background-80 rounded-md">
|
||||
<UserMenuRoot size="xs" />
|
||||
|
||||
@@ -44,7 +44,7 @@ export const ProjectActionsMenu: FC<Props> = ({
|
||||
customButton={
|
||||
<span
|
||||
ref={actionSectionRef}
|
||||
className="grid place-items-center p-0.5 text-custom-sidebar-text-400 hover:bg-custom-sidebar-background-80 rounded"
|
||||
className="grid place-items-center p-0.5 text-custom-sidebar-text-400 hover:bg-custom-sidebar-background-90 rounded"
|
||||
onClick={() => setIsMenuActive(!isMenuActive)}
|
||||
>
|
||||
<MoreHorizontal className="size-4" />
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import type { TPartialProject } from "@/plane-web/types";
|
||||
// plane propel imports
|
||||
import { Logo } from "@plane/propel/emoji-icon-picker";
|
||||
import { ChevronDownIcon } from "@plane/propel/icons";
|
||||
import { Tooltip } from "@plane/propel/tooltip";
|
||||
|
||||
type TProjectHeaderButtonProps = {
|
||||
project: TPartialProject;
|
||||
};
|
||||
|
||||
export function ProjectHeaderButton({ project }: TProjectHeaderButtonProps) {
|
||||
return (
|
||||
<Tooltip tooltipContent={project.name} position="bottom">
|
||||
<div className="relative flex items-center text-left select-none w-full max-w-48 pr-1">
|
||||
<div className="size-7 rounded-md bg-custom-background-90 flex items-center justify-center flex-shrink-0">
|
||||
<Logo logo={project.logo_props} size={16} />
|
||||
</div>
|
||||
<div className="relative flex-1 min-w-0">
|
||||
<p className="truncate text-base font-medium text-custom-sidebar-text-200 px-2">{project.name}</p>
|
||||
<div className="absolute right-0 top-0 bottom-0 flex items-center justify-end pointer-events-none opacity-0 group-hover:opacity-100 transition-opacity duration-200">
|
||||
<div className="relative h-full w-8 flex items-center justify-end">
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-custom-background-90 to-custom-background-90 rounded-r" />
|
||||
<ChevronDownIcon className="relative z-10 size-4 text-custom-text-300" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
@@ -1,20 +1,107 @@
|
||||
import type { FC } from "react";
|
||||
// plane imports
|
||||
import { Logo } from "@plane/propel/emoji-icon-picker";
|
||||
import type { TLogoProps } from "@plane/types";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
// plane ui imports
|
||||
import type { ICustomSearchSelectOption } from "@plane/types";
|
||||
import { CustomSearchSelect } from "@plane/ui";
|
||||
// plane propel imports
|
||||
import { ProjectIcon } from "@plane/propel/icons";
|
||||
// hooks
|
||||
import { useAppRouter } from "@/hooks/use-app-router";
|
||||
import { useProject } from "@/hooks/store/use-project";
|
||||
import { useUserPermissions } from "@/hooks/store/user";
|
||||
import { useNavigationItems } from "@/plane-web/components/navigations";
|
||||
// local components
|
||||
import { SwitcherLabel } from "../common/switcher-label";
|
||||
import { ProjectHeaderButton } from "./project-header-button";
|
||||
// utils
|
||||
import { getTabUrl } from "./tab-navigation-utils";
|
||||
import { useTabPreferences } from "./use-tab-preferences";
|
||||
|
||||
type ProjectHeaderProps = {
|
||||
project: {
|
||||
name: string;
|
||||
logo_props: TLogoProps;
|
||||
};
|
||||
type TProjectHeaderProps = {
|
||||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
export const ProjectHeader: FC<ProjectHeaderProps> = ({ project }) => (
|
||||
<div className="flex items-center gap-1.5 text-left select-none w-full">
|
||||
<div className="size-7 rounded-md bg-custom-background-90 flex items-center justify-center flex-shrink-0">
|
||||
<Logo logo={project.logo_props} size={16} />
|
||||
</div>
|
||||
<p className="truncate text-base font-medium text-custom-sidebar-text-200 flex-shrink-0">{project.name}</p>
|
||||
</div>
|
||||
);
|
||||
export const ProjectHeader = observer((props: TProjectHeaderProps) => {
|
||||
const { workspaceSlug, projectId } = props;
|
||||
// router
|
||||
const router = useAppRouter();
|
||||
// store hooks
|
||||
const { joinedProjectIds, getPartialProjectById } = useProject();
|
||||
const { allowPermissions } = useUserPermissions();
|
||||
|
||||
// Get current project details
|
||||
const currentProjectDetails = getPartialProjectById(projectId);
|
||||
|
||||
// Get available navigation items for this project
|
||||
const navigationItems = useNavigationItems({
|
||||
workspaceSlug: workspaceSlug,
|
||||
projectId,
|
||||
project: currentProjectDetails,
|
||||
allowPermissions,
|
||||
});
|
||||
|
||||
// Get preferences from hook
|
||||
const { tabPreferences } = useTabPreferences(workspaceSlug, projectId);
|
||||
|
||||
// Memoize available tab keys
|
||||
const availableTabKeys = useMemo(() => navigationItems.map((item) => item.key), [navigationItems]);
|
||||
|
||||
// Memoize validated default tab key
|
||||
const validatedDefaultTabKey = useMemo(
|
||||
() =>
|
||||
availableTabKeys.includes(tabPreferences.defaultTab)
|
||||
? tabPreferences.defaultTab
|
||||
: availableTabKeys[0] || "work_items",
|
||||
[availableTabKeys, tabPreferences.defaultTab]
|
||||
);
|
||||
|
||||
// Memoize switcher options to prevent recalculation on every render
|
||||
const switcherOptions = useMemo<ICustomSearchSelectOption[]>(
|
||||
() =>
|
||||
joinedProjectIds
|
||||
.map((id): ICustomSearchSelectOption | null => {
|
||||
const project = getPartialProjectById(id);
|
||||
if (!project) return null;
|
||||
|
||||
return {
|
||||
value: id,
|
||||
query: project.name,
|
||||
content: (
|
||||
<SwitcherLabel
|
||||
name={project.name}
|
||||
logo_props={project.logo_props}
|
||||
LabelIcon={ProjectIcon}
|
||||
type="material"
|
||||
/>
|
||||
),
|
||||
};
|
||||
})
|
||||
.filter((option): option is ICustomSearchSelectOption => option !== null),
|
||||
[joinedProjectIds, getPartialProjectById]
|
||||
);
|
||||
|
||||
// Memoize onChange handler
|
||||
const handleProjectChange = useCallback(
|
||||
(value: string) => {
|
||||
if (value !== currentProjectDetails?.id) {
|
||||
router.push(getTabUrl(workspaceSlug, value, validatedDefaultTabKey));
|
||||
}
|
||||
},
|
||||
[currentProjectDetails?.id, router, workspaceSlug, validatedDefaultTabKey]
|
||||
);
|
||||
|
||||
// Early return if no project details
|
||||
if (!currentProjectDetails) return null;
|
||||
|
||||
return (
|
||||
<CustomSearchSelect
|
||||
options={switcherOptions}
|
||||
value={currentProjectDetails.id}
|
||||
onChange={handleProjectChange}
|
||||
customButton={currentProjectDetails ? <ProjectHeaderButton project={currentProjectDetails} /> : null}
|
||||
className="h-full rounded"
|
||||
customButtonClassName="group flex items-center gap-0.5 rounded hover:bg-custom-background-90 outline-none cursor-pointer h-full"
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -115,7 +115,7 @@ export const TabNavigationRoot: FC<TTabNavigationRootProps> = observer((props) =
|
||||
const hiddenNavigationItems = allNavigationItems.filter((item) => tabPreferences.hiddenTabs.includes(item.key));
|
||||
|
||||
// Responsive tab layout hook
|
||||
const { visibleItems, overflowItems, hasOverflow, containerRef, itemRefs } = useResponsiveTabLayout({
|
||||
const { visibleItems, overflowItems, hasOverflow, itemRefs, containerRef } = useResponsiveTabLayout({
|
||||
visibleNavigationItems,
|
||||
hiddenNavigationItems,
|
||||
isActive,
|
||||
@@ -169,7 +169,7 @@ export const TabNavigationRoot: FC<TTabNavigationRootProps> = observer((props) =
|
||||
{/* container for the tab navigation */}
|
||||
<div className="flex items-center gap-3 overflow-hidden size-full">
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
<ProjectHeader project={project} />
|
||||
<ProjectHeader workspaceSlug={workspaceSlug} projectId={projectId} />
|
||||
<div className="shrink-0">
|
||||
<ProjectActionsMenu
|
||||
workspaceSlug={workspaceSlug}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import type { TNavigationItem } from "./tab-navigation-root";
|
||||
|
||||
export type TResponsiveTabLayout = {
|
||||
visibleItems: TNavigationItem[];
|
||||
overflowItems: TNavigationItem[];
|
||||
hasOverflow: boolean;
|
||||
containerRef: React.RefObject<HTMLDivElement>;
|
||||
itemRefs: React.MutableRefObject<(HTMLDivElement | null)[]>;
|
||||
containerRef: (node: HTMLDivElement | null) => void;
|
||||
};
|
||||
|
||||
type UseResponsiveTabLayoutProps = {
|
||||
@@ -30,9 +30,9 @@ export const useResponsiveTabLayout = ({
|
||||
hiddenNavigationItems,
|
||||
isActive,
|
||||
}: UseResponsiveTabLayoutProps): TResponsiveTabLayout => {
|
||||
// Refs for measuring space and items
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
// Refs for measuring items
|
||||
const itemRefs = useRef<(HTMLDivElement | null)[]>([]);
|
||||
const resizeObserverRef = useRef<ResizeObserver | null>(null);
|
||||
|
||||
// State for responsive behavior
|
||||
const [containerWidth, setContainerWidth] = useState<number>(0);
|
||||
@@ -42,24 +42,44 @@ export const useResponsiveTabLayout = ({
|
||||
const gap = 4; // gap-1 = 4px
|
||||
const overflowButtonWidth = 40;
|
||||
|
||||
const container = containerRef?.current;
|
||||
// Callback ref that sets up ResizeObserver when element is attached
|
||||
const containerRef = useCallback((node: HTMLDivElement | null) => {
|
||||
// Clean up previous observer if it exists
|
||||
if (resizeObserverRef.current) {
|
||||
resizeObserverRef.current.disconnect();
|
||||
resizeObserverRef.current = null;
|
||||
}
|
||||
|
||||
// ResizeObserver to measure container width
|
||||
useEffect(() => {
|
||||
if (!container) return;
|
||||
// If node is null (unmounting), just clean up
|
||||
if (!node) {
|
||||
setContainerWidth(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Set initial width immediately
|
||||
setContainerWidth(node.offsetWidth);
|
||||
|
||||
// Create and set up new ResizeObserver
|
||||
const resizeObserver = new ResizeObserver((entries) => {
|
||||
for (const entry of entries) {
|
||||
setContainerWidth(entry.contentRect.width);
|
||||
}
|
||||
});
|
||||
|
||||
resizeObserver.observe(container);
|
||||
resizeObserverRef.current = resizeObserver;
|
||||
resizeObserver.observe(node);
|
||||
}, []); // Empty deps - callback function remains stable
|
||||
|
||||
return () => {
|
||||
resizeObserver.disconnect();
|
||||
};
|
||||
}, [container]);
|
||||
// Cleanup effect to disconnect observer on component unmount
|
||||
useEffect(
|
||||
() => () => {
|
||||
if (resizeObserverRef.current) {
|
||||
resizeObserverRef.current.disconnect();
|
||||
resizeObserverRef.current = null;
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
// Calculate how many items can fit
|
||||
useEffect(() => {
|
||||
@@ -137,7 +157,7 @@ export const useResponsiveTabLayout = ({
|
||||
visibleItems,
|
||||
overflowItems,
|
||||
hasOverflow,
|
||||
containerRef,
|
||||
itemRefs,
|
||||
containerRef,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -38,7 +38,7 @@ export const HelpMenuRoot = observer(function HelpMenuRoot() {
|
||||
<AppSidebarItem
|
||||
variant="button"
|
||||
item={{
|
||||
icon: <HelpCircle className="size-4" />,
|
||||
icon: <HelpCircle className="size-5" />,
|
||||
isActive: isNeedHelpOpen,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -69,8 +69,8 @@ export const SidebarProjectsListItem = observer(function SidebarProjectsListItem
|
||||
const { isMobile } = usePlatformOS();
|
||||
const { allowPermissions } = useUserPermissions();
|
||||
const { getIsProjectListOpen, toggleProjectListOpen } = useCommandPalette();
|
||||
const { toggleAnySidebarDropdown } = useAppTheme();
|
||||
const { preferences: projectPreferences } = useProjectNavigationPreferences();
|
||||
const { isExtendedProjectSidebarOpened, toggleExtendedProjectSidebar, toggleAnySidebarDropdown } = useAppTheme();
|
||||
|
||||
// states
|
||||
const [leaveProjectModalOpen, setLeaveProjectModal] = useState(false);
|
||||
@@ -259,6 +259,10 @@ export const SidebarProjectsListItem = observer(function SidebarProjectsListItem
|
||||
} else {
|
||||
router.push(defaultTabUrl);
|
||||
}
|
||||
// close the extended sidebar if it is open
|
||||
if (isExtendedProjectSidebarOpened) {
|
||||
toggleExtendedProjectSidebar(false);
|
||||
}
|
||||
};
|
||||
|
||||
const isAccordionMode = projectPreferences.navigationMode === "accordion";
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
"uuid": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@dotenvx/dotenvx": "catalog:",
|
||||
"@plane/eslint-config": "workspace:*",
|
||||
"@plane/tailwind-config": "workspace:*",
|
||||
"@plane/typescript-config": "workspace:*",
|
||||
@@ -86,7 +87,6 @@
|
||||
"@types/react": "catalog:",
|
||||
"@types/react-color": "^3.0.6",
|
||||
"@types/react-dom": "catalog:",
|
||||
"dotenv": "^16.4.5",
|
||||
"prettier": "^3.2.5",
|
||||
"typescript": "catalog:",
|
||||
"vite": "catalog:",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import path from "node:path";
|
||||
import * as dotenv from "@dotenvx/dotenvx";
|
||||
import { reactRouter } from "@react-router/dev/vite";
|
||||
import dotenv from "dotenv";
|
||||
import { defineConfig } from "vite";
|
||||
import tsconfigPaths from "vite-tsconfig-paths";
|
||||
|
||||
|
||||
+3
-1
@@ -24,6 +24,8 @@
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"express": "catalog:",
|
||||
"mdast-util-to-hast": "13.2.1",
|
||||
"valibot": "1.2.0",
|
||||
"glob": "11.1.0",
|
||||
"js-yaml": "4.1.1",
|
||||
@@ -48,7 +50,7 @@
|
||||
"unrs-resolver"
|
||||
]
|
||||
},
|
||||
"packageManager": "pnpm@10.21.0",
|
||||
"packageManager": "pnpm@10.24.0+sha512.01ff8ae71b4419903b65c60fb2dc9d34cf8bb6e06d03bde112ef38f7a34d6904c424ba66bea5cdcf12890230bf39f9580473140ed9c946fef328b6e5238a345a",
|
||||
"engines": {
|
||||
"node": ">=22.18.0"
|
||||
}
|
||||
|
||||
Generated
+40
-73
@@ -18,6 +18,9 @@ catalogs:
|
||||
'@bprogress/core':
|
||||
specifier: ^1.3.4
|
||||
version: 1.3.4
|
||||
'@dotenvx/dotenvx':
|
||||
specifier: 1.51.1
|
||||
version: 1.51.1
|
||||
'@react-router/dev':
|
||||
specifier: 7.9.5
|
||||
version: 7.9.5
|
||||
@@ -95,6 +98,8 @@ catalogs:
|
||||
version: 13.0.0
|
||||
|
||||
overrides:
|
||||
express: 4.22.0
|
||||
mdast-util-to-hast: 13.2.1
|
||||
valibot: 1.2.0
|
||||
glob: 11.1.0
|
||||
js-yaml: 4.1.1
|
||||
@@ -212,6 +217,9 @@ importers:
|
||||
specifier: 'catalog:'
|
||||
version: 13.0.0
|
||||
devDependencies:
|
||||
'@dotenvx/dotenvx':
|
||||
specifier: 'catalog:'
|
||||
version: 1.51.1
|
||||
'@plane/eslint-config':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/eslint-config
|
||||
@@ -239,9 +247,6 @@ importers:
|
||||
'@types/react-dom':
|
||||
specifier: 'catalog:'
|
||||
version: 18.3.1
|
||||
dotenv:
|
||||
specifier: ^16.4.5
|
||||
version: 16.6.1
|
||||
typescript:
|
||||
specifier: 5.8.3
|
||||
version: 5.8.3
|
||||
@@ -255,8 +260,8 @@ importers:
|
||||
apps/live:
|
||||
dependencies:
|
||||
'@dotenvx/dotenvx':
|
||||
specifier: ^1.49.0
|
||||
version: 1.49.0
|
||||
specifier: 'catalog:'
|
||||
version: 1.51.1
|
||||
'@hocuspocus/extension-database':
|
||||
specifier: 2.15.2
|
||||
version: 2.15.2(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27)
|
||||
@@ -305,15 +310,12 @@ importers:
|
||||
cors:
|
||||
specifier: ^2.8.5
|
||||
version: 2.8.5
|
||||
dotenv:
|
||||
specifier: ^16.4.5
|
||||
version: 16.6.1
|
||||
express:
|
||||
specifier: ^4.21.2
|
||||
version: 4.21.2
|
||||
specifier: 4.22.0
|
||||
version: 4.22.0
|
||||
express-ws:
|
||||
specifier: ^5.0.2
|
||||
version: 5.0.2(express@4.21.2)
|
||||
version: 5.0.2(express@4.22.0)
|
||||
helmet:
|
||||
specifier: ^7.1.0
|
||||
version: 7.2.0
|
||||
@@ -475,6 +477,9 @@ importers:
|
||||
specifier: 'catalog:'
|
||||
version: 13.0.0
|
||||
devDependencies:
|
||||
'@dotenvx/dotenvx':
|
||||
specifier: 'catalog:'
|
||||
version: 1.51.1
|
||||
'@plane/eslint-config':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/eslint-config
|
||||
@@ -502,9 +507,6 @@ importers:
|
||||
'@types/react-dom':
|
||||
specifier: 'catalog:'
|
||||
version: 18.3.1
|
||||
dotenv:
|
||||
specifier: ^16.4.5
|
||||
version: 16.6.1
|
||||
typescript:
|
||||
specifier: 5.8.3
|
||||
version: 5.8.3
|
||||
@@ -689,6 +691,9 @@ importers:
|
||||
specifier: 'catalog:'
|
||||
version: 13.0.0
|
||||
devDependencies:
|
||||
'@dotenvx/dotenvx':
|
||||
specifier: 'catalog:'
|
||||
version: 1.51.1
|
||||
'@plane/eslint-config':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/eslint-config
|
||||
@@ -719,9 +724,6 @@ importers:
|
||||
'@types/react-dom':
|
||||
specifier: 'catalog:'
|
||||
version: 18.3.1
|
||||
dotenv:
|
||||
specifier: ^16.4.5
|
||||
version: 16.6.1
|
||||
prettier:
|
||||
specifier: ^3.2.5
|
||||
version: 3.6.2
|
||||
@@ -1861,8 +1863,8 @@ packages:
|
||||
'@date-fns/tz@1.4.1':
|
||||
resolution: {integrity: sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==}
|
||||
|
||||
'@dotenvx/dotenvx@1.49.0':
|
||||
resolution: {integrity: sha512-M1cyP6YstFQCjih54SAxCqHLMMi8QqV8tenpgGE48RTXWD7vfMYJiw/6xcCDpS2h28AcLpTsFCZA863Ge9yxzA==}
|
||||
'@dotenvx/dotenvx@1.51.1':
|
||||
resolution: {integrity: sha512-fqcQxcxC4LOaUlW8IkyWw8x0yirlLUkbxohz9OnWvVWjf73J5yyw7jxWnkOJaUKXZotcGEScDox9MU6rSkcDgg==}
|
||||
hasBin: true
|
||||
|
||||
'@ecies/ciphers@0.2.4':
|
||||
@@ -2921,7 +2923,7 @@ packages:
|
||||
resolution: {integrity: sha512-Mg94Tw9JSaRuwkvIC6PaODRzsLs6mo70ppz5qdIK/G3iotSxsH08TDNdzot7CaXXevk/pIiD/+Tbn0H/asHsYA==}
|
||||
engines: {node: '>=20.0.0'}
|
||||
peerDependencies:
|
||||
express: ^4.17.1 || ^5
|
||||
express: 4.22.0
|
||||
react-router: 7.9.5
|
||||
typescript: 5.8.3
|
||||
peerDependenciesMeta:
|
||||
@@ -5694,10 +5696,10 @@ packages:
|
||||
resolution: {integrity: sha512-0uvmuk61O9HXgLhGl3QhNSEtRsQevtmbL94/eILaliEADZBHZOQUAiHFrGPrgsjikohyrmSG5g+sCfASTt0lkQ==}
|
||||
engines: {node: '>=4.5.0'}
|
||||
peerDependencies:
|
||||
express: ^4.0.0 || ^5.0.0-alpha.1
|
||||
express: 4.22.0
|
||||
|
||||
express@4.21.2:
|
||||
resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==}
|
||||
express@4.22.0:
|
||||
resolution: {integrity: sha512-c2iPh3xp5vvCLgaHK03+mWLFPhox7j1LwyxcZwFVApEv5i0X+IjPpbT50SJJwwLpdBVfp45AkK/v+AFgv/XlfQ==}
|
||||
engines: {node: '>= 0.10.0'}
|
||||
|
||||
extend@3.0.2:
|
||||
@@ -6666,9 +6668,6 @@ packages:
|
||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
mdast-util-definitions@5.1.2:
|
||||
resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==}
|
||||
|
||||
mdast-util-find-and-replace@3.0.2:
|
||||
resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
|
||||
|
||||
@@ -6699,11 +6698,8 @@ packages:
|
||||
mdast-util-phrasing@4.1.0:
|
||||
resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
|
||||
|
||||
mdast-util-to-hast@12.3.0:
|
||||
resolution: {integrity: sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==}
|
||||
|
||||
mdast-util-to-hast@13.2.0:
|
||||
resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==}
|
||||
mdast-util-to-hast@13.2.1:
|
||||
resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}
|
||||
|
||||
mdast-util-to-markdown@2.1.2:
|
||||
resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
|
||||
@@ -8720,18 +8716,12 @@ packages:
|
||||
unist-util-find-after@5.0.0:
|
||||
resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==}
|
||||
|
||||
unist-util-generated@2.0.1:
|
||||
resolution: {integrity: sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==}
|
||||
|
||||
unist-util-is@5.2.1:
|
||||
resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==}
|
||||
|
||||
unist-util-is@6.0.0:
|
||||
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
|
||||
|
||||
unist-util-position@4.0.4:
|
||||
resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==}
|
||||
|
||||
unist-util-position@5.0.0:
|
||||
resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
|
||||
|
||||
@@ -9575,7 +9565,7 @@ snapshots:
|
||||
|
||||
'@date-fns/tz@1.4.1': {}
|
||||
|
||||
'@dotenvx/dotenvx@1.49.0':
|
||||
'@dotenvx/dotenvx@1.51.1':
|
||||
dependencies:
|
||||
commander: 11.1.0
|
||||
dotenv: 17.2.1
|
||||
@@ -10715,10 +10705,10 @@ snapshots:
|
||||
- tsx
|
||||
- yaml
|
||||
|
||||
'@react-router/express@7.9.5(express@4.21.2)(react-router@7.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.8.3)':
|
||||
'@react-router/express@7.9.5(express@4.22.0)(react-router@7.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@react-router/node': 7.9.5(react-router@7.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.8.3)
|
||||
express: 4.21.2
|
||||
express: 4.22.0
|
||||
react-router: 7.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
optionalDependencies:
|
||||
typescript: 5.8.3
|
||||
@@ -10733,10 +10723,10 @@ snapshots:
|
||||
'@react-router/serve@7.9.5(react-router@7.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@mjackson/node-fetch-server': 0.2.0
|
||||
'@react-router/express': 7.9.5(express@4.21.2)(react-router@7.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.8.3)
|
||||
'@react-router/express': 7.9.5(express@4.22.0)(react-router@7.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.8.3)
|
||||
'@react-router/node': 7.9.5(react-router@7.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(typescript@5.8.3)
|
||||
compression: 1.8.1
|
||||
express: 4.21.2
|
||||
express: 4.22.0
|
||||
get-port: 5.1.1
|
||||
morgan: 1.10.1
|
||||
react-router: 7.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
@@ -13857,15 +13847,15 @@ snapshots:
|
||||
lodash: 4.17.21
|
||||
winston: 3.17.0
|
||||
|
||||
express-ws@5.0.2(express@4.21.2):
|
||||
express-ws@5.0.2(express@4.22.0):
|
||||
dependencies:
|
||||
express: 4.21.2
|
||||
express: 4.22.0
|
||||
ws: 7.5.10
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
||||
express@4.21.2:
|
||||
express@4.22.0:
|
||||
dependencies:
|
||||
accepts: 1.3.8
|
||||
array-flatten: 1.1.1
|
||||
@@ -13888,7 +13878,7 @@ snapshots:
|
||||
parseurl: 1.3.3
|
||||
path-to-regexp: 0.1.12
|
||||
proxy-addr: 2.0.7
|
||||
qs: 6.13.0
|
||||
qs: 6.14.0
|
||||
range-parser: 1.2.1
|
||||
safe-buffer: 5.2.1
|
||||
send: 0.19.0
|
||||
@@ -14292,7 +14282,7 @@ snapshots:
|
||||
comma-separated-tokens: 2.0.3
|
||||
hast-util-whitespace: 3.0.0
|
||||
html-void-elements: 3.0.0
|
||||
mdast-util-to-hast: 13.2.0
|
||||
mdast-util-to-hast: 13.2.1
|
||||
property-information: 7.1.0
|
||||
space-separated-tokens: 2.0.2
|
||||
stringify-entities: 4.0.4
|
||||
@@ -14308,7 +14298,7 @@ snapshots:
|
||||
hast-util-to-text: 4.0.2
|
||||
hast-util-whitespace: 3.0.0
|
||||
mdast-util-phrasing: 4.1.0
|
||||
mdast-util-to-hast: 13.2.0
|
||||
mdast-util-to-hast: 13.2.1
|
||||
mdast-util-to-string: 4.0.0
|
||||
rehype-minify-whitespace: 6.0.2
|
||||
trim-trailing-lines: 2.1.0
|
||||
@@ -14936,12 +14926,6 @@ snapshots:
|
||||
|
||||
math-intrinsics@1.1.0: {}
|
||||
|
||||
mdast-util-definitions@5.1.2:
|
||||
dependencies:
|
||||
'@types/mdast': 3.0.15
|
||||
'@types/unist': 2.0.11
|
||||
unist-util-visit: 4.1.2
|
||||
|
||||
mdast-util-find-and-replace@3.0.2:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
@@ -15045,18 +15029,7 @@ snapshots:
|
||||
'@types/mdast': 4.0.4
|
||||
unist-util-is: 6.0.0
|
||||
|
||||
mdast-util-to-hast@12.3.0:
|
||||
dependencies:
|
||||
'@types/hast': 2.3.10
|
||||
'@types/mdast': 3.0.15
|
||||
mdast-util-definitions: 5.1.2
|
||||
micromark-util-sanitize-uri: 1.2.0
|
||||
trim-lines: 3.0.1
|
||||
unist-util-generated: 2.0.1
|
||||
unist-util-position: 4.0.4
|
||||
unist-util-visit: 4.1.2
|
||||
|
||||
mdast-util-to-hast@13.2.0:
|
||||
mdast-util-to-hast@13.2.1:
|
||||
dependencies:
|
||||
'@types/hast': 3.0.4
|
||||
'@types/mdast': 4.0.4
|
||||
@@ -16586,7 +16559,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/hast': 2.3.10
|
||||
'@types/mdast': 3.0.15
|
||||
mdast-util-to-hast: 12.3.0
|
||||
mdast-util-to-hast: 13.2.1
|
||||
unified: 10.1.2
|
||||
|
||||
remark-stringify@11.0.0:
|
||||
@@ -17480,8 +17453,6 @@ snapshots:
|
||||
'@types/unist': 3.0.3
|
||||
unist-util-is: 6.0.0
|
||||
|
||||
unist-util-generated@2.0.1: {}
|
||||
|
||||
unist-util-is@5.2.1:
|
||||
dependencies:
|
||||
'@types/unist': 2.0.11
|
||||
@@ -17490,10 +17461,6 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
unist-util-position@4.0.4:
|
||||
dependencies:
|
||||
'@types/unist': 2.0.11
|
||||
|
||||
unist-util-position@5.0.0:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
@@ -9,6 +9,7 @@ catalog:
|
||||
"@atlaskit/pragmatic-drag-and-drop-hitbox": 1.1.0
|
||||
"@atlaskit/pragmatic-drag-and-drop": 1.7.4
|
||||
"@bprogress/core": ^1.3.4
|
||||
"@dotenvx/dotenvx": 1.51.1
|
||||
"@react-router/dev": 7.9.5
|
||||
"@react-router/node": 7.9.5
|
||||
"@react-router/serve": 7.9.5
|
||||
@@ -22,6 +23,7 @@ catalog:
|
||||
"@types/react-dom": 18.3.1
|
||||
"@types/react": 18.3.11
|
||||
axios: 1.12.0
|
||||
express: 4.22.0
|
||||
lodash-es: 4.17.21
|
||||
lucide-react: 0.469.0
|
||||
mobx-react: 9.1.1
|
||||
|
||||
Reference in New Issue
Block a user