@opsnow-mcp/opsnow-mcp-common-ui-server 1.0.23 → 1.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -538,11 +538,9 @@ export const PieChartExamples = [
|
|
|
538
538
|
const [chartData] = useState([
|
|
539
539
|
{ service: 'EC2', cost: 15600 },
|
|
540
540
|
{ service: 'RDS', cost: 8200 },
|
|
541
|
-
{ service: 'S3', cost: 4300 }
|
|
542
|
-
{ service: 'Lambda', cost: 2100 },
|
|
543
|
-
{ service: 'CloudFront', cost: 1800 }
|
|
541
|
+
{ service: 'S3', cost: 4300 }
|
|
544
542
|
])
|
|
545
|
-
const [chartCategory] = useState(['EC2', 'RDS', 'S3'
|
|
543
|
+
const [chartCategory] = useState(['EC2', 'RDS', 'S3'])
|
|
546
544
|
|
|
547
545
|
// 다운로드 핸들러
|
|
548
546
|
const handleDownload = () => {
|
|
@@ -6841,3 +6839,428 @@ export const XyMultiChartExamples = [
|
|
|
6841
6839
|
/>`
|
|
6842
6840
|
},
|
|
6843
6841
|
];
|
|
6842
|
+
// Heatmap Chart 컴포넌트 예제 데이터
|
|
6843
|
+
export const HeatmapChartExamples = [
|
|
6844
|
+
{
|
|
6845
|
+
title: '히트맵 차트 - 기본',
|
|
6846
|
+
description: '인시던트 발생 패턴(시간×요일) 히트맵 차트 기본 예제입니다. heatRule로 최소/최대 색상을 지정하고, 기본 그래디언트 범례를 표시합니다.',
|
|
6847
|
+
code_props_usage: `
|
|
6848
|
+
const chartId = 'heatmap-chart-${generateUniqueGeneralId()}'
|
|
6849
|
+
const chartRef = useRef(null)
|
|
6850
|
+
const [chartProps, setChartProps] = useState({
|
|
6851
|
+
chart: {
|
|
6852
|
+
paddingLeft: 0,
|
|
6853
|
+
paddingRight: 0,
|
|
6854
|
+
paddingBottom: 0,
|
|
6855
|
+
},
|
|
6856
|
+
xAxis: {
|
|
6857
|
+
type: 'category',
|
|
6858
|
+
valueField: 'hour',
|
|
6859
|
+
gridHidden: true,
|
|
6860
|
+
renderer: {
|
|
6861
|
+
opposite: true,
|
|
6862
|
+
minGridDistance: 20,
|
|
6863
|
+
},
|
|
6864
|
+
label: { fontSize: 11 },
|
|
6865
|
+
},
|
|
6866
|
+
yAxis: {
|
|
6867
|
+
type: 'category',
|
|
6868
|
+
valueField: 'day',
|
|
6869
|
+
gridHidden: true,
|
|
6870
|
+
renderer: {
|
|
6871
|
+
inversed: true,
|
|
6872
|
+
minGridDistance: 20,
|
|
6873
|
+
},
|
|
6874
|
+
label: { fontSize: 11, maxWidth: 70, fontWeight: 'bold' },
|
|
6875
|
+
},
|
|
6876
|
+
series: {
|
|
6877
|
+
categoryXField: 'hour',
|
|
6878
|
+
categoryYField: 'day',
|
|
6879
|
+
valueField: 'value',
|
|
6880
|
+
columns: {
|
|
6881
|
+
strokeWidth: 2,
|
|
6882
|
+
hover: { enabled: true },
|
|
6883
|
+
},
|
|
6884
|
+
tooltip: {
|
|
6885
|
+
type: 'CI',
|
|
6886
|
+
header: { name: '{day} {hour}h' },
|
|
6887
|
+
body: { value: '{value} {l.unit}' },
|
|
6888
|
+
},
|
|
6889
|
+
},
|
|
6890
|
+
heatRule: {
|
|
6891
|
+
key: 'fill',
|
|
6892
|
+
minColor: '#fce4ec',
|
|
6893
|
+
maxColor: '#c62828',
|
|
6894
|
+
},
|
|
6895
|
+
legend: {
|
|
6896
|
+
orientation: 'horizontal',
|
|
6897
|
+
legendWidth: 200,
|
|
6898
|
+
},
|
|
6899
|
+
})
|
|
6900
|
+
const [chartData, setChartData] = useState([
|
|
6901
|
+
{ hour: '0', day: 'day_0', value: 0 }, { hour: '1', day: 'day_0', value: 2 },
|
|
6902
|
+
{ hour: '2', day: 'day_0', value: 0 }, { hour: '3', day: 'day_0', value: 5 },
|
|
6903
|
+
{ hour: '4', day: 'day_0', value: 0 }, { hour: '5', day: 'day_0', value: 0 },
|
|
6904
|
+
{ hour: '6', day: 'day_0', value: 1 }, { hour: '7', day: 'day_0', value: 3 },
|
|
6905
|
+
{ hour: '8', day: 'day_0', value: 0 }, { hour: '9', day: 'day_0', value: 0 },
|
|
6906
|
+
{ hour: '10', day: 'day_0', value: 4 }, { hour: '11', day: 'day_0', value: 0 },
|
|
6907
|
+
{ hour: '12', day: 'day_0', value: 0 }, { hour: '13', day: 'day_0', value: 2 },
|
|
6908
|
+
{ hour: '14', day: 'day_0', value: 0 }, { hour: '15', day: 'day_0', value: 0 },
|
|
6909
|
+
{ hour: '16', day: 'day_0', value: 6 }, { hour: '17', day: 'day_0', value: 0 },
|
|
6910
|
+
{ hour: '18', day: 'day_0', value: 0 }, { hour: '19', day: 'day_0', value: 1 },
|
|
6911
|
+
{ hour: '20', day: 'day_0', value: 0 }, { hour: '21', day: 'day_0', value: 0 },
|
|
6912
|
+
{ hour: '22', day: 'day_0', value: 3 }, { hour: '23', day: 'day_0', value: 0 },
|
|
6913
|
+
{ hour: '0', day: 'day_1', value: 0 }, { hour: '1', day: 'day_1', value: 0 },
|
|
6914
|
+
{ hour: '2', day: 'day_1', value: 1 }, { hour: '3', day: 'day_1', value: 0 },
|
|
6915
|
+
{ hour: '4', day: 'day_1', value: 0 }, { hour: '5', day: 'day_1', value: 3 },
|
|
6916
|
+
{ hour: '6', day: 'day_1', value: 0 }, { hour: '7', day: 'day_1', value: 0 },
|
|
6917
|
+
{ hour: '8', day: 'day_1', value: 7 }, { hour: '9', day: 'day_1', value: 0 },
|
|
6918
|
+
{ hour: '10', day: 'day_1', value: 0 }, { hour: '11', day: 'day_1', value: 2 },
|
|
6919
|
+
{ hour: '12', day: 'day_1', value: 0 }, { hour: '13', day: 'day_1', value: 0 },
|
|
6920
|
+
{ hour: '14', day: 'day_1', value: 4 }, { hour: '15', day: 'day_1', value: 0 },
|
|
6921
|
+
{ hour: '16', day: 'day_1', value: 0 }, { hour: '17', day: 'day_1', value: 1 },
|
|
6922
|
+
{ hour: '18', day: 'day_1', value: 0 }, { hour: '19', day: 'day_1', value: 5 },
|
|
6923
|
+
{ hour: '20', day: 'day_1', value: 0 }, { hour: '21', day: 'day_1', value: 0 },
|
|
6924
|
+
{ hour: '22', day: 'day_1', value: 0 }, { hour: '23', day: 'day_1', value: 2 },
|
|
6925
|
+
{ hour: '0', day: 'day_2', value: 1 }, { hour: '1', day: 'day_2', value: 0 },
|
|
6926
|
+
{ hour: '2', day: 'day_2', value: 0 }, { hour: '3', day: 'day_2', value: 0 },
|
|
6927
|
+
{ hour: '4', day: 'day_2', value: 3 }, { hour: '5', day: 'day_2', value: 0 },
|
|
6928
|
+
{ hour: '6', day: 'day_2', value: 0 }, { hour: '7', day: 'day_2', value: 6 },
|
|
6929
|
+
{ hour: '8', day: 'day_2', value: 0 }, { hour: '9', day: 'day_2', value: 2 },
|
|
6930
|
+
{ hour: '10', day: 'day_2', value: 0 }, { hour: '11', day: 'day_2', value: 0 },
|
|
6931
|
+
{ hour: '12', day: 'day_2', value: 4 }, { hour: '13', day: 'day_2', value: 0 },
|
|
6932
|
+
{ hour: '14', day: 'day_2', value: 0 }, { hour: '15', day: 'day_2', value: 1 },
|
|
6933
|
+
{ hour: '16', day: 'day_2', value: 0 }, { hour: '17', day: 'day_2', value: 0 },
|
|
6934
|
+
{ hour: '18', day: 'day_2', value: 5 }, { hour: '19', day: 'day_2', value: 0 },
|
|
6935
|
+
{ hour: '20', day: 'day_2', value: 0 }, { hour: '21', day: 'day_2', value: 3 },
|
|
6936
|
+
{ hour: '22', day: 'day_2', value: 0 }, { hour: '23', day: 'day_2', value: 0 },
|
|
6937
|
+
])
|
|
6938
|
+
const chartLocaleMessage = [
|
|
6939
|
+
{ name: 'day_0', locale: 'Mon 4/14' },
|
|
6940
|
+
{ name: 'day_1', locale: 'Tue 4/15' },
|
|
6941
|
+
{ name: 'day_2', locale: 'Wed 4/16' },
|
|
6942
|
+
]
|
|
6943
|
+
const chartLocaleProps = [
|
|
6944
|
+
{ name: 'l.unit', locale: 'incidents' },
|
|
6945
|
+
]
|
|
6946
|
+
`,
|
|
6947
|
+
code: `<OpsnowCommonHeatmapChart
|
|
6948
|
+
chartId={chartId}
|
|
6949
|
+
ref={chartRef}
|
|
6950
|
+
chartProps={chartProps}
|
|
6951
|
+
chartData={chartData}
|
|
6952
|
+
chartLocaleMessage={chartLocaleMessage}
|
|
6953
|
+
chartLocaleProps={chartLocaleProps}
|
|
6954
|
+
/>`
|
|
6955
|
+
},
|
|
6956
|
+
{
|
|
6957
|
+
title: '히트맵 차트 - 레전드 라벨 및 스타일',
|
|
6958
|
+
description: '범례에 labelText와 스타일(폰트 크기, 바 높이)을 커스터마이징한 히트맵 차트 예제입니다.',
|
|
6959
|
+
code_props_usage: `
|
|
6960
|
+
const chartId = 'heatmap-chart-${generateUniqueGeneralId()}'
|
|
6961
|
+
const chartRef = useRef(null)
|
|
6962
|
+
const [chartProps, setChartProps] = useState({
|
|
6963
|
+
chart: {
|
|
6964
|
+
paddingLeft: 0,
|
|
6965
|
+
paddingRight: 0,
|
|
6966
|
+
paddingBottom: 0,
|
|
6967
|
+
},
|
|
6968
|
+
xAxis: {
|
|
6969
|
+
type: 'category',
|
|
6970
|
+
valueField: 'hour',
|
|
6971
|
+
gridHidden: true,
|
|
6972
|
+
renderer: {
|
|
6973
|
+
opposite: true,
|
|
6974
|
+
minGridDistance: 20,
|
|
6975
|
+
},
|
|
6976
|
+
label: { fontSize: 11 },
|
|
6977
|
+
},
|
|
6978
|
+
yAxis: {
|
|
6979
|
+
type: 'category',
|
|
6980
|
+
valueField: 'day',
|
|
6981
|
+
gridHidden: true,
|
|
6982
|
+
renderer: {
|
|
6983
|
+
inversed: true,
|
|
6984
|
+
minGridDistance: 20,
|
|
6985
|
+
},
|
|
6986
|
+
label: { fontSize: 11, maxWidth: 70, fontWeight: 'bold' },
|
|
6987
|
+
},
|
|
6988
|
+
series: {
|
|
6989
|
+
categoryXField: 'hour',
|
|
6990
|
+
categoryYField: 'day',
|
|
6991
|
+
valueField: 'value',
|
|
6992
|
+
columns: {
|
|
6993
|
+
strokeWidth: 2,
|
|
6994
|
+
hover: { enabled: true },
|
|
6995
|
+
},
|
|
6996
|
+
tooltip: {
|
|
6997
|
+
type: 'CI',
|
|
6998
|
+
header: { name: '{day} {hour}h' },
|
|
6999
|
+
body: { value: '{value} {l.unit}' },
|
|
7000
|
+
label: { fontSize: 11 },
|
|
7001
|
+
},
|
|
7002
|
+
},
|
|
7003
|
+
heatRule: {
|
|
7004
|
+
key: 'fill',
|
|
7005
|
+
minColor: '#fce4ec',
|
|
7006
|
+
maxColor: '#c62828',
|
|
7007
|
+
},
|
|
7008
|
+
legend: {
|
|
7009
|
+
orientation: 'horizontal',
|
|
7010
|
+
labelText: '{l.legendLabel}',
|
|
7011
|
+
labelFontSize: 12,
|
|
7012
|
+
legendWidth: 200,
|
|
7013
|
+
barHeight: 16,
|
|
7014
|
+
},
|
|
7015
|
+
})
|
|
7016
|
+
const [chartData, setChartData] = useState([
|
|
7017
|
+
{ hour: '0', day: 'day_0', value: 0 }, { hour: '1', day: 'day_0', value: 2 },
|
|
7018
|
+
{ hour: '2', day: 'day_0', value: 0 }, { hour: '3', day: 'day_0', value: 5 },
|
|
7019
|
+
{ hour: '4', day: 'day_0', value: 0 }, { hour: '5', day: 'day_0', value: 0 },
|
|
7020
|
+
{ hour: '6', day: 'day_0', value: 1 }, { hour: '7', day: 'day_0', value: 3 },
|
|
7021
|
+
{ hour: '8', day: 'day_0', value: 0 }, { hour: '9', day: 'day_0', value: 0 },
|
|
7022
|
+
{ hour: '10', day: 'day_0', value: 4 }, { hour: '11', day: 'day_0', value: 0 },
|
|
7023
|
+
{ hour: '12', day: 'day_0', value: 0 }, { hour: '13', day: 'day_0', value: 2 },
|
|
7024
|
+
{ hour: '14', day: 'day_0', value: 0 }, { hour: '15', day: 'day_0', value: 0 },
|
|
7025
|
+
{ hour: '16', day: 'day_0', value: 6 }, { hour: '17', day: 'day_0', value: 0 },
|
|
7026
|
+
{ hour: '18', day: 'day_0', value: 0 }, { hour: '19', day: 'day_0', value: 1 },
|
|
7027
|
+
{ hour: '20', day: 'day_0', value: 0 }, { hour: '21', day: 'day_0', value: 0 },
|
|
7028
|
+
{ hour: '22', day: 'day_0', value: 3 }, { hour: '23', day: 'day_0', value: 0 },
|
|
7029
|
+
{ hour: '0', day: 'day_1', value: 0 }, { hour: '1', day: 'day_1', value: 0 },
|
|
7030
|
+
{ hour: '2', day: 'day_1', value: 1 }, { hour: '3', day: 'day_1', value: 0 },
|
|
7031
|
+
{ hour: '4', day: 'day_1', value: 0 }, { hour: '5', day: 'day_1', value: 3 },
|
|
7032
|
+
{ hour: '6', day: 'day_1', value: 0 }, { hour: '7', day: 'day_1', value: 0 },
|
|
7033
|
+
{ hour: '8', day: 'day_1', value: 7 }, { hour: '9', day: 'day_1', value: 0 },
|
|
7034
|
+
{ hour: '10', day: 'day_1', value: 0 }, { hour: '11', day: 'day_1', value: 2 },
|
|
7035
|
+
{ hour: '12', day: 'day_1', value: 0 }, { hour: '13', day: 'day_1', value: 0 },
|
|
7036
|
+
{ hour: '14', day: 'day_1', value: 4 }, { hour: '15', day: 'day_1', value: 0 },
|
|
7037
|
+
{ hour: '16', day: 'day_1', value: 0 }, { hour: '17', day: 'day_1', value: 1 },
|
|
7038
|
+
{ hour: '18', day: 'day_1', value: 0 }, { hour: '19', day: 'day_1', value: 5 },
|
|
7039
|
+
{ hour: '20', day: 'day_1', value: 0 }, { hour: '21', day: 'day_1', value: 0 },
|
|
7040
|
+
{ hour: '22', day: 'day_1', value: 0 }, { hour: '23', day: 'day_1', value: 2 },
|
|
7041
|
+
])
|
|
7042
|
+
const chartLocaleMessage = [
|
|
7043
|
+
{ name: 'day_0', locale: 'Mon 4/14' },
|
|
7044
|
+
{ name: 'day_1', locale: 'Tue 4/15' },
|
|
7045
|
+
]
|
|
7046
|
+
const chartLocaleProps = [
|
|
7047
|
+
{ name: 'l.unit', locale: 'incidents' },
|
|
7048
|
+
{ name: 'l.legendLabel', locale: 'Incident Count' },
|
|
7049
|
+
]
|
|
7050
|
+
`,
|
|
7051
|
+
code: `<OpsnowCommonHeatmapChart
|
|
7052
|
+
chartId={chartId}
|
|
7053
|
+
ref={chartRef}
|
|
7054
|
+
chartProps={chartProps}
|
|
7055
|
+
chartData={chartData}
|
|
7056
|
+
chartLocaleMessage={chartLocaleMessage}
|
|
7057
|
+
chartLocaleProps={chartLocaleProps}
|
|
7058
|
+
/>`
|
|
7059
|
+
},
|
|
7060
|
+
{
|
|
7061
|
+
title: '히트맵 차트 - 커스텀 색상 및 클릭 이벤트',
|
|
7062
|
+
description: '커스텀 색상(보라 계열 그래디언트)과 셀 클릭 이벤트를 처리하는 히트맵 차트 예제입니다. onChartClick으로 클릭한 셀 정보를 받을 수 있습니다.',
|
|
7063
|
+
code_props_usage: `
|
|
7064
|
+
const chartId = 'heatmap-chart-${generateUniqueGeneralId()}'
|
|
7065
|
+
const chartRef = useRef(null)
|
|
7066
|
+
const [clickedCell, setClickedCell] = useState(null)
|
|
7067
|
+
const [chartProps, setChartProps] = useState({
|
|
7068
|
+
chart: {
|
|
7069
|
+
paddingLeft: 0,
|
|
7070
|
+
paddingRight: 0,
|
|
7071
|
+
paddingBottom: 0,
|
|
7072
|
+
},
|
|
7073
|
+
xAxis: {
|
|
7074
|
+
type: 'category',
|
|
7075
|
+
valueField: 'hour',
|
|
7076
|
+
gridHidden: true,
|
|
7077
|
+
renderer: {
|
|
7078
|
+
opposite: true,
|
|
7079
|
+
minGridDistance: 20,
|
|
7080
|
+
},
|
|
7081
|
+
label: { fontSize: 11 },
|
|
7082
|
+
},
|
|
7083
|
+
yAxis: {
|
|
7084
|
+
type: 'category',
|
|
7085
|
+
valueField: 'day',
|
|
7086
|
+
gridHidden: true,
|
|
7087
|
+
renderer: {
|
|
7088
|
+
inversed: true,
|
|
7089
|
+
minGridDistance: 20,
|
|
7090
|
+
},
|
|
7091
|
+
label: { fontSize: 11, maxWidth: 70, fontWeight: 'bold' },
|
|
7092
|
+
},
|
|
7093
|
+
series: {
|
|
7094
|
+
categoryXField: 'hour',
|
|
7095
|
+
categoryYField: 'day',
|
|
7096
|
+
valueField: 'value',
|
|
7097
|
+
columns: {
|
|
7098
|
+
strokeWidth: 2,
|
|
7099
|
+
hover: { enabled: true, color: '#d50000' },
|
|
7100
|
+
},
|
|
7101
|
+
tooltip: {
|
|
7102
|
+
type: 'CI',
|
|
7103
|
+
header: { name: '{day} {hour}h' },
|
|
7104
|
+
body: { value: '{value} {l.unit}' },
|
|
7105
|
+
},
|
|
7106
|
+
},
|
|
7107
|
+
heatRule: {
|
|
7108
|
+
key: 'fill',
|
|
7109
|
+
minColor: '#e8eaf6',
|
|
7110
|
+
maxColor: '#4a148c',
|
|
7111
|
+
},
|
|
7112
|
+
legend: {
|
|
7113
|
+
orientation: 'horizontal',
|
|
7114
|
+
labelText: '{l.legendLabel}',
|
|
7115
|
+
labelFontSize: 12,
|
|
7116
|
+
labelFontWeight: 'bold',
|
|
7117
|
+
legendWidth: 200,
|
|
7118
|
+
barHeight: 16,
|
|
7119
|
+
},
|
|
7120
|
+
})
|
|
7121
|
+
const [chartData, setChartData] = useState([
|
|
7122
|
+
{ hour: '0', day: 'day_0', value: 0 }, { hour: '1', day: 'day_0', value: 2 },
|
|
7123
|
+
{ hour: '2', day: 'day_0', value: 0 }, { hour: '3', day: 'day_0', value: 5 },
|
|
7124
|
+
{ hour: '4', day: 'day_0', value: 0 }, { hour: '5', day: 'day_0', value: 0 },
|
|
7125
|
+
{ hour: '6', day: 'day_0', value: 1 }, { hour: '7', day: 'day_0', value: 3 },
|
|
7126
|
+
{ hour: '8', day: 'day_0', value: 0 }, { hour: '9', day: 'day_0', value: 0 },
|
|
7127
|
+
{ hour: '10', day: 'day_0', value: 4 }, { hour: '11', day: 'day_0', value: 0 },
|
|
7128
|
+
{ hour: '12', day: 'day_0', value: 0 }, { hour: '13', day: 'day_0', value: 2 },
|
|
7129
|
+
{ hour: '14', day: 'day_0', value: 0 }, { hour: '15', day: 'day_0', value: 0 },
|
|
7130
|
+
{ hour: '16', day: 'day_0', value: 6 }, { hour: '17', day: 'day_0', value: 0 },
|
|
7131
|
+
{ hour: '18', day: 'day_0', value: 0 }, { hour: '19', day: 'day_0', value: 1 },
|
|
7132
|
+
{ hour: '20', day: 'day_0', value: 0 }, { hour: '21', day: 'day_0', value: 0 },
|
|
7133
|
+
{ hour: '22', day: 'day_0', value: 3 }, { hour: '23', day: 'day_0', value: 0 },
|
|
7134
|
+
{ hour: '0', day: 'day_1', value: 0 }, { hour: '1', day: 'day_1', value: 0 },
|
|
7135
|
+
{ hour: '2', day: 'day_1', value: 1 }, { hour: '3', day: 'day_1', value: 0 },
|
|
7136
|
+
{ hour: '4', day: 'day_1', value: 0 }, { hour: '5', day: 'day_1', value: 3 },
|
|
7137
|
+
{ hour: '6', day: 'day_1', value: 0 }, { hour: '7', day: 'day_1', value: 0 },
|
|
7138
|
+
{ hour: '8', day: 'day_1', value: 7 }, { hour: '9', day: 'day_1', value: 0 },
|
|
7139
|
+
{ hour: '10', day: 'day_1', value: 0 }, { hour: '11', day: 'day_1', value: 2 },
|
|
7140
|
+
{ hour: '12', day: 'day_1', value: 0 }, { hour: '13', day: 'day_1', value: 0 },
|
|
7141
|
+
{ hour: '14', day: 'day_1', value: 4 }, { hour: '15', day: 'day_1', value: 0 },
|
|
7142
|
+
{ hour: '16', day: 'day_1', value: 0 }, { hour: '17', day: 'day_1', value: 1 },
|
|
7143
|
+
{ hour: '18', day: 'day_1', value: 0 }, { hour: '19', day: 'day_1', value: 5 },
|
|
7144
|
+
{ hour: '20', day: 'day_1', value: 0 }, { hour: '21', day: 'day_1', value: 0 },
|
|
7145
|
+
{ hour: '22', day: 'day_1', value: 0 }, { hour: '23', day: 'day_1', value: 2 },
|
|
7146
|
+
])
|
|
7147
|
+
const chartLocaleMessage = [
|
|
7148
|
+
{ name: 'day_0', locale: 'Mon 4/14' },
|
|
7149
|
+
{ name: 'day_1', locale: 'Tue 4/15' },
|
|
7150
|
+
]
|
|
7151
|
+
const chartLocaleProps = [
|
|
7152
|
+
{ name: 'l.unit', locale: 'incidents' },
|
|
7153
|
+
{ name: 'l.legendLabel', locale: 'Incident Count' },
|
|
7154
|
+
]
|
|
7155
|
+
const handleChartClick = (data) => {
|
|
7156
|
+
setClickedCell(data)
|
|
7157
|
+
console.log('Clicked cell:', data)
|
|
7158
|
+
}
|
|
7159
|
+
`,
|
|
7160
|
+
code: `<OpsnowCommonHeatmapChart
|
|
7161
|
+
chartId={chartId}
|
|
7162
|
+
ref={chartRef}
|
|
7163
|
+
chartProps={chartProps}
|
|
7164
|
+
chartData={chartData}
|
|
7165
|
+
chartLocaleMessage={chartLocaleMessage}
|
|
7166
|
+
chartLocaleProps={chartLocaleProps}
|
|
7167
|
+
onChartClick={handleChartClick}
|
|
7168
|
+
/>`
|
|
7169
|
+
},
|
|
7170
|
+
{
|
|
7171
|
+
title: '히트맵 차트 - downloadFile (차트 다운로드)',
|
|
7172
|
+
description: 'ref를 통해 downloadFile 메서드를 호출하여 히트맵 차트를 이미지(png, jpg) 또는 PDF로 다운로드하는 예제입니다.',
|
|
7173
|
+
code_props_usage: `
|
|
7174
|
+
const chartId = 'heatmap-chart-${generateUniqueGeneralId()}'
|
|
7175
|
+
const chartRef = useRef(null)
|
|
7176
|
+
const [chartProps, setChartProps] = useState({
|
|
7177
|
+
chart: {
|
|
7178
|
+
paddingLeft: 0,
|
|
7179
|
+
paddingRight: 0,
|
|
7180
|
+
paddingBottom: 0,
|
|
7181
|
+
},
|
|
7182
|
+
xAxis: {
|
|
7183
|
+
type: 'category',
|
|
7184
|
+
valueField: 'hour',
|
|
7185
|
+
gridHidden: true,
|
|
7186
|
+
renderer: {
|
|
7187
|
+
opposite: true,
|
|
7188
|
+
minGridDistance: 20,
|
|
7189
|
+
},
|
|
7190
|
+
label: { fontSize: 11 },
|
|
7191
|
+
},
|
|
7192
|
+
yAxis: {
|
|
7193
|
+
type: 'category',
|
|
7194
|
+
valueField: 'day',
|
|
7195
|
+
gridHidden: true,
|
|
7196
|
+
renderer: {
|
|
7197
|
+
inversed: true,
|
|
7198
|
+
minGridDistance: 20,
|
|
7199
|
+
},
|
|
7200
|
+
label: { fontSize: 11, maxWidth: 70, fontWeight: 'bold' },
|
|
7201
|
+
},
|
|
7202
|
+
series: {
|
|
7203
|
+
categoryXField: 'hour',
|
|
7204
|
+
categoryYField: 'day',
|
|
7205
|
+
valueField: 'value',
|
|
7206
|
+
columns: {
|
|
7207
|
+
strokeWidth: 2,
|
|
7208
|
+
hover: { enabled: true },
|
|
7209
|
+
},
|
|
7210
|
+
tooltip: {
|
|
7211
|
+
type: 'CI',
|
|
7212
|
+
header: { name: '{day} {hour}h' },
|
|
7213
|
+
body: { value: '{value} {l.unit}' },
|
|
7214
|
+
},
|
|
7215
|
+
},
|
|
7216
|
+
heatRule: {
|
|
7217
|
+
key: 'fill',
|
|
7218
|
+
minColor: '#e0f2f1',
|
|
7219
|
+
maxColor: '#00695c',
|
|
7220
|
+
},
|
|
7221
|
+
legend: {
|
|
7222
|
+
orientation: 'horizontal',
|
|
7223
|
+
legendWidth: 200,
|
|
7224
|
+
},
|
|
7225
|
+
})
|
|
7226
|
+
const [chartData, setChartData] = useState([
|
|
7227
|
+
{ hour: '0', day: 'day_0', value: 0 }, { hour: '1', day: 'day_0', value: 2 },
|
|
7228
|
+
{ hour: '2', day: 'day_0', value: 0 }, { hour: '3', day: 'day_0', value: 5 },
|
|
7229
|
+
{ hour: '4', day: 'day_0', value: 0 }, { hour: '5', day: 'day_0', value: 0 },
|
|
7230
|
+
{ hour: '6', day: 'day_0', value: 1 }, { hour: '7', day: 'day_0', value: 3 },
|
|
7231
|
+
{ hour: '8', day: 'day_0', value: 0 }, { hour: '9', day: 'day_0', value: 0 },
|
|
7232
|
+
{ hour: '10', day: 'day_0', value: 4 }, { hour: '11', day: 'day_0', value: 0 },
|
|
7233
|
+
{ hour: '12', day: 'day_0', value: 0 }, { hour: '13', day: 'day_0', value: 2 },
|
|
7234
|
+
{ hour: '14', day: 'day_0', value: 0 }, { hour: '15', day: 'day_0', value: 0 },
|
|
7235
|
+
{ hour: '16', day: 'day_0', value: 6 }, { hour: '17', day: 'day_0', value: 0 },
|
|
7236
|
+
{ hour: '18', day: 'day_0', value: 0 }, { hour: '19', day: 'day_0', value: 1 },
|
|
7237
|
+
{ hour: '20', day: 'day_0', value: 0 }, { hour: '21', day: 'day_0', value: 0 },
|
|
7238
|
+
{ hour: '22', day: 'day_0', value: 3 }, { hour: '23', day: 'day_0', value: 0 },
|
|
7239
|
+
])
|
|
7240
|
+
const chartLocaleProps = [
|
|
7241
|
+
{ name: 'l.unit', locale: 'incidents' },
|
|
7242
|
+
]
|
|
7243
|
+
const chartLocaleMessage = [
|
|
7244
|
+
{ name: 'day_0', locale: 'Mon 4/14' },
|
|
7245
|
+
]
|
|
7246
|
+
|
|
7247
|
+
// 다운로드 함수
|
|
7248
|
+
const handleDownload = (fileType) => {
|
|
7249
|
+
// fileType: 'png' | 'jpg' | 'pdf'
|
|
7250
|
+
// fileOption: { quality?: number } (jpg일 때 품질 0~1)
|
|
7251
|
+
chartRef.current?.downloadFile('heatmap-chart', fileType)
|
|
7252
|
+
}
|
|
7253
|
+
`,
|
|
7254
|
+
code: `<OpsnowCommonHeatmapChart
|
|
7255
|
+
chartId={chartId}
|
|
7256
|
+
ref={chartRef}
|
|
7257
|
+
chartProps={chartProps}
|
|
7258
|
+
chartData={chartData}
|
|
7259
|
+
chartLocaleMessage={chartLocaleMessage}
|
|
7260
|
+
chartLocaleProps={chartLocaleProps}
|
|
7261
|
+
/>
|
|
7262
|
+
<button onClick={() => handleDownload('png')}>Download PNG</button>
|
|
7263
|
+
<button onClick={() => handleDownload('jpg')}>Download JPG</button>
|
|
7264
|
+
<button onClick={() => handleDownload('pdf')}>Download PDF</button>`
|
|
7265
|
+
},
|
|
7266
|
+
];
|
|
@@ -1337,6 +1337,172 @@ export const GaugeChartSchema = z.object({
|
|
|
1337
1337
|
`),
|
|
1338
1338
|
chartValue: z.number().describe("차트 값"),
|
|
1339
1339
|
});
|
|
1340
|
+
// opsnow-common-heatmap-chart
|
|
1341
|
+
export const HeatmapChartSchema = z.object({
|
|
1342
|
+
chartId: z.string().describe("차트의 고유 식별자"),
|
|
1343
|
+
chartProps: z.object({}).describe(`
|
|
1344
|
+
다음 정의된 형식 예를 보고 차트 속성을 설정하세요.
|
|
1345
|
+
**유효한 JSON 형식이어야합니다.**
|
|
1346
|
+
{
|
|
1347
|
+
// 차트 기본 설정
|
|
1348
|
+
"chart": {
|
|
1349
|
+
"paddingTop": 0, // 차트 상단 패딩 (px)
|
|
1350
|
+
"paddingBottom": 0, // 차트 하단 패딩 (px)
|
|
1351
|
+
"paddingLeft": 0, // 차트 좌측 패딩 (px)
|
|
1352
|
+
"paddingRight": 0, // 차트 우측 패딩 (px)
|
|
1353
|
+
"panX": false, // X축 팬 가능 여부
|
|
1354
|
+
"panY": false, // Y축 팬 가능 여부
|
|
1355
|
+
"wheelStep": 0.25, // 줌 휠 단계
|
|
1356
|
+
"scrollbarX": { // X축 스크롤바 설정
|
|
1357
|
+
"height": 6, // 스크롤바 높이 (px)
|
|
1358
|
+
"gripScale": 0 // 그립 크기 비율
|
|
1359
|
+
},
|
|
1360
|
+
"scrollbarY": { // Y축 스크롤바 설정
|
|
1361
|
+
"gripScale": 0 // 그립 크기 비율
|
|
1362
|
+
},
|
|
1363
|
+
"zoomOutButtonHidden": true // 줌 아웃 버튼 숨김 여부
|
|
1364
|
+
},
|
|
1365
|
+
|
|
1366
|
+
// X축 설정
|
|
1367
|
+
"xAxis": {
|
|
1368
|
+
"type": "category", // 축 타입: 'category' (필수)
|
|
1369
|
+
"valueField": "hour", // X축 값 필드명 (chartData의 필드명과 일치해야 함)
|
|
1370
|
+
"categories": ["0", "1", "2"], // 카테고리 명시적 순서 지정 (선택사항, 생략 시 데이터에서 자동 추출)
|
|
1371
|
+
"gridHidden": true, // 격자선 숨김 여부
|
|
1372
|
+
"labelHidden": false, // 라벨 숨김 여부
|
|
1373
|
+
"label": {
|
|
1374
|
+
"fontSize": 11, // 라벨 폰트 크기
|
|
1375
|
+
"maxWidth": 60, // 라벨 최대 너비 (px)
|
|
1376
|
+
"paddingTop": 5, // 라벨 상단 패딩
|
|
1377
|
+
"fontWeight": "normal" // 라벨 폰트 두께
|
|
1378
|
+
},
|
|
1379
|
+
"renderer": {
|
|
1380
|
+
"opposite": true, // X축을 상단에 배치 (기본값: false)
|
|
1381
|
+
"minGridDistance": 20 // 격자선 최소 간격
|
|
1382
|
+
},
|
|
1383
|
+
"startLocation": 0, // 축 시작 위치 (0~1)
|
|
1384
|
+
"endLocation": 1 // 축 끝 위치 (0~1)
|
|
1385
|
+
},
|
|
1386
|
+
|
|
1387
|
+
// Y축 설정
|
|
1388
|
+
"yAxis": {
|
|
1389
|
+
"type": "category", // 축 타입: 'category' (필수)
|
|
1390
|
+
"valueField": "day", // Y축 값 필드명 (chartData의 필드명과 일치해야 함)
|
|
1391
|
+
"categories": ["day_0", "day_1"], // 카테고리 명시적 순서 지정 (선택사항)
|
|
1392
|
+
"gridHidden": true, // 격자선 숨김 여부
|
|
1393
|
+
"labelHidden": false, // 라벨 숨김 여부
|
|
1394
|
+
"label": {
|
|
1395
|
+
"fontSize": 11, // 라벨 폰트 크기
|
|
1396
|
+
"maxWidth": 70, // 라벨 최대 너비 (px)
|
|
1397
|
+
"fontWeight": "bold" // 라벨 폰트 두께
|
|
1398
|
+
},
|
|
1399
|
+
"renderer": {
|
|
1400
|
+
"inversed": true, // Y축 반전 (기본값: true, 위→아래 순서)
|
|
1401
|
+
"minGridDistance": 20 // 격자선 최소 간격
|
|
1402
|
+
},
|
|
1403
|
+
"startLocation": 0, // 축 시작 위치
|
|
1404
|
+
"endLocation": 1 // 축 끝 위치
|
|
1405
|
+
},
|
|
1406
|
+
|
|
1407
|
+
// 시리즈 설정 (단일 ColumnSeries)
|
|
1408
|
+
"series": {
|
|
1409
|
+
"categoryXField": "hour", // X축 카테고리 필드 (기본값: xAxis.valueField)
|
|
1410
|
+
"categoryYField": "day", // Y축 카테고리 필드 (기본값: yAxis.valueField)
|
|
1411
|
+
"valueField": "value", // 값 필드 (기본값: "value")
|
|
1412
|
+
"columns": {
|
|
1413
|
+
"strokeWidth": 2, // 셀 테두리 두께
|
|
1414
|
+
"cornerRadius": 0, // 셀 모서리 둥글기
|
|
1415
|
+
"hover": {
|
|
1416
|
+
"enabled": true, // 호버 효과 활성화
|
|
1417
|
+
"scale": 1, // 호버 시 확대 비율
|
|
1418
|
+
"color": "#d50000" // 호버 시 테두리 색상
|
|
1419
|
+
}
|
|
1420
|
+
},
|
|
1421
|
+
"tooltip": {
|
|
1422
|
+
"type": "CI", // 'CI' (Individual) 고정 — 각 셀별 툴팁
|
|
1423
|
+
"enabled": true, // 툴팁 활성화
|
|
1424
|
+
"header": { "name": "{day} {hour}h" }, // 헤더 텍스트 ({}로 필드 참조)
|
|
1425
|
+
"body": {
|
|
1426
|
+
"name": "", // 바디 이름 (선택사항)
|
|
1427
|
+
"value": "{value} {l.unit}" // 바디 값 ({l.xxx}로 locale 참조)
|
|
1428
|
+
},
|
|
1429
|
+
"label": { "fontSize": 11 } // 툴팁 폰트 크기
|
|
1430
|
+
},
|
|
1431
|
+
"animation": {
|
|
1432
|
+
"duration": 500, // 애니메이션 지속 시간 (ms)
|
|
1433
|
+
"delay": 100 // 애니메이션 지연 시간 (ms)
|
|
1434
|
+
}
|
|
1435
|
+
},
|
|
1436
|
+
|
|
1437
|
+
// 히트맵 색상 규칙 (필수)
|
|
1438
|
+
"heatRule": {
|
|
1439
|
+
"key": "fill", // 변경할 속성: 'fill' (색상)
|
|
1440
|
+
"dataField": "value", // 값 필드 (기본값: "value")
|
|
1441
|
+
"minColor": "#fce4ec", // 최소값 색상 (연한색)
|
|
1442
|
+
"maxColor": "#c62828", // 최대값 색상 (진한색)
|
|
1443
|
+
"minValue": 0, // 최소값 직접 지정 (선택사항, 생략 시 데이터에서 자동 계산)
|
|
1444
|
+
"maxValue": 10 // 최대값 직접 지정 (선택사항)
|
|
1445
|
+
},
|
|
1446
|
+
|
|
1447
|
+
// 범례 설정 (히트맵 그래디언트 범례)
|
|
1448
|
+
"legend": {
|
|
1449
|
+
"orientation": "horizontal", // 방향: 'horizontal' | 'vertical'
|
|
1450
|
+
"labelText": "{l.legendLabel}", // 범례 라벨 ({l.xxx}로 locale 참조)
|
|
1451
|
+
"labelFontSize": 12, // 라벨 폰트 크기
|
|
1452
|
+
"labelFontWeight": "normal", // 라벨 폰트 두께
|
|
1453
|
+
"valueLabelFontSize": 11, // 값 라벨 폰트 크기
|
|
1454
|
+
"legendWidth": 200, // 범례 너비 (px)
|
|
1455
|
+
"barHeight": 16, // 범례 바 높이 (px)
|
|
1456
|
+
"paddingTop": 10, // 상단 패딩
|
|
1457
|
+
"startText": "Low", // 시작 라벨 텍스트
|
|
1458
|
+
"endText": "High", // 끝 라벨 텍스트
|
|
1459
|
+
"stepCount": 5, // 범례 단계 수
|
|
1460
|
+
"reversed": false // 범례 방향 반전
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
`),
|
|
1464
|
+
chartData: z.array(z.record(z.any())).optional().describe(`히트맵에 표시할 데이터 배열입니다. 각 항목은 X축 카테고리, Y축 카테고리, 값 필드를 포함해야 합니다.
|
|
1465
|
+
예시)
|
|
1466
|
+
[
|
|
1467
|
+
{ "hour": "0", "day": "day_0", "value": 3 },
|
|
1468
|
+
{ "hour": "1", "day": "day_0", "value": 0 },
|
|
1469
|
+
{ "hour": "2", "day": "day_0", "value": 5 },
|
|
1470
|
+
{ "hour": "0", "day": "day_1", "value": 1 },
|
|
1471
|
+
{ "hour": "1", "day": "day_1", "value": 7 }
|
|
1472
|
+
]`),
|
|
1473
|
+
chartLocaleProps: z.array(z.object({
|
|
1474
|
+
name: z.string(),
|
|
1475
|
+
locale: z.string()
|
|
1476
|
+
})).optional().describe(`차트에 적용할 다국어 플레이스홀더 목록입니다. {l.xxx} 형태로 chartProps에서 참조합니다.
|
|
1477
|
+
예시)
|
|
1478
|
+
[
|
|
1479
|
+
{ "name": "l.unit", "locale": "건" },
|
|
1480
|
+
{ "name": "l.legendLabel", "locale": "인시던트 수" }
|
|
1481
|
+
]`),
|
|
1482
|
+
chartLocaleData: z.array(z.object({
|
|
1483
|
+
name: z.string().describe("chartData에 정의된 필드 이름"),
|
|
1484
|
+
value: z.string().describe("chartData에 정의된 필드 값 전체 또는 일부"),
|
|
1485
|
+
locale: z.string().describe("chartData에 정의된 필드 다국어 값으로 value에 다국어 값을 적용")
|
|
1486
|
+
})).optional().describe(`차트 데이터에 다국어를 적용합니다.
|
|
1487
|
+
예시)
|
|
1488
|
+
[
|
|
1489
|
+
{ "name": "day", "value": "day_0", "locale": "월요일" }
|
|
1490
|
+
]`),
|
|
1491
|
+
chartLocaleMessage: z.array(z.object({
|
|
1492
|
+
name: z.string().describe("카테고리 키 (chartData의 카테고리 값과 일치)"),
|
|
1493
|
+
locale: z.string().describe("표시할 다국어 텍스트")
|
|
1494
|
+
})).optional().describe(`카테고리 라벨을 다국어 텍스트로 치환합니다. Y축 또는 X축 카테고리의 키를 표시 텍스트로 변환할 때 사용합니다.
|
|
1495
|
+
예시)
|
|
1496
|
+
[
|
|
1497
|
+
{ "name": "day_0", "locale": "월요일 4/14" },
|
|
1498
|
+
{ "name": "day_1", "locale": "화요일 4/15" }
|
|
1499
|
+
]`),
|
|
1500
|
+
chartTooltipDetailText: z.string().optional().describe("툴팁 하단에 표시할 상세 안내 텍스트"),
|
|
1501
|
+
chartNoRowsText: z.string().optional().describe("데이터 없을 때 표시할 텍스트"),
|
|
1502
|
+
langCd: z.enum(['ko', 'en', 'ja', 'zh', 'ar']).optional().describe("언어 코드"),
|
|
1503
|
+
isDarkMode: z.boolean().optional().describe("다크 모드 활성화 여부"),
|
|
1504
|
+
onChartClick: z.string().optional().describe('셀 클릭 시 호출되는 콜백 함수(stringified). 클릭 시 { xField, yField, valueField, from: "heatmap" } 객체를 전달합니다.')
|
|
1505
|
+
});
|
|
1340
1506
|
// Chart 컴포넌트 함수 - 배열 반환
|
|
1341
1507
|
export function createChartComponent() {
|
|
1342
1508
|
return [
|
|
@@ -1639,5 +1805,58 @@ export function createChartComponent() {
|
|
|
1639
1805
|
};
|
|
1640
1806
|
}
|
|
1641
1807
|
},
|
|
1808
|
+
{
|
|
1809
|
+
name: "createHeatmapChart",
|
|
1810
|
+
description: `히트맵 차트 컴포넌트 - 2차원 매트릭스 형태의 데이터 시각화 지원
|
|
1811
|
+
|
|
1812
|
+
**이 차트 컴포넌트는 amCharts5를 기반으로 구현되었습니다.**
|
|
1813
|
+
|
|
1814
|
+
히트맵 차트는 X축과 Y축 모두 카테고리(category) 축을 사용하며,
|
|
1815
|
+
각 셀의 값에 따라 minColor ~ maxColor 사이의 그래디언트로 색상이 결정됩니다.
|
|
1816
|
+
인시던트 발생 패턴(시간×요일), 리소스 사용량 등 2차원 분포 시각화에 적합합니다.
|
|
1817
|
+
|
|
1818
|
+
**import:**
|
|
1819
|
+
\`\`\`javascript
|
|
1820
|
+
import { useCommonComponents } from '@opsnow-common/opsnow-finops-common-ui-loader';
|
|
1821
|
+
const { OpsnowCommonHeatmapChart } = useCommonComponents();
|
|
1822
|
+
\`\`\``,
|
|
1823
|
+
parameters: HeatmapChartSchema,
|
|
1824
|
+
handler: async (args) => {
|
|
1825
|
+
const props = [];
|
|
1826
|
+
if (args.chartId)
|
|
1827
|
+
props.push(`chartId="${args.chartId}"`);
|
|
1828
|
+
if (args.chartProps)
|
|
1829
|
+
props.push(`chartProps={${args.chartProps}}`);
|
|
1830
|
+
if (args.chartData)
|
|
1831
|
+
props.push(`chartData={${args.chartData}}`);
|
|
1832
|
+
else
|
|
1833
|
+
props.push(`chartData={[]}`);
|
|
1834
|
+
if (args.chartLocaleProps)
|
|
1835
|
+
props.push(`chartLocaleProps={${args.chartLocaleProps}}`);
|
|
1836
|
+
if (args.chartLocaleData)
|
|
1837
|
+
props.push(`chartLocaleData={${args.chartLocaleData}}`);
|
|
1838
|
+
if (args.chartLocaleMessage)
|
|
1839
|
+
props.push(`chartLocaleMessage={${args.chartLocaleMessage}}`);
|
|
1840
|
+
if (args.chartTooltipDetailText)
|
|
1841
|
+
props.push(`chartTooltipDetailText="${args.chartTooltipDetailText}"`);
|
|
1842
|
+
if (args.chartNoRowsText)
|
|
1843
|
+
props.push(`chartNoRowsText="${args.chartNoRowsText}"`);
|
|
1844
|
+
if (args.langCd)
|
|
1845
|
+
props.push(`langCd="${args.langCd}"`);
|
|
1846
|
+
if (args.isDarkMode !== undefined)
|
|
1847
|
+
props.push(`isDarkMode={${args.isDarkMode}}`);
|
|
1848
|
+
if (args.onChartClick)
|
|
1849
|
+
props.push(`onChartClick={${args.onChartClick}}`);
|
|
1850
|
+
const code = `<OpsnowCommonHeatmapChart ${props.join(' ')} />`;
|
|
1851
|
+
return {
|
|
1852
|
+
content: [
|
|
1853
|
+
{
|
|
1854
|
+
type: "text",
|
|
1855
|
+
text: `\`\`\`jsx\n${code}\n\`\`\``
|
|
1856
|
+
}
|
|
1857
|
+
]
|
|
1858
|
+
};
|
|
1859
|
+
}
|
|
1860
|
+
},
|
|
1642
1861
|
];
|
|
1643
1862
|
}
|