Skip to content

Commit

Permalink
refactor: move add desktop layout into
Browse files Browse the repository at this point in the history
  • Loading branch information
moonrailgun committed Apr 7, 2024
1 parent 6fbf316 commit 0711c3c
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 158 deletions.
162 changes: 162 additions & 0 deletions src/client/pages/Layout/DesktopLayout.tsx
@@ -0,0 +1,162 @@
import * as React from 'react';
import {
LuAreaChart,
LuFilePieChart,
LuMonitorDot,
LuServer,
LuWifi,
} from 'react-icons/lu';
import { TooltipProvider } from '@/components/ui/tooltip';
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from '@/components/ui/resizable';
import { useLocalStorageState } from 'ahooks';
import { cn } from '@/utils/style';
import { Separator } from '@/components/ui/separator';
import { Nav } from './Nav';
import { WorkspaceSwitcher } from '@/components/WorkspaceSwitcher';
import { UserConfig } from './UserConfig';
import { Outlet } from '@tanstack/react-router';
import { trpc } from '@/api/trpc';
import { useUserStore } from '@/store/user';
import { LayoutProps } from './types';

const defaultLayout: [number, number, number] = [265, 440, 655];

export const DesktopLayout: React.FC<LayoutProps> = React.memo((props) => {
const [layout = defaultLayout, setLayout] = useLocalStorageState(
'react-resizable-panels:layout',
{ defaultValue: defaultLayout }
);
const [isCollapsed = false, setIsCollapsed] = useLocalStorageState<boolean>(
'react-resizable-panels:collapsed',
{
defaultValue: false,
}
);
const workspaceId = useUserStore((state) => state.info?.currentWorkspace?.id);
const { data: serviceCount } = trpc.workspace.getServiceCount.useQuery(
{
workspaceId: workspaceId!,
},
{
enabled: !!workspaceId,
}
);

const navbar = (
<>
<div
className={cn(
'flex h-[52px] items-center justify-center',
isCollapsed ? 'h-[52px]' : 'px-2'
)}
>
<WorkspaceSwitcher isCollapsed={isCollapsed} />
</div>
<Separator />
<Nav
isCollapsed={isCollapsed}
links={[
{
title: 'Website',
label: String(serviceCount?.website ?? ''),
icon: LuAreaChart,
to: '/website',
},
{
title: 'Monitor',
label: String(serviceCount?.monitor ?? ''),
icon: LuMonitorDot,
to: '/monitor',
},
{
title: 'Servers',
label: '',
icon: LuServer,
to: '/server',
},
{
title: 'Telemetry',
label: String(serviceCount?.telemetry ?? ''),
icon: LuWifi,
to: '/telemetry',
},
{
title: 'Pages',
label: String(serviceCount?.page ?? ''),
icon: LuFilePieChart,
to: '/page',
},
]}
/>
<Separator />
<div className="flex-1" />
<Separator />

<div className={cn(isCollapsed && 'm-auto')}>
<UserConfig isCollapsed={isCollapsed} />
</div>
</>
);

return (
<TooltipProvider delayDuration={0}>
<ResizablePanelGroup
direction="horizontal"
onLayout={(sizes: number[]) => {
if (sizes.length === 3) {
setLayout(sizes as typeof defaultLayout);
} else if (sizes.length === 2) {
const listSize = layout[1];
const rest = 100 - sizes[0] - listSize;
setLayout([sizes[0], listSize, rest]);
}
}}
className="h-full items-stretch"
>
<ResizablePanel
defaultSize={layout[0]}
collapsedSize={1}
collapsible={true}
minSize={10}
maxSize={20}
onCollapse={() => {
setIsCollapsed(true);
}}
onExpand={() => {
setIsCollapsed(false);
}}
className={cn(
'flex flex-col',
isCollapsed &&
'min-w-[50px] transition-all duration-300 ease-in-out'
)}
>
{navbar}
</ResizablePanel>

{props.list && (
<>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={layout[1]} minSize={25}>
<div className="h-full overflow-hidden">{props.list}</div>
</ResizablePanel>
</>
)}

<ResizableHandle withHandle />
<ResizablePanel
defaultSize={props.list ? layout[2] : layout[1] + layout[2]}
>
<div className="h-full overflow-hidden">
{props.children ?? <Outlet />}
</div>
</ResizablePanel>
</ResizablePanelGroup>
</TooltipProvider>
);
});
DesktopLayout.displayName = 'DesktopLayout';
6 changes: 6 additions & 0 deletions src/client/pages/Layout/MobileLayout.tsx
@@ -0,0 +1,6 @@
import React from 'react';

export const MobileLayout: React.FC = React.memo(() => {
return <div>Mobile</div>;
});
MobileLayout.displayName = 'MobileLayout';
1 change: 0 additions & 1 deletion src/client/pages/Layout/UserConfig.tsx
@@ -1,4 +1,3 @@
import { ColorSchemeSwitcher } from '@/components/ColorSchemeSwitcher';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import {
Expand Down
3 changes: 3 additions & 0 deletions src/client/pages/Layout/types.ts
@@ -0,0 +1,3 @@
export interface LayoutProps extends React.PropsWithChildren {
list?: React.ReactNode;
}
166 changes: 9 additions & 157 deletions src/client/pages/LayoutV2.tsx
@@ -1,164 +1,16 @@
import * as React from 'react';
import {
LuAreaChart,
LuFilePieChart,
LuMonitorDot,
LuServer,
LuWifi,
} from 'react-icons/lu';
import { TooltipProvider } from '@/components/ui/tooltip';
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from '@/components/ui/resizable';
import { useLocalStorageState } from 'ahooks';
import { cn } from '@/utils/style';
import { Separator } from '@/components/ui/separator';
import { Nav } from './Layout/Nav';
import { WorkspaceSwitcher } from '@/components/WorkspaceSwitcher';
import { UserConfig } from './Layout/UserConfig';
import { Outlet } from '@tanstack/react-router';
import { trpc } from '@/api/trpc';
import { useUserStore } from '@/store/user';
import { DesktopLayout } from './Layout/DesktopLayout';
import { LayoutProps } from './Layout/types';
import { useIsMobile } from '@/hooks/useIsMobile';
import { MobileLayout } from './Layout/MobileLayout';

const defaultLayout: [number, number, number] = [265, 440, 655];

interface LayoutProps extends React.PropsWithChildren {
list?: React.ReactNode;
}
export const LayoutV2: React.FC<LayoutProps> = React.memo((props) => {
const [layout = defaultLayout, setLayout] = useLocalStorageState(
'react-resizable-panels:layout',
{ defaultValue: defaultLayout }
);
const [isCollapsed = false, setIsCollapsed] = useLocalStorageState<boolean>(
'react-resizable-panels:collapsed',
{
defaultValue: false,
}
);
const workspaceId = useUserStore((state) => state.info?.currentWorkspace?.id);
const { data: serviceCount } = trpc.workspace.getServiceCount.useQuery(
{
workspaceId: workspaceId!,
},
{
enabled: !!workspaceId,
}
);

const navbar = (
<>
<div
className={cn(
'flex h-[52px] items-center justify-center',
isCollapsed ? 'h-[52px]' : 'px-2'
)}
>
<WorkspaceSwitcher isCollapsed={isCollapsed} />
</div>
<Separator />
<Nav
isCollapsed={isCollapsed}
links={[
{
title: 'Website',
label: String(serviceCount?.website ?? ''),
icon: LuAreaChart,
to: '/website',
},
{
title: 'Monitor',
label: String(serviceCount?.monitor ?? ''),
icon: LuMonitorDot,
to: '/monitor',
},
{
title: 'Servers',
label: '',
icon: LuServer,
to: '/server',
},
{
title: 'Telemetry',
label: String(serviceCount?.telemetry ?? ''),
icon: LuWifi,
to: '/telemetry',
},
{
title: 'Pages',
label: String(serviceCount?.page ?? ''),
icon: LuFilePieChart,
to: '/page',
},
]}
/>
<Separator />
<div className="flex-1" />
<Separator />

<div className={cn(isCollapsed && 'm-auto')}>
<UserConfig isCollapsed={isCollapsed} />
</div>
</>
);

return (
<TooltipProvider delayDuration={0}>
<ResizablePanelGroup
direction="horizontal"
onLayout={(sizes: number[]) => {
if (sizes.length === 3) {
setLayout(sizes as typeof defaultLayout);
} else if (sizes.length === 2) {
const listSize = layout[1];
const rest = 100 - sizes[0] - listSize;
setLayout([sizes[0], listSize, rest]);
}
}}
className="h-full items-stretch"
>
<ResizablePanel
defaultSize={layout[0]}
collapsedSize={1}
collapsible={true}
minSize={10}
maxSize={20}
onCollapse={() => {
setIsCollapsed(true);
}}
onExpand={() => {
setIsCollapsed(false);
}}
className={cn(
'flex flex-col',
isCollapsed &&
'min-w-[50px] transition-all duration-300 ease-in-out'
)}
>
{navbar}
</ResizablePanel>
const isMobile = useIsMobile();

{props.list && (
<>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={layout[1]} minSize={25}>
<div className="h-full overflow-hidden">{props.list}</div>
</ResizablePanel>
</>
)}
if (isMobile) {
return <MobileLayout />;
}

<ResizableHandle withHandle />
<ResizablePanel
defaultSize={props.list ? layout[2] : layout[1] + layout[2]}
>
<div className="h-full overflow-hidden">
{props.children ?? <Outlet />}
</div>
</ResizablePanel>
</ResizablePanelGroup>
</TooltipProvider>
);
return <DesktopLayout {...props} />;
});
LayoutV2.displayName = 'LayoutV2';

0 comments on commit 0711c3c

Please sign in to comment.