[feat] validation 추가 중
This commit is contained in:
@@ -2,13 +2,29 @@
|
||||
"dashboardId": "0001",
|
||||
"title": "대시보드 1",
|
||||
"templateId": null,
|
||||
"layout": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 3,
|
||||
"h": 1,
|
||||
"i": "000001"
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": 10,
|
||||
"w": 5,
|
||||
"h": 2,
|
||||
"i": "000002"
|
||||
}
|
||||
],
|
||||
"widgets": [
|
||||
{
|
||||
"id": "000001",
|
||||
"widgetId": "000001",
|
||||
"title": "라인차트 위젯",
|
||||
"date": "2022-04-11T18:27:45+09:00",
|
||||
"dataSetId": "",
|
||||
"type": "lineChart",
|
||||
"dataSetId": "000001",
|
||||
"type": "CHART_LINE",
|
||||
"option": {
|
||||
"xField": "name",
|
||||
"series": [
|
||||
@@ -31,6 +47,36 @@
|
||||
],
|
||||
"legendPosition": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"widgetId": "000002",
|
||||
"title": "파이차트 위젯",
|
||||
"date": "2022-04-11T18:27:45+09:00",
|
||||
"dataSetId": "00001",
|
||||
"type": "CHART_PIE",
|
||||
"option": {
|
||||
"xField": "name",
|
||||
"series": {
|
||||
"field": "high",
|
||||
"color": [
|
||||
"#5470c6",
|
||||
"#91cc75",
|
||||
"#fac858",
|
||||
"#ee6666",
|
||||
"#73c0de",
|
||||
"#3ba272",
|
||||
"#fc8452",
|
||||
"#9a60b4",
|
||||
"#ea7ccc",
|
||||
"#5470c6",
|
||||
"#91cc75",
|
||||
"#fac858"
|
||||
],
|
||||
"aggregation": "",
|
||||
"label": "name"
|
||||
},
|
||||
"legendPosition": "right"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"title": "위젯1",
|
||||
"createDate": "2022-04-11T18:27:45+09:00",
|
||||
"dataId": "",
|
||||
"type": "LINECHART",
|
||||
"type": "CHART_LINE",
|
||||
"option": {
|
||||
"xField": "title",
|
||||
"series": [
|
||||
@@ -33,7 +33,7 @@
|
||||
"title": "위젯2",
|
||||
"createDate": "2022-01-20T13:51:43+09:00",
|
||||
"dataId": "",
|
||||
"type": "PIECHART",
|
||||
"type": "CHART_PIE",
|
||||
"option": {}
|
||||
}
|
||||
]
|
||||
|
||||
98
frontend-web/public/data/sample/chart.json
Normal file
98
frontend-web/public/data/sample/chart.json
Normal file
@@ -0,0 +1,98 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "january",
|
||||
"color": "#00BFFF",
|
||||
"high": 18,
|
||||
"low": 2,
|
||||
"avg": 8.9
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "february",
|
||||
"color": "#4682B4",
|
||||
"high": 23,
|
||||
"low": -2,
|
||||
"avg": 9.9
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "march",
|
||||
"color": "#00CED1",
|
||||
"high": 25,
|
||||
"low": -1,
|
||||
"avg": 11.3
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "april",
|
||||
"color": "#3CB371",
|
||||
"high": 23,
|
||||
"low": 1,
|
||||
"avg": 13
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "may",
|
||||
"color": "#9ACD32",
|
||||
"high": 26,
|
||||
"low": 5,
|
||||
"avg": 16.2
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "june",
|
||||
"color": "#BDB76B",
|
||||
"high": 32,
|
||||
"low": 7,
|
||||
"avg": 19.9
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "july",
|
||||
"color": "#FFD700",
|
||||
"high": 33,
|
||||
"low": 12,
|
||||
"avg": 23
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "august",
|
||||
"color": "#FF8C00",
|
||||
"high": 33,
|
||||
"low": 12,
|
||||
"avg": 23.6
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "september",
|
||||
"color": "#FF7F50",
|
||||
"high": 32,
|
||||
"low": 7,
|
||||
"avg": 21.1
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "october",
|
||||
"color": "#F4A460",
|
||||
"high": 28,
|
||||
"low": 2,
|
||||
"avg": 17
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"name": "november",
|
||||
"color": "#8B4513",
|
||||
"high": 25,
|
||||
"low": -2,
|
||||
"avg": 12.5
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"name": "december",
|
||||
"color": "#778899",
|
||||
"high": 22,
|
||||
"low": -2,
|
||||
"avg": 10
|
||||
}
|
||||
]
|
||||
142
frontend-web/public/data/sample/chart1.json
Normal file
142
frontend-web/public/data/sample/chart1.json
Normal file
@@ -0,0 +1,142 @@
|
||||
[
|
||||
{
|
||||
"year": 1970,
|
||||
"country": "Saudi Arabia",
|
||||
"oil": 192.2
|
||||
},
|
||||
{
|
||||
"year": 1970,
|
||||
"country": "USA",
|
||||
"oil": 533.5
|
||||
},
|
||||
{
|
||||
"year": 1970,
|
||||
"country": "Iran",
|
||||
"oil": 192.6
|
||||
},
|
||||
{
|
||||
"year": 1970,
|
||||
"country": "Mexico",
|
||||
"oil": 24.2
|
||||
},
|
||||
{
|
||||
"year": 1980,
|
||||
"country": "Saudi Arabia",
|
||||
"oil": 509.8
|
||||
},
|
||||
{
|
||||
"year": 1980,
|
||||
"country": "USA",
|
||||
"oil": 480.2
|
||||
},
|
||||
{
|
||||
"year": 1980,
|
||||
"country": "Iran",
|
||||
"oil": 74.3
|
||||
},
|
||||
{
|
||||
"year": 1980,
|
||||
"country": "Mexico",
|
||||
"oil": 107.2
|
||||
},
|
||||
{
|
||||
"year": 1990,
|
||||
"country": "Saudi Arabia",
|
||||
"oil": 342.6
|
||||
},
|
||||
{
|
||||
"year": 1990,
|
||||
"country": "USA",
|
||||
"oil": 416.6
|
||||
},
|
||||
{
|
||||
"year": 1990,
|
||||
"country": "Iran",
|
||||
"oil": 162.8
|
||||
},
|
||||
{
|
||||
"year": 1990,
|
||||
"country": "Mexico",
|
||||
"oil": 146.3
|
||||
},
|
||||
{
|
||||
"year": 1990,
|
||||
"country": "Russia",
|
||||
"oil": 515.9
|
||||
},
|
||||
{
|
||||
"year": 2000,
|
||||
"country": "Saudi Arabia",
|
||||
"oil": 456.3
|
||||
},
|
||||
{
|
||||
"year": 2000,
|
||||
"country": "USA",
|
||||
"oil": 352.6
|
||||
},
|
||||
{
|
||||
"year": 2000,
|
||||
"country": "Iran",
|
||||
"oil": 191.3
|
||||
},
|
||||
{
|
||||
"year": 2000,
|
||||
"country": "Mexico",
|
||||
"oil": 171.2
|
||||
},
|
||||
{
|
||||
"year": 2000,
|
||||
"country": "Russia",
|
||||
"oil": 323.3
|
||||
},
|
||||
{
|
||||
"year": 2008,
|
||||
"country": "Saudi Arabia",
|
||||
"oil": 515.3
|
||||
},
|
||||
{
|
||||
"year": 2008,
|
||||
"country": "USA",
|
||||
"oil": 304.9
|
||||
},
|
||||
{
|
||||
"year": 2008,
|
||||
"country": "Iran",
|
||||
"oil": 209.9
|
||||
},
|
||||
{
|
||||
"year": 2008,
|
||||
"country": "Mexico",
|
||||
"oil": 157.7
|
||||
},
|
||||
{
|
||||
"year": 2008,
|
||||
"country": "Russia",
|
||||
"oil": 488.5
|
||||
},
|
||||
{
|
||||
"year": 2009,
|
||||
"country": "Saudi Arabia",
|
||||
"oil": 459.5
|
||||
},
|
||||
{
|
||||
"year": 2009,
|
||||
"country": "USA",
|
||||
"oil": 325.3
|
||||
},
|
||||
{
|
||||
"year": 2009,
|
||||
"country": "Iran",
|
||||
"oil": 202.4
|
||||
},
|
||||
{
|
||||
"year": 2009,
|
||||
"country": "Mexico",
|
||||
"oil": 147.5
|
||||
},
|
||||
{
|
||||
"year": 2009,
|
||||
"country": "Russia",
|
||||
"oil": 494.2
|
||||
}
|
||||
]
|
||||
126
frontend-web/public/data/sample/chart2.json
Normal file
126
frontend-web/public/data/sample/chart2.json
Normal file
@@ -0,0 +1,126 @@
|
||||
[
|
||||
{
|
||||
"day": "1",
|
||||
"value": 11
|
||||
},
|
||||
{
|
||||
"day": "2",
|
||||
"value": 7
|
||||
},
|
||||
{
|
||||
"day": "3",
|
||||
"value": 6
|
||||
},
|
||||
{
|
||||
"day": "4",
|
||||
"value": 8
|
||||
},
|
||||
{
|
||||
"day": "5",
|
||||
"value": 7
|
||||
},
|
||||
{
|
||||
"day": "6",
|
||||
"value": 7
|
||||
},
|
||||
{
|
||||
"day": "7",
|
||||
"value": 11
|
||||
},
|
||||
{
|
||||
"day": "8",
|
||||
"value": 9
|
||||
},
|
||||
{
|
||||
"day": "9",
|
||||
"value": 5
|
||||
},
|
||||
{
|
||||
"day": "10",
|
||||
"value": 8
|
||||
},
|
||||
{
|
||||
"day": "11",
|
||||
"value": 6
|
||||
},
|
||||
{
|
||||
"day": "12",
|
||||
"value": 9
|
||||
},
|
||||
{
|
||||
"day": "13",
|
||||
"value": 8
|
||||
},
|
||||
{
|
||||
"day": "14",
|
||||
"value": 6
|
||||
},
|
||||
{
|
||||
"day": "15",
|
||||
"value": 6
|
||||
},
|
||||
{
|
||||
"day": "16",
|
||||
"value": 6
|
||||
},
|
||||
{
|
||||
"day": "17",
|
||||
"value": 10
|
||||
},
|
||||
{
|
||||
"day": "18",
|
||||
"value": 9
|
||||
},
|
||||
{
|
||||
"day": "19",
|
||||
"value": 12
|
||||
},
|
||||
{
|
||||
"day": "20",
|
||||
"value": 9
|
||||
},
|
||||
{
|
||||
"day": "21",
|
||||
"value": 8
|
||||
},
|
||||
{
|
||||
"day": "22",
|
||||
"value": 13
|
||||
},
|
||||
{
|
||||
"day": "23",
|
||||
"value": 9
|
||||
},
|
||||
{
|
||||
"day": "24",
|
||||
"value": 7
|
||||
},
|
||||
{
|
||||
"day": "25",
|
||||
"value": 6
|
||||
},
|
||||
{
|
||||
"day": "26",
|
||||
"value": 11
|
||||
},
|
||||
{
|
||||
"day": "27",
|
||||
"value": 8
|
||||
},
|
||||
{
|
||||
"day": "28",
|
||||
"value": 7
|
||||
},
|
||||
{
|
||||
"day": "29",
|
||||
"value": 9
|
||||
},
|
||||
{
|
||||
"day": "30",
|
||||
"value": 7
|
||||
},
|
||||
{
|
||||
"day": "31",
|
||||
"value": 3
|
||||
}
|
||||
]
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { CssBaseline } from '@mui/material';
|
||||
import Layout from './layouts/Layout';
|
||||
import Router from './router';
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Divider, Box, Stack, Typography } from '@mui/material';
|
||||
|
||||
function WidgetWrapper(props) {
|
||||
const { title, width, button } = props;
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
width: width,
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ width: '100%', py: 1 }}>
|
||||
<Typography variant="subtitle1" component="span" sx={{ fontWeight: 500 }}>
|
||||
{title}
|
||||
</Typography>
|
||||
{button}
|
||||
</Stack>
|
||||
<Divider sx={{ marginBottom: 4 }} />
|
||||
{props.children}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
WidgetWrapper.defaultProps = {
|
||||
title: '',
|
||||
width: '100%',
|
||||
menuList: false,
|
||||
naviUrl: false,
|
||||
button: false,
|
||||
};
|
||||
|
||||
export default WidgetWrapper;
|
||||
@@ -9,11 +9,9 @@ import './index.css';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<ThemeProvider theme={theme}>
|
||||
<App />
|
||||
</ThemeProvider>
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>,
|
||||
<BrowserRouter>
|
||||
<ThemeProvider theme={theme}>
|
||||
<App />
|
||||
</ThemeProvider>
|
||||
</BrowserRouter>,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
import { Box } from '@mui/material';
|
||||
|
||||
const LineChart = props => {
|
||||
const { option, dataSet, ...rest } = props;
|
||||
@@ -25,8 +26,10 @@ const LineChart = props => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const newOption = createComponentOption();
|
||||
setComponentOption(newOption);
|
||||
if (option && dataSet) {
|
||||
const newOption = createComponentOption();
|
||||
setComponentOption(newOption);
|
||||
}
|
||||
}, [option, dataSet]);
|
||||
|
||||
/**
|
||||
@@ -41,13 +44,12 @@ const LineChart = props => {
|
||||
// series option에서 가져오기
|
||||
const newSeries = [];
|
||||
const newColors = [];
|
||||
option.series.forEach((item, index) => {
|
||||
// console.log(item, index);
|
||||
option.series.forEach(item => {
|
||||
if (item.field) {
|
||||
const series = {
|
||||
name: item.field,
|
||||
data: dataSet.map(dataItem => dataItem[item.field]),
|
||||
type: rest.componentType,
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
};
|
||||
newSeries.push(series);
|
||||
@@ -72,7 +74,14 @@ const LineChart = props => {
|
||||
};
|
||||
|
||||
return (
|
||||
<ReactECharts option={componentOption} style={{ height: '100%', width: '100%' }} lazyUpdate={true} notMerge={true} />
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<ReactECharts option={componentOption} style={{ height: '100%', width: '100%' }} lazyUpdate={true} notMerge={true} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import ReactECharts from 'echarts-for-react';
|
||||
|
||||
const PieChart = props => {
|
||||
@@ -15,16 +15,7 @@ const PieChart = props => {
|
||||
orient: 'vertical',
|
||||
left: 'left',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
smooth: true,
|
||||
},
|
||||
{
|
||||
type: 'pie',
|
||||
smooth: true,
|
||||
},
|
||||
],
|
||||
series: [],
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
@@ -35,7 +26,7 @@ const PieChart = props => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('PieChart ', option, dataSet);
|
||||
setComponentOption(defaultComponentOption);
|
||||
setComponentOption(createComponentOption());
|
||||
}, [option, dataSet]);
|
||||
|
||||
@@ -45,30 +36,28 @@ const PieChart = props => {
|
||||
* 컴포넌트에 맞는 형태로 생성
|
||||
*/
|
||||
const createComponentOption = () => {
|
||||
let newOption = defaultComponentOption;
|
||||
let newOption = { ...defaultComponentOption };
|
||||
|
||||
const getData = () =>
|
||||
dataSet.map(item => ({
|
||||
value: item[option.series.field],
|
||||
name: item[option.series.label],
|
||||
}));
|
||||
|
||||
if (dataSet) {
|
||||
const op = {
|
||||
type: 'pie',
|
||||
smooth: true,
|
||||
color: [...option.series.color],
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
smooth: true,
|
||||
data: getData(),
|
||||
color: option.series.color, // 옵션값은 바뀌는데 색은 왜 제때 안 바뀔까요..
|
||||
},
|
||||
],
|
||||
};
|
||||
newOption = { ...defaultComponentOption, ...op };
|
||||
}
|
||||
|
||||
return newOption;
|
||||
};
|
||||
|
||||
|
||||
@@ -13,24 +13,51 @@ import '/node_modules/react-resizable/css/styles.css';
|
||||
const ResponsiveGridLayout = WidthProvider(Responsive);
|
||||
|
||||
function DashboardModify(props) {
|
||||
const layout = [
|
||||
{ i: 'a', x: 0, y: 0, w: 1, h: 2, static: true },
|
||||
{ i: 'b', x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 },
|
||||
{ i: 'c', x: 4, y: 0, w: 1, h: 2 },
|
||||
];
|
||||
|
||||
// const layout = [
|
||||
// { i: 'a', x: 0, y: 0, w: 1, h: 2, static: true },
|
||||
// { i: 'b', x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 },
|
||||
// { i: 'c', x: 4, y: 0, w: 1, h: 2 },
|
||||
// ];
|
||||
// 현재 선택된 widget 목록
|
||||
const [selectedWidgets, setSelectedWidgets] = useState([]);
|
||||
// 화면에 그려질 widget 목록
|
||||
const [widgets, setWidgets] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
// 여기서 처리
|
||||
if (selectedWidgets.length > 0) {
|
||||
console.log(selectedWidgets);
|
||||
// console.log(selectedWidgets);
|
||||
}
|
||||
}, [selectedWidgets]);
|
||||
|
||||
useEffect(() => {
|
||||
// 여기서 처리
|
||||
if (widgets.length > 0) {
|
||||
console.log(widgets);
|
||||
}
|
||||
}, [widgets]);
|
||||
|
||||
// 현재 위젯 선택창에서 선택된 위젯 목록 callback
|
||||
const handleWidgetSelect = items => {
|
||||
setSelectedWidgets(items);
|
||||
};
|
||||
|
||||
const onAddItems = items => {
|
||||
// console.log('adding', 'n' + this.state.newCounter);
|
||||
// this.setState({
|
||||
// // Add a new item. It must have a unique key!
|
||||
// items: this.state.items.concat({
|
||||
// i: "n" + this.state.newCounter,
|
||||
// x: (this.state.items.length * 2) % (this.state.cols || 12),
|
||||
// y: Infinity, // puts it at the bottom
|
||||
// w: 2,
|
||||
// h: 2
|
||||
// }),
|
||||
// // Increment the counter to ensure key is always unique.
|
||||
// newCounter: this.state.newCounter + 1
|
||||
// });
|
||||
};
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<PageTitleBox
|
||||
@@ -67,10 +94,10 @@ function DashboardModify(props) {
|
||||
backgroundColor: '#eee',
|
||||
}}
|
||||
>
|
||||
<ResponsiveGridLayout layout={layout} rowHeight={54} compactType={null} cols={{ lg: 20 }}>
|
||||
<Card key="a">a</Card>
|
||||
<Card key="b">b</Card>
|
||||
<Card key="c">c</Card>
|
||||
<ResponsiveGridLayout rowHeight={54} compactType={null} cols={{ lg: 20 }}>
|
||||
{/*<Card key="a">a</Card>*/}
|
||||
{/*<Card key="b">b</Card>*/}
|
||||
{/*<Card key="c">c</Card>*/}
|
||||
</ResponsiveGridLayout>
|
||||
</Box>
|
||||
</PageTitleBox>
|
||||
|
||||
@@ -1,50 +1,110 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { Box, IconButton, Stack } from '@mui/material';
|
||||
import { Link as RouterLink, useLocation, useSearchParams } from 'react-router-dom';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Box, Card, IconButton, Stack } from '@mui/material';
|
||||
import { Link as RouterLink, useLocation, useMatch, useSearchParams } from 'react-router-dom';
|
||||
import AutorenewIcon from '@mui/icons-material/Autorenew';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import PageTitleBox from '@/components/PageTitleBox';
|
||||
import TitleBox from '@/components/TitleBox';
|
||||
import { DialogAlertIconButton } from '@/components/button/DialogAlertButton';
|
||||
import WidgetWrapper from '@/widget/wrapper/WidgetWrapper';
|
||||
import { get } from '@/helpers/apiHelper';
|
||||
import BoardListItem from '@/components/BoardListItem';
|
||||
import RGL, { Responsive, WidthProvider } from 'react-grid-layout';
|
||||
import '/node_modules/react-grid-layout/css/styles.css';
|
||||
import '/node_modules/react-resizable/css/styles.css';
|
||||
|
||||
const ResponsiveGridLayout = WidthProvider(Responsive);
|
||||
|
||||
const DashboardView = props => {
|
||||
const location = useLocation();
|
||||
const dashboardId = '222';
|
||||
const dashboardName = '111';
|
||||
const match = useMatch('/dashboard/:dashboard_id');
|
||||
const [dashboardInfo, setDashboardInfo] = useState({ title: '', widgets: [], layout: [] });
|
||||
|
||||
const [dashboardId, setDashboardId] = useState(null);
|
||||
|
||||
const ReactGridLayout = WidthProvider(RGL);
|
||||
const layout = [
|
||||
{
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 2,
|
||||
i: '0',
|
||||
static: true,
|
||||
},
|
||||
{
|
||||
x: 6,
|
||||
y: 0,
|
||||
w: 6,
|
||||
h: 3,
|
||||
i: '1',
|
||||
static: true,
|
||||
},
|
||||
];
|
||||
useEffect(() => {
|
||||
console.log('location : ', location);
|
||||
console.log('props.match : ', props);
|
||||
setDashboardId(match.params.dashboard_id);
|
||||
getDashboardInfo(match.params.dashboard_id);
|
||||
}, []);
|
||||
|
||||
const handleRenewClick = () => {
|
||||
console.log('renew');
|
||||
const getDashboardInfo = id => {
|
||||
get('/data/dummyDashboardInfo.json').then(response => {
|
||||
setDashboardInfo(response.data);
|
||||
});
|
||||
};
|
||||
|
||||
const handleRefreshClick = () => {
|
||||
getDashboardInfo(match.params.dashboard_id);
|
||||
};
|
||||
|
||||
const generateWidget = () => {
|
||||
console.log('generateWidget', dashboardInfo.widgets);
|
||||
return dashboardInfo.widgets.map((item, index) => {
|
||||
console.log('data', item);
|
||||
return (
|
||||
<Card key={index} sx={{ width: '100%', height: '100%', borderRadius: 1 }}>
|
||||
<WidgetWrapper
|
||||
widgetOption={item}
|
||||
dataSetId={item.dataSetId}
|
||||
sx={{ width: '100%', height: '100%', borderRadius: 1 }}
|
||||
/>
|
||||
</Card>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<PageTitleBox title="대시보드 조회">
|
||||
<TitleBox
|
||||
title={dashboardName}
|
||||
title={dashboardInfo.title}
|
||||
button={
|
||||
<Stack direction="row" spacing={1}>
|
||||
<IconButton onClick={handleRenewClick} aria-label="새로고침" color="primary">
|
||||
<IconButton onClick={handleRefreshClick} aria-label="새로고침" color="primary">
|
||||
<AutorenewIcon />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
component={RouterLink}
|
||||
to={`/dashboard/modify?id=${dashboardId}&name=${dashboardName}`}
|
||||
to={`/dashboard/modify?id=${dashboardId}&name=${dashboardInfo.title}`}
|
||||
aria-label="수정"
|
||||
>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
<DialogAlertIconButton size="small" icon={<DeleteIcon />}>
|
||||
{`<${dashboardName}>을 삭제하시겠습니까?`}
|
||||
{`<${dashboardInfo.title}>을 삭제하시겠습니까?`}
|
||||
</DialogAlertIconButton>
|
||||
</Stack>
|
||||
}
|
||||
>
|
||||
<Box sx={{ width: '100%', height: '50vw', borderRadius: 1, backgroundColor: '#eee' }} />
|
||||
<Box
|
||||
sx={{
|
||||
width: '1280px',
|
||||
minHeight: '1080px',
|
||||
borderRadius: 1,
|
||||
backgroundColor: '#eee',
|
||||
}}
|
||||
>
|
||||
<ReactGridLayout layout={layout}>{generateWidget()}</ReactGridLayout>
|
||||
</Box>
|
||||
</TitleBox>
|
||||
</PageTitleBox>
|
||||
);
|
||||
|
||||
@@ -4,8 +4,7 @@ import PageTitleBox from '@/components/PageTitleBox';
|
||||
import BoardList from '@/components/BoardList';
|
||||
import { Outlet, useParams } from 'react-router-dom';
|
||||
import AddIconButton from '@/components/button/AddIconButton';
|
||||
// import { get } from '@/helpers/apiHelper';
|
||||
import axios from 'axios';
|
||||
import { get } from '@/helpers/apiHelper';
|
||||
|
||||
const title = '대시보드';
|
||||
|
||||
@@ -17,8 +16,7 @@ function Dashboard(props) {
|
||||
const [loadedCount, setLoadedCount] = useState(1);
|
||||
|
||||
useEffect(() => {
|
||||
axios
|
||||
.get('/data/dummyDashboardList.json')
|
||||
get('/data/dummyDashboardList.json')
|
||||
.then(response => response.data)
|
||||
.then(data => setLoadedWidgetData(data.filter((list, idx) => idx <= 10 * loadedCount)));
|
||||
setIsLoading(true);
|
||||
|
||||
@@ -24,6 +24,8 @@ function WidgetAttributeSelect(props) {
|
||||
const [switchChart, setSwitchChart] = useState(defaultChart);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('option changed', option);
|
||||
|
||||
const ChartProps = {
|
||||
option: option,
|
||||
dataSet: chartData,
|
||||
|
||||
@@ -35,8 +35,7 @@ function WidgetCreate(props) {
|
||||
|
||||
const [isWidgetValueValid, setIsWidgetValueValid] = useState(false);
|
||||
const [isNextButtonDisabled, setIsNextButtonDisabled] = useState(true);
|
||||
// const [isSubmit, setIsSubmit] = useState(false);
|
||||
const isSubmit = false;
|
||||
const [isSubmit, setIsSubmit] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeStep === 0 && !!dataSet) {
|
||||
@@ -65,20 +64,17 @@ function WidgetCreate(props) {
|
||||
};
|
||||
|
||||
// 위젯 속성 저장
|
||||
const handleSubmitClick = event => {
|
||||
const handleSubmit = event => {
|
||||
event.preventDefault();
|
||||
// isSubmit = true;
|
||||
|
||||
console.log(event);
|
||||
|
||||
return false;
|
||||
// if (!isWidgetValueValid) {
|
||||
// return;
|
||||
// }
|
||||
// console.log('datesetId:', dataSet);
|
||||
// console.log('widgetType:', widgetType);
|
||||
// console.log('widgetTitle:', widgetTitle);
|
||||
// console.log('widgetOption:', widgetOption);
|
||||
setIsSubmit(true);
|
||||
console.log('widgetOption:', widgetOption);
|
||||
if (!isWidgetValueValid) {
|
||||
return;
|
||||
}
|
||||
console.log('datesetId:', dataSet);
|
||||
console.log('widgetType:', widgetType);
|
||||
console.log('widgetTitle:', widgetTitle);
|
||||
console.log('widgetOption:', widgetOption);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -33,7 +33,7 @@ function WidgetModify(props) {
|
||||
|
||||
// 위젯 속성 저장
|
||||
const handleSubmit = event => {
|
||||
// datasetId , componentId, widgetTitle, option
|
||||
// dataSetId , componentId, widgetTitle, option
|
||||
event.preventDefault();
|
||||
console.log('datesetId:', data.dataId);
|
||||
console.log('widgetType:', data.type);
|
||||
|
||||
@@ -4,8 +4,7 @@ import PageContainer from '@/components/PageContainer';
|
||||
import PageTitleBox from '@/components/PageTitleBox';
|
||||
import BoardList from '@/components/BoardList';
|
||||
import AddIconButton from '@/components/button/AddIconButton';
|
||||
// import { get } from '@/helpers/apiHelper';
|
||||
import axios from 'axios';
|
||||
import { get } from '@/helpers/apiHelper';
|
||||
|
||||
const title = '위젯';
|
||||
|
||||
@@ -17,8 +16,7 @@ function Widget() {
|
||||
const [loadedCount, setLoadedCount] = useState(1);
|
||||
|
||||
useEffect(() => {
|
||||
axios
|
||||
.get('/data/dummyWidgetList.json')
|
||||
get('/data/dummyWidgetList.json')
|
||||
.then(response => response.data)
|
||||
.then(data => setLoadedWidgetData(data.filter((list, idx) => idx <= 10 * loadedCount)));
|
||||
setIsLoading(true);
|
||||
|
||||
@@ -1,14 +1,72 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Box, Divider, Stack, Typography } from '@mui/material';
|
||||
import { WIDGET_TYPE } from '@/constant';
|
||||
import LineChart from '@/modules/linechart/LineChart';
|
||||
import { get } from '@/helpers/apiHelper';
|
||||
import LineChartSetting from '@/widget/settings/LineChartSetting';
|
||||
import PieChart from '@/modules/piechart/PieChart';
|
||||
import PieChartSetting from '@/widget/settings/PieChartSetting';
|
||||
|
||||
const WidgetWrapper = props => {
|
||||
const { widgetId } = props;
|
||||
const { widgetOption, dataSetId } = props;
|
||||
|
||||
const [widget, setWidget] = useState(null);
|
||||
useEffect(() => {
|
||||
if (widgetId) {
|
||||
console.log('widgetId : ', widgetId);
|
||||
console.log('WidgetWrapper');
|
||||
|
||||
if (dataSetId) {
|
||||
getData();
|
||||
}
|
||||
}, [widgetId]);
|
||||
return <Box></Box>;
|
||||
}, []);
|
||||
|
||||
const getData = () => {
|
||||
get('/data/sample/chart.json').then(response => {
|
||||
console.log('res', response.data);
|
||||
if (widgetOption) {
|
||||
console.log('widget widgetOption : ', widgetOption);
|
||||
const widgetType = widgetOption.type;
|
||||
let module = null;
|
||||
switch (widgetType) {
|
||||
case WIDGET_TYPE.CHART_LINE:
|
||||
module = <LineChart option={widgetOption.option} dataSet={response.data} />;
|
||||
break;
|
||||
case WIDGET_TYPE.CHART_BAR:
|
||||
break;
|
||||
case WIDGET_TYPE.CHART_PIE:
|
||||
module = <PieChart option={widgetOption.option} dataSet={response.data} />;
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
setWidget(module);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack
|
||||
sx={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
border: '1px solid #DADDDD',
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center" sx={{ width: '100%', py: 1 }}>
|
||||
<Typography variant="subtitle1" component="span" sx={{ fontWeight: 500 }}>
|
||||
{widgetOption && widgetOption.title}
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Divider sx={{ marginBottom: 4 }} />
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
{widget}
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default WidgetWrapper;
|
||||
|
||||
3
package-lock.json
generated
Normal file
3
package-lock.json
generated
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"lockfileVersion": 1
|
||||
}
|
||||
Reference in New Issue
Block a user