chore: create cluster ux
This commit is contained in:
@@ -24,6 +24,8 @@ export default function useChartConfig() {
|
||||
splitLineColor: token.colorBorder,
|
||||
tickLineColor: token.colorSplit,
|
||||
axislabelColor: token.colorTextTertiary,
|
||||
colorSecondary: token.colorTextSecondary,
|
||||
colorTertiary: token.colorTextTertiary,
|
||||
gaugeBgColor: token.colorFillSecondary,
|
||||
gaugeSplitLineColor: isDarkTheme
|
||||
? 'rgba(255,255,255,.3)'
|
||||
@@ -172,8 +174,8 @@ export default function useChartConfig() {
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
distance: -11,
|
||||
length: 6,
|
||||
distance: -10,
|
||||
length: 5,
|
||||
splitNumber: 5,
|
||||
lineStyle: {
|
||||
width: 1.5,
|
||||
@@ -206,13 +208,13 @@ export default function useChartConfig() {
|
||||
rich: {
|
||||
value: {
|
||||
fontSize: 16,
|
||||
fontWeight: '500',
|
||||
fontWeight: '600',
|
||||
color: chartColorMap.titleColor
|
||||
},
|
||||
unit: {
|
||||
fontSize: 14,
|
||||
color: chartColorMap.titleColor,
|
||||
fontWeight: '500',
|
||||
fontWeight: '600',
|
||||
padding: [0, 0, 0, 2]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Chart from '@/components/echarts/chart';
|
||||
import useChartConfig from '@/components/echarts/config';
|
||||
import EmptyData from '@/components/empty-data';
|
||||
import React, { memo } from 'react';
|
||||
import React from 'react';
|
||||
import { ChartProps } from './types';
|
||||
|
||||
const strokeColorFunc = (percent: number) => {
|
||||
@@ -34,10 +34,19 @@ const GaugeChart: React.FC<Omit<ChartProps, 'seriesData' | 'xAxisData'>> = (
|
||||
...gaugeItemConfig,
|
||||
...gaugeConfig
|
||||
};
|
||||
|
||||
combineGaugeConfig.detail.rich.value.color = colorValue;
|
||||
combineGaugeConfig.detail.rich.unit.color = colorValue;
|
||||
|
||||
return {
|
||||
title: {
|
||||
...titleConfig,
|
||||
text: title,
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
color: chartColorMap.colorSecondary,
|
||||
fontWeight: 400
|
||||
},
|
||||
top: '0',
|
||||
left: 'center'
|
||||
},
|
||||
@@ -58,7 +67,7 @@ const GaugeChart: React.FC<Omit<ChartProps, 'seriesData' | 'xAxisData'>> = (
|
||||
color: 'transparent'
|
||||
},
|
||||
detail: {
|
||||
...gaugeItemConfig.detail,
|
||||
...combineGaugeConfig.detail,
|
||||
formatter: labelFormatter || gaugeItemConfig.detail.formatter
|
||||
},
|
||||
data: [{ value }]
|
||||
@@ -78,4 +87,4 @@ const GaugeChart: React.FC<Omit<ChartProps, 'seriesData' | 'xAxisData'>> = (
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(GaugeChart);
|
||||
export default GaugeChart;
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
import OverlayScroller from '@/components/overlay-scroller';
|
||||
import useBodyScroll from '@/hooks/use-body-scroll';
|
||||
import useOverlayScroller from '@/hooks/use-overlay-scroller';
|
||||
import { Modal, type ModalProps } from 'antd';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Wrapper = styled.div<{ $maxHeight?: number }>`
|
||||
max-height: ${({ $maxHeight }) =>
|
||||
typeof $maxHeight === 'number' ? `${$maxHeight}px` : $maxHeight};
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
const ScrollerModal = (props: ModalProps & { maxContentHeight?: number }) => {
|
||||
const scroller = React.useRef<any>(null);
|
||||
const { saveScrollHeight, restoreScrollHeight } = useBodyScroll();
|
||||
const { initialize, destroyInstance } = useOverlayScroller();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (props.open) {
|
||||
@@ -14,6 +24,24 @@ const ScrollerModal = (props: ModalProps & { maxContentHeight?: number }) => {
|
||||
}
|
||||
}, [props.open]);
|
||||
|
||||
// init scroller, delay to ensure modal is fully open
|
||||
React.useEffect(() => {
|
||||
let timeout = null;
|
||||
if (props.open) {
|
||||
timeout = setTimeout(() => {
|
||||
if (scroller.current) {
|
||||
initialize(scroller.current);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
return () => {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
destroyInstance();
|
||||
};
|
||||
}, [props.open, initialize]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
{...props}
|
||||
@@ -34,12 +62,16 @@ const ScrollerModal = (props: ModalProps & { maxContentHeight?: number }) => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<OverlayScroller
|
||||
style={{ paddingInline: 24, paddingBlockEnd: props.footer ? 0 : 32 }}
|
||||
maxHeight={props.maxContentHeight || 500}
|
||||
<Wrapper
|
||||
ref={scroller}
|
||||
data-overlayscrollbars-initialize
|
||||
className="overlay-scroller-wrapper"
|
||||
$maxHeight={props.maxContentHeight || 500}
|
||||
hidden={false}
|
||||
style={{ paddingInline: 24, paddingBlockEnd: props.footer ? 0 : 24 }}
|
||||
>
|
||||
{props.children}
|
||||
</OverlayScroller>
|
||||
</Wrapper>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
import useUserSettings from '@/hooks/use-user-settings';
|
||||
import { Tag, TagProps } from 'antd';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const TagWrapper = styled(Tag)`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
height: 22px;
|
||||
opacity: 0.7;
|
||||
`;
|
||||
|
||||
const ThemeTag: React.FC<TagProps & { opacity?: number }> = ({
|
||||
opacity,
|
||||
@@ -11,7 +23,7 @@ const ThemeTag: React.FC<TagProps & { opacity?: number }> = ({
|
||||
const { userSettings } = useUserSettings();
|
||||
const { isDarkTheme } = userSettings;
|
||||
return (
|
||||
<Tag
|
||||
<TagWrapper
|
||||
{...restProps}
|
||||
style={{
|
||||
...style,
|
||||
@@ -19,7 +31,7 @@ const ThemeTag: React.FC<TagProps & { opacity?: number }> = ({
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Tag>
|
||||
</TagWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -8,13 +8,14 @@ interface CardProps {
|
||||
children?: React.ReactNode;
|
||||
clickable?: boolean;
|
||||
ghost?: boolean;
|
||||
header?: React.ReactNode;
|
||||
footer?: React.ReactNode;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
const CardWrapper = styled.div`
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
padding: 16px 20px;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
@@ -39,6 +40,12 @@ const CardWrapper = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const CardContent = styled.div`
|
||||
padding: 16px 20px;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const Card: React.FC<CardProps> = (props) => {
|
||||
const {
|
||||
className,
|
||||
@@ -46,6 +53,8 @@ const Card: React.FC<CardProps> = (props) => {
|
||||
children,
|
||||
clickable = true,
|
||||
ghost = false,
|
||||
header,
|
||||
footer,
|
||||
onClick
|
||||
} = props;
|
||||
|
||||
@@ -58,7 +67,9 @@ const Card: React.FC<CardProps> = (props) => {
|
||||
style={{ height: height || '180px' }}
|
||||
onClick={onClick}
|
||||
>
|
||||
{children}
|
||||
{header}
|
||||
<CardContent>{children}</CardContent>
|
||||
{footer}
|
||||
</CardWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user