more cards
This commit is contained in:
parent
e05f143812
commit
b01a38ecc9
17 changed files with 530 additions and 92 deletions
|
|
@ -17,7 +17,6 @@ function DashboardList({ history, siteId }: { history: any; siteId: string }) {
|
|||
const { dashboardStore } = useStore();
|
||||
const list = dashboardStore.filteredList;
|
||||
const dashboardsSearch = dashboardStore.filter.query;
|
||||
const lenth = list.length;
|
||||
|
||||
|
||||
const tableConfig: TableColumnsType<Dashboard> = [
|
||||
|
|
@ -72,7 +71,7 @@ function DashboardList({ history, siteId }: { history: any; siteId: string }) {
|
|||
];
|
||||
return (
|
||||
<NoContent
|
||||
show={lenth === 0}
|
||||
show={list.length === 0 && !dashboardStore.filter.showMine}
|
||||
title={
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<AnimatedSVG name={ICONS.NO_DASHBOARDS} size={180} />
|
||||
|
|
|
|||
|
|
@ -1,25 +1,41 @@
|
|||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Button } from 'antd';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import React from 'react';
|
||||
import { PageTitle } from 'UI';
|
||||
import DashboardSearch from './DashboardSearch';
|
||||
|
||||
import { useStore } from 'App/mstore';
|
||||
import { observer, useObserver } from 'mobx-react-lite';
|
||||
import { withSiteId } from 'App/routes';
|
||||
import { Button } from 'antd'
|
||||
import { PlusOutlined } from "@ant-design/icons";
|
||||
import { PageTitle } from 'UI';
|
||||
|
||||
import DashboardSearch from './DashboardSearch';
|
||||
import NewDashboardModal from './NewDashModal';
|
||||
|
||||
function Header({ history, siteId }: { history: any; siteId: string }) {
|
||||
const [showModal, setShowModal] = React.useState(false);
|
||||
const { dashboardStore } = useStore();
|
||||
const sort = useObserver(() => dashboardStore.sort);
|
||||
|
||||
const onSaveDashboard = () => {
|
||||
dashboardStore.initDashboard();
|
||||
dashboardStore
|
||||
.save(dashboardStore.dashboardInstance)
|
||||
.then(async (syncedDashboard) => {
|
||||
dashboardStore.selectDashboardById(syncedDashboard.dashboardId);
|
||||
history.push(
|
||||
withSiteId(`/dashboard/${syncedDashboard.dashboardId}`, siteId)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const onAddDashboardClick = () => {
|
||||
dashboardStore.initDashboard();
|
||||
dashboardStore.save(dashboardStore.dashboardInstance).then(async (syncedDashboard) => {
|
||||
dashboardStore.selectDashboardById(syncedDashboard.dashboardId);
|
||||
history.push(withSiteId(`/dashboard/${syncedDashboard.dashboardId}`, siteId));
|
||||
});
|
||||
setShowModal(true);
|
||||
};
|
||||
|
||||
const onClose = () => {
|
||||
setShowModal(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex items-center justify-between px-4 pb-2">
|
||||
<div className="flex items-baseline mr-3">
|
||||
<PageTitle title="Dashboards" />
|
||||
|
|
@ -27,7 +43,9 @@ function Header({ history, siteId }: { history: any; siteId: string }) {
|
|||
<div className="ml-auto flex items-center">
|
||||
<Button
|
||||
icon={<PlusOutlined />}
|
||||
type="primary" onClick={onAddDashboardClick}>
|
||||
type="primary"
|
||||
onClick={onAddDashboardClick}
|
||||
>
|
||||
Create Dashboard
|
||||
</Button>
|
||||
<div className="mx-2"></div>
|
||||
|
|
@ -35,17 +53,9 @@ function Header({ history, siteId }: { history: any; siteId: string }) {
|
|||
<DashboardSearch />
|
||||
</div>
|
||||
</div>
|
||||
{/*<Select*/}
|
||||
{/* options={[*/}
|
||||
{/* { label: 'Newest', value: 'desc' },*/}
|
||||
{/* { label: 'Oldest', value: 'asc' },*/}
|
||||
{/* ]}*/}
|
||||
{/* defaultValue={sort.by}*/}
|
||||
{/* plain*/}
|
||||
{/* onChange={({ value }) => dashboardStore.updateKey('sort', { by: value.value })}*/}
|
||||
{/*/>*/}
|
||||
</div>
|
||||
|
||||
<NewDashboardModal onClose={onClose} open={showModal} onSave={onSaveDashboard} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,143 @@
|
|||
import { Angry, ArrowDownUp, Mouse, MousePointerClick, Unlink } from 'lucide-react';
|
||||
import React from 'react';
|
||||
|
||||
|
||||
|
||||
import ExCard from './ExCard';
|
||||
|
||||
|
||||
function ExampleCount() {
|
||||
return <ExCard title={'Sessions by'}>
|
||||
<Frustrations />
|
||||
</ExCard>;
|
||||
}
|
||||
|
||||
function Frustrations() {
|
||||
const rows = [
|
||||
{
|
||||
label: 'Rage Clicks',
|
||||
progress: 25,
|
||||
value: 100,
|
||||
icon: <Angry size={12} strokeWidth={1} />,
|
||||
},
|
||||
{
|
||||
label: 'Dead Clicks',
|
||||
progress: 75,
|
||||
value: 75,
|
||||
icon: <MousePointerClick size={12} strokeWidth={1} />,
|
||||
},
|
||||
{
|
||||
label: '4XX Pages',
|
||||
progress: 50,
|
||||
value: 50,
|
||||
icon: <Unlink size={12} strokeWidth={1} />,
|
||||
},
|
||||
{
|
||||
label: 'Mouse Trashing',
|
||||
progress: 10,
|
||||
value: 25,
|
||||
icon: <Mouse size={12} strokeWidth={1} />,
|
||||
},
|
||||
{
|
||||
label: 'Excessive Scrolling',
|
||||
progress: 10,
|
||||
value: 10,
|
||||
icon: <ArrowDownUp size={12} strokeWidth={1} />,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className={'flex gap-2 flex-col'}>
|
||||
{rows.map((r) => (
|
||||
<div
|
||||
className={
|
||||
'flex items-center gap-2 border-b border-dotted last:border-0 py-2 first:pt-0 last:pb-0'
|
||||
}
|
||||
>
|
||||
<Circle badgeType={0}>{r.icon}</Circle>
|
||||
<div>{r.label}</div>
|
||||
<div style={{ marginLeft: 'auto', marginRight: 20, display: 'flex' }}>
|
||||
<div
|
||||
style={{
|
||||
height: 2,
|
||||
width: 140 * (0.01 * r.progress),
|
||||
background: '#394EFF',
|
||||
}}
|
||||
className={'rounded-l'}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
height: 2,
|
||||
width: 140-(140 * (0.01 * r.progress)),
|
||||
background: '#E2E4F6',
|
||||
}}
|
||||
className={'rounded-r'}
|
||||
/>
|
||||
</div>
|
||||
<div className={'min-w-8'}>{r.value}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Errors() {
|
||||
const rows = [
|
||||
{
|
||||
label: 'HTTP response status code (404 Not Found)',
|
||||
value: 500,
|
||||
progress: 90,
|
||||
icon: <div className={'text-red text-xs'}>4XX</div>,
|
||||
},
|
||||
{
|
||||
label: 'Cross-origin request blocked',
|
||||
value: 300,
|
||||
progress: 60,
|
||||
icon: <div className={'text-red text-xs'}>CROS</div>,
|
||||
},
|
||||
{
|
||||
label: 'Reference error',
|
||||
value: 200,
|
||||
progress: 40,
|
||||
icon: <div className={'text-red text-xs'}>RE</div>,
|
||||
},
|
||||
{
|
||||
label: 'Unhandled Promise Rejection',
|
||||
value: 50,
|
||||
progress: 20,
|
||||
icon: <div className={'text-red text-xs'}>NULL</div>,
|
||||
},
|
||||
{
|
||||
label: 'Failed Network Request',
|
||||
value: 10,
|
||||
progress: 5,
|
||||
icon: <div className={'text-red text-xs'}>XHR</div>,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function Circle({
|
||||
children,
|
||||
badgeType,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
badgeType: 0 | 1 | 2;
|
||||
}) {
|
||||
const colors = {
|
||||
0: '#FFFBE6',
|
||||
1: '#FFF1F0',
|
||||
2: '#EBF4F5',
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={'p-2 rounded-full'}
|
||||
style={{ background: colors[badgeType] }}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default ExampleCount
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
import React from 'react'
|
||||
|
||||
function ExCard({
|
||||
title,
|
||||
children,
|
||||
}: {
|
||||
title: React.ReactNode;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={'rounded overflow-hidden border p-4 bg-white'}
|
||||
style={{ width: 400, height: 286 }}
|
||||
>
|
||||
<div className={'font-semibold text-lg'}>{title}</div>
|
||||
<div className={'flex flex-col gap-2 mt-2'}>{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExCard
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import { ArrowRight } from 'lucide-react';
|
||||
import React from 'react';
|
||||
|
||||
import ExCard from './ExCard';
|
||||
|
||||
function ExampleFunnel() {
|
||||
const steps = [
|
||||
{
|
||||
progress: 500,
|
||||
},
|
||||
{
|
||||
progress: 250,
|
||||
},
|
||||
{
|
||||
progress: 100,
|
||||
},
|
||||
];
|
||||
return (
|
||||
<ExCard title={'Funnel'}>
|
||||
<>
|
||||
{steps.map((step, index) => (
|
||||
<div key={index}>
|
||||
<div>Step {index + 1}</div>
|
||||
<div className={'rounded flex items-center w-full overflow-hidden'}>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: step.progress <= 100 ? '#394EFF' : '#E2E4F6',
|
||||
width: `${(step.progress / 500) * 100}%`,
|
||||
height: 30,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
style={{
|
||||
width: `${((500 - step.progress) / 500) * 100}%`,
|
||||
height: 30,
|
||||
background: '#FFF1F0',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={'flex items-center gap-2'}>
|
||||
<ArrowRight size={14} color={'#8C8C8C'} strokeWidth={1} />
|
||||
<div className={'text-disabled-text'}>{step.progress}</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
</ExCard>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExampleFunnel;
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import React from 'react';
|
||||
import { ResponsiveContainer, Sankey } from 'recharts';
|
||||
|
||||
import CustomLink from 'App/components/shared/Insights/SankeyChart/CustomLink';
|
||||
import CustomNode from 'App/components/shared/Insights/SankeyChart/CustomNode';
|
||||
|
||||
import ExCard from './ExCard';
|
||||
|
||||
function ExamplePath() {
|
||||
const data = {
|
||||
nodes: [
|
||||
{ idd: 0, name: 'Home' },
|
||||
{ idd: 1, name: 'Google' },
|
||||
{ idd: 2, name: 'Facebook' },
|
||||
{ idd: 3, name: 'Search' },
|
||||
{ idd: 4, name: 'Product' },
|
||||
{ idd: 5, name: 'Chart' },
|
||||
],
|
||||
links: [
|
||||
{ source: 0, target: 3, value: 40 },
|
||||
{ source: 0, target: 4, value: 60 },
|
||||
|
||||
{ source: 1, target: 3, value: 100 },
|
||||
{ source: 2, target: 3, value: 100 },
|
||||
|
||||
{ source: 3, target: 4, value: 50 },
|
||||
{ source: 3, target: 5, value: 50 },
|
||||
|
||||
{ source: 4, target: 5, value: 15 },
|
||||
],
|
||||
};
|
||||
return (
|
||||
<ExCard title={'Path Finder'}>
|
||||
<ResponsiveContainer width={'100%'} height={230}>
|
||||
<Sankey
|
||||
nodeWidth={6}
|
||||
sort={false}
|
||||
iterations={128}
|
||||
node={<CustomNode isDemo />}
|
||||
link={(linkProps) => <CustomLink {...linkProps} />}
|
||||
data={data}
|
||||
>
|
||||
<defs>
|
||||
<linearGradient id={'linkGradient'}>
|
||||
<stop offset="0%" stopColor="rgba(57, 78, 255, 0.2)" />
|
||||
<stop offset="100%" stopColor="rgba(57, 78, 255, 0.2)" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</Sankey>
|
||||
</ResponsiveContainer>
|
||||
</ExCard>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExamplePath
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
import { Segmented } from 'antd';
|
||||
import React from 'react';
|
||||
|
||||
import ExCard from './ExCard';
|
||||
|
||||
function ExampleTrend() {
|
||||
const rows = [50, 40, 30, 20, 10];
|
||||
const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May'];
|
||||
|
||||
const [isMulti, setIsMulti] = React.useState(false);
|
||||
return (
|
||||
<ExCard
|
||||
title={
|
||||
<div className={'flex items-center gap-2'}>
|
||||
<div>Trend</div>
|
||||
<Segmented
|
||||
options={[
|
||||
{ label: 'Single-Series', value: 'single' },
|
||||
{ label: 'Multi-Series', value: 'multi' },
|
||||
]}
|
||||
onChange={(v) => setIsMulti(v === 'multi')}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className={'relative'}>
|
||||
<div className={'flex flex-col gap-4'}>
|
||||
{rows.map((r) => (
|
||||
<div className={'flex items-center gap-2'}>
|
||||
<div className={'text-gray-dark'}>{r}K</div>
|
||||
<div className="border-t border-dotted border-gray-lighter w-full"></div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className={'ml-4 flex items-center justify-around w-full'}>
|
||||
{months.map((m) => (
|
||||
<div className={'text-gray-dark'}>{m}</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div style={{ position: 'absolute', top: 50, left: 50 }}>
|
||||
<svg
|
||||
width="310"
|
||||
height="65"
|
||||
viewBox="0 0 310 65"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M1 55.3477L12.3778 48.184C23.7556 41.0204 46.5111 26.6931 69.2667 16.6138C92.0222 6.53442 114.778 0.703032 137.533 1.58821C160.289 2.47339 183.044 10.0751 205.8 18.5821C228.556 27.0891 251.311 36.5013 274.067 34.6878C296.822 32.8743 319.578 19.8351 342.333 12.8615C365.089 5.88789 387.844 4.97992 410.6 13.8627C433.356 22.7454 456.111 41.4189 478.867 51.0086C501.622 60.5983 524.378 61.1042 547.133 60.1189C569.889 59.1335 592.644 56.6569 615.4 51.4908C638.156 46.3247 660.911 38.4691 683.667 33.0755C706.422 27.6819 729.178 24.7502 751.933 18.4788C774.689 12.2073 797.444 2.59602 820.2 4.96937C842.956 7.34271 865.711 21.7007 888.467 24.9543C911.222 28.2078 933.978 20.357 956.733 24.9861C979.489 29.6152 1002.24 46.7243 1013.62 55.2788L1025 63.8333"
|
||||
stroke="#394EFF"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
{isMulti ? (
|
||||
<div style={{ position: 'absolute', top: 50, left: 50 }}>
|
||||
<svg
|
||||
width="310"
|
||||
height="66"
|
||||
viewBox="0 0 310 66"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M1028 60.5095L1016.64 55.3116C1005.28 50.1137 982.569 19.7179 959.854 12.4043C937.138 5.09082 914.423 0.85959 891.708 1.50187C868.992 2.14416 846.277 7.65995 823.561 13.8326C800.846 20.0052 778.131 46.8346 755.415 45.5188C732.7 44.2029 709.984 34.7417 687.269 29.6817C664.554 24.6217 641.838 23.9629 619.123 30.4082C596.407 36.8535 573.692 50.4029 550.977 57.3611C528.261 64.3193 505.546 64.6864 482.83 63.9714C460.115 63.2565 437.4 61.4595 414.684 57.711C391.969 53.9625 369.253 48.2625 346.538 44.3489C323.823 40.4353 301.107 38.3081 278.392 33.7576C255.676 29.207 232.961 22.2331 210.246 23.9552C187.53 25.6773 164.815 36.0954 142.099 38.4562C119.384 40.8169 96.6686 35.1204 73.9532 38.4793C51.2378 41.8381 16.7156 44.2524 5.35794 50.4595L-5.99987 56.6666"
|
||||
stroke="#24959A"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className={'flex gap-4 justify-center'}>
|
||||
<div className={'flex gap-2 items-center'}>
|
||||
<div className={'w-4 h-4 rounded-full bg-main'} />
|
||||
<div>CTA 1</div>
|
||||
</div>
|
||||
<div className={'flex gap-2 items-center'}>
|
||||
<div className={'w-4 h-4 rounded-full bg-tealx'} />
|
||||
<div>CTA 2</div>
|
||||
</div>
|
||||
</div>
|
||||
</ExCard>
|
||||
);
|
||||
}
|
||||
|
||||
export default ExampleTrend;
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
import { Segmented } from 'antd';
|
||||
import { Activity, BarChart, TableCellsMerge, TrendingUp } from 'lucide-react';
|
||||
import React from 'react';
|
||||
|
||||
import { Modal } from 'UI';
|
||||
import ExampleCount from "./Examples/Count";
|
||||
|
||||
import ExampleFunnel from './Examples/Funnel';
|
||||
import ExamplePath from './Examples/Path';
|
||||
import ExampleTrend from './Examples/Trend';
|
||||
|
||||
function NewDashboardModal(props: { onClose: () => void; open: boolean }) {
|
||||
return (
|
||||
<Modal onClose={props.onClose} open={props.open} size={'xlarge'}>
|
||||
<Modal.Content className={'bg-[#FAFAFA]'}>
|
||||
<div className={'flex flex-col gap-4'}>
|
||||
<div className={'flex items-center justify-between'}>
|
||||
<div className={'text-2xl leading-4 font-semibold'}>
|
||||
Select your first card type to add to the dashboard
|
||||
</div>
|
||||
<div className={'link'} onClick={props.onClose}>
|
||||
Close
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Segmented
|
||||
options={[
|
||||
{
|
||||
label: (
|
||||
<div className={'flex items-center gap-2'}>
|
||||
<TrendingUp size={16} strokeWidth={1} />
|
||||
<div>Product Analytics</div>
|
||||
</div>
|
||||
),
|
||||
value: 'product-analytics',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<div className={'flex items-center gap-2'}>
|
||||
<Activity size={16} strokeWidth={1} />
|
||||
<div>Performance Monitoring</div>
|
||||
</div>
|
||||
),
|
||||
value: 'performance-monitoring',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<div className={'flex items-center gap-2'}>
|
||||
<BarChart size={16} strokeWidth={1} />
|
||||
<div>Web Analytics</div>
|
||||
</div>
|
||||
),
|
||||
value: 'web-analytics',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<div className={'flex items-center gap-2'}>
|
||||
<TableCellsMerge size={16} strokeWidth={1} />
|
||||
<div>Core Web Vitals</div>
|
||||
</div>
|
||||
),
|
||||
value: 'core-web-vitals',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<div className={'mt-2 w-full flex flex-wrap gap-2 overflow-scroll'}>
|
||||
<ExampleFunnel />
|
||||
<ExamplePath />
|
||||
<ExampleTrend />
|
||||
<ExampleCount />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal.Content>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export default NewDashboardModal;
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
import React from 'react';
|
||||
import SessionListItem from '../SessionListItem';
|
||||
|
||||
function SessionList(props) {
|
||||
return (
|
||||
<div>
|
||||
Session list
|
||||
<SessionListItem session={{}} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SessionList;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './SessionList';
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
session: any;
|
||||
}
|
||||
function SessionListItem(props: Props) {
|
||||
return (
|
||||
<div>
|
||||
Session list item
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SessionListItem;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './SessionListItem';
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import React from 'react';
|
||||
import SessionList from '../SessionList';
|
||||
|
||||
function SessionWidget(props) {
|
||||
return (
|
||||
<div>
|
||||
<SessionList />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default SessionWidget;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './SessionWidget';
|
||||
|
|
@ -34,9 +34,11 @@ const CustomLink: React.FC<CustomLinkProps> = (props) => {
|
|||
targetControlX,
|
||||
linkWidth,
|
||||
index,
|
||||
} = props;
|
||||
const isActive = activeLinks.length > 0 && activeLinks.includes(payload.id);
|
||||
const isHover = hoveredLinks.length > 0 && hoveredLinks.includes(payload.id);
|
||||
activeLink
|
||||
} =
|
||||
props;
|
||||
const isActive = activeLinks?.length > 0 && activeLinks.includes(payload.id);
|
||||
const isHover = hoveredLinks?.length > 0 && hoveredLinks.includes(payload.id);
|
||||
|
||||
const onClick = () => {
|
||||
if (props.onClick) {
|
||||
|
|
|
|||
|
|
@ -17,19 +17,40 @@ const CustomNode: React.FC<CustomNodeProps> = (props) => {
|
|||
const { x, y, width, height, index, payload, containerWidth } = props;
|
||||
const isOut = x + width + 6 > containerWidth;
|
||||
|
||||
return (
|
||||
<Layer key={`CustomNode${index}`} style={{ cursor: 'pointer' }}>
|
||||
<Rectangle x={x} y={y} width={width} height={height} fill='#394EFF' fillOpacity='1' />
|
||||
<foreignObject
|
||||
x={isOut ? x - 6 : x + width + 5}
|
||||
y={y + 5}
|
||||
height='25'
|
||||
style={{ width: '150px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}
|
||||
>
|
||||
<NodeButton payload={payload} />
|
||||
</foreignObject>
|
||||
</Layer>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<Layer key={`CustomNode${index}`} style={{ cursor: 'pointer' }}>
|
||||
<Rectangle x={x} y={y} width={width} height={height} fill='#394EFF' fillOpacity='1' />
|
||||
|
||||
{/*<foreignObject*/}
|
||||
{/* x={isOut ? x - 6 : x + width + 5}*/}
|
||||
{/* y={0}*/}
|
||||
{/* height={48}*/}
|
||||
{/* style={{ width: '150px', padding: '2px' }}*/}
|
||||
{/*>*/}
|
||||
{/* <NodeDropdown payload={payload} />*/}
|
||||
{/*</foreignObject>*/}
|
||||
|
||||
{!isDemo ? (
|
||||
<foreignObject
|
||||
x={isOut ? x - 6 : x + width + 5}
|
||||
y={y + 5}
|
||||
height="25"
|
||||
style={{ width: "150px", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}
|
||||
>
|
||||
<NodeButton payload={payload} />
|
||||
</foreignObject>
|
||||
) : (
|
||||
<foreignObject
|
||||
x={isOut ? x - 6 : x + width + 5}
|
||||
y={y + 5}
|
||||
height="28"
|
||||
style={{ width: "70px", whiteSpace: "nowrap" }}
|
||||
>
|
||||
<div className={'p-1 bg-white rounded border'}>{payload.name}</div>
|
||||
</foreignObject>
|
||||
)}
|
||||
</Layer>
|
||||
);
|
||||
}
|
||||
|
||||
export default CustomNode;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import cn from 'classnames';
|
|||
interface Props {
|
||||
children: React.ReactNode;
|
||||
open?: boolean;
|
||||
size ?: 'tiny' | 'small' | 'large' | 'fullscreen';
|
||||
size ?: 'tiny' | 'small' | 'large' | 'fullscreen' | 'xlarge';
|
||||
onClose?: () => void;
|
||||
}
|
||||
function Modal(props: Props) {
|
||||
|
|
@ -20,14 +20,22 @@ function Modal(props: Props) {
|
|||
}, [open]);
|
||||
|
||||
const style: any = {};
|
||||
if (size === 'tiny') {
|
||||
style.width = '300px';
|
||||
} else if (size === 'small') {
|
||||
style.width = '400px';
|
||||
} else if (size === 'large') {
|
||||
style.width = '700px';
|
||||
} else if (size === 'fullscreen') {
|
||||
style.width = '100%';
|
||||
switch (size) {
|
||||
case 'tiny':
|
||||
style.width = '300px';
|
||||
break;
|
||||
case 'small':
|
||||
style.width = '400px';
|
||||
break;
|
||||
case 'large':
|
||||
style.width = '700px';
|
||||
break;
|
||||
case 'xlarge':
|
||||
style.width = '846px';
|
||||
break;
|
||||
case 'fullscreen':
|
||||
style.width = '100%';
|
||||
break;
|
||||
}
|
||||
|
||||
const handleClose = (e: React.MouseEvent<HTMLDivElement>) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue