Browse Source

비행경로 test 탭 생성

pull/2/head
junh_eee 2 years ago
parent
commit
a9debf1e9d
  1. 11
      src/@core/layouts/components/navbar/NavbarUser.js
  2. 10
      src/components/mapDraw/MapControlDraw.js
  3. 5629
      src/components/mapDraw/geojson/airArea.json
  4. 24
      src/components/mapDraw/google/DronMarker.js
  5. 64
      src/components/mapDraw/google/GoogleMap.js
  6. 107
      src/components/mapDraw/naver/NaverMap.js
  7. 31
      src/components/mapDraw/naver/NaverMapControl.js
  8. 129
      src/components/mapDraw/naver/draw/DrawPath.js
  9. 71
      src/components/mapDraw/naver/draw/DrawTest0.js
  10. 157
      src/components/mapDraw/naver/draw/DrawTest1.js
  11. 180
      src/components/mapDraw/naver/draw/DrawTest2.js
  12. 63
      src/components/mapDraw/naver/dron/DronHistory.js
  13. 158
      src/components/mapDraw/naver/dron/DronMarker.js
  14. 150
      src/components/mapDraw/naver/feature/FeatureAirZone.js
  15. 25
      src/components/mapDraw/naver/search/NaverMapSearch.js
  16. 488
      src/components/mapDraw/naver/sensor/SensorZone.js
  17. 42
      src/components/mapDraw/nhn/NMap.js
  18. 62
      src/components/mapDraw/nhn/NMapMarker.js
  19. 47
      src/components/mapDraw/nhn/NMapPolyline.js
  20. 4
      src/modules/control/map/actions/controlMapActions.ts
  21. 10
      src/modules/control/map/reducers/controlMapReducer.ts
  22. 7
      src/router/routes/index.js
  23. 66
      src/views/testDraw/alarm/ControlAlarmList.js
  24. 45
      src/views/testDraw/alarm/ControlAlarmNotice.js
  25. 18
      src/views/testDraw/index.js
  26. 183
      src/views/testDraw/main/ControlMainDraw.js
  27. 10
      src/views/testDraw/menu/ControlMenuLeft.js
  28. 219
      src/views/testDraw/report/ControlReportDetail.js
  29. 115
      src/views/testDraw/report/ControlReportList.js
  30. 244
      src/views/testDraw/setting/ControlSetting.js
  31. 233
      src/views/testDraw/weather/WeatherList.js

11
src/@core/layouts/components/navbar/NavbarUser.js

@ -92,6 +92,17 @@ const NavbarUser = props => {
드론 관제 시스템
</NavLink>
</NavItem>
<NavItem>
<NavLink
onClick={() => window.open('/testDraw', '_blank')}
// active={active === '2'}
// onClick={() => {
// toggle('2')
// }}
>
버퍼 테스트
</NavLink>
</NavItem>
</Nav>
{/* <div className='bookmark-wrapper d-flex align-items-center'>
<NavItem className='d-none d-lg-block'>

10
src/components/mapDraw/MapControlDraw.js

@ -0,0 +1,10 @@
import React from 'react';
import { GoogleCustomMap } from './google/GoogleMap';
import { NaverCustomMap } from './naver/NaverMap';
export const MapControlDraw = props => {
// console.log('```````````````````````');
return (
<>{props.mapType === 'google' ? <GoogleCustomMap /> : <NaverCustomMap />}</>
);
};

5629
src/components/mapDraw/geojson/airArea.json

File diff suppressed because it is too large Load Diff

24
src/components/mapDraw/google/DronMarker.js

@ -0,0 +1,24 @@
import React from 'react';
import { useEffect, useRef, useState } from 'react';
import InfoBox from 'react-google-maps/lib/components/addons/InfoBox';
import Marker from 'react-google-maps/lib/components/Marker';
import OverlayView from 'react-google-maps/lib/components/OverlayView';
import dronicon from '../../../assets/control/icon/drone.png';
import { useDispatch, useSelector } from 'react-redux';
import { ControlGpData } from '../../../modules/control/gp';
import { StoreState } from '../../../modules';
export const DronMarker = props => {
return (
<Marker
key={props.dronInfo.objectId}
icon={{
url: dronicon,
scaledSize: new window.google.maps.Size(25, 25)
}}
title={props.dronInfo.objectId}
onClick={() => alert(11111)}
position={{ lat: props.dronInfo.lat, lng: props.dronInfo.lng }}
></Marker>
);
};

64
src/components/mapDraw/google/GoogleMap.js

@ -0,0 +1,64 @@
import React, { useEffect, useState } from 'react';
import {
GoogleMap,
GroundOverlay,
Marker,
Polyline,
withGoogleMap,
withScriptjs
} from 'react-google-maps';
import { DronMarker } from './DronMarker';
// import { StoreState } from '../../../modules';
import { useSelector } from 'react-redux';
import SearchBox from 'react-google-maps/lib/components/places/SearchBox';
import InfoWindow from 'react-google-maps/lib/components/InfoWindow';
const MapInit = () => {
const { controlGpList } = useSelector(state => state.controlGpState);
const [bounds, setBounds] = useState(null);
useEffect(() => {
console.log('GoogleMap >>>>>', controlGpList);
}, [controlGpList]);
const onSearchBoxMounted = () => {};
const onPlacesChanged = () => {};
return (
<>
<GoogleMap
defaultZoom={10}
defaultCenter={{ lat: 37.5, lng: 127 }}
defaultOptions={{}}
>
<div style={{ height: 100 }}>test</div>
{controlGpList?.map(item => (
// <DronMarker controlGpList={controlGpList} />
<DronMarker dronInfo={item} key={item.objectId} />
))}
</GoogleMap>
</>
);
};
const GoogleMapWrapped = withScriptjs(withGoogleMap(MapInit));
export const GoogleCustomMap = () => {
const mapProps = {
key: 'AIzaSyDKCsI8cbzgi4es3xCUIhElUm6NRM73QuI',
url: 'https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=drawing,geometryplaces'
};
console.log(`${mapProps.url}&key=${mapProps.key}`);
return (
<div style={{ width: '100vw', height: '100vh' }}>
<GoogleMapWrapped
googleMapURL={`${mapProps.url}&key=${mapProps.key}`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `100%` }} />}
mapElement={<div style={{ height: `100%` }} />}
/>
</div>
);
};

107
src/components/mapDraw/naver/NaverMap.js

@ -0,0 +1,107 @@
import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import dronicon from '../../../assets/control/icon/drone.png';
import { DronMarker } from './dron/DronMarker';
import { DronHistory } from './dron/DronHistory';
import NaverMapControl from './NaverMapControl';
import { NaverMapSearch } from './search/NaverMapSearch';
import { FeatureAirZone } from './feature/FeatureAirZone';
import { DrawPath } from './draw/DrawPath';
import { DrawTest0 } from './draw/DrawTest0';
import { DrawTest1 } from './draw/DrawTest1';
import { DrawTest2 } from './draw/DrawTest2';
import geoJson from '../geojson/airArea.json';
import SensorZone from "./sensor/SensorZone";
export const NaverCustomMap = () => {
const naver = window.naver;
let map;
const [isMapLoad, setIsMapLoad] = useState(false);
const [mapObject, setMapObject] = useState(null);
let arrMarkers = []; // 마커 배열
let arrPolyline = []; // 폴리라인 배열
let features = geoJson.features;
useEffect(() => {
NaverMapInit();
// console.log(map);
// console.log(features);
// setIsMapLoad(true);
}, []);
useEffect(() => {
// console.log('==============11111==================', mapObject);
}, [mapObject]);
const removeArrMarkers = arrData => {
arrMarkers = arrData;
};
const NaverMapInit = () => {
const mapOptions = {
// center: new naver.maps.LatLng(36.56793936069445, 127.85101412107547),
center: new naver.maps.LatLng(37.445949, 126.673868),
zoom: 13,
zoomControl: true,
mapTypeId: naver.maps.MapTypeId.HYBRID,
zoomControlOptions: {
position: naver.maps.Position.TOP_LEFT,
style: naver.maps.ZoomControlStyle.SMALL
}
};
// map = ;
setMapObject(new naver.maps.Map('map', mapOptions));
// naver.maps.Event.addListener(map, 'click', function (e) {
// console.log(e);
// });
// naver.maps.Event.addListener(map, 'idle', function (e) {
// console.log(e);
// });
};
return (
<>
<div id='map' style={{ width: '100%', height: '100vh' }}></div>
{mapObject != null ? (
<>
{/* <DronMarker
map={mapObject}
naver={naver}
arrMarkers={arrMarkers}
removeArrMarkers={removeArrMarkers}
test={test}
/> */}
<NaverMapControl map={mapObject} />
{/* <DronHistory
map={mapObject}
naver={naver}
arrPolyline={arrPolyline}
/> */}
<FeatureAirZone map={mapObject} naver={naver} features={features} />
{/* <NaverMapSearch map={mapObject} naver={naver} /> */}
{/* <SensorZone map={mapObject} naver={naver} /> */}
{/* <DrawLine map={mapObject} naver={naver} /> */}
{/* <DrawTest2 map={mapObject} naver={naver} /> */}
{/* <DrawTest map={mapObject} naver={naver} /> */}
<DrawPath map={mapObject} naver={naver} />
</>
) : null}
{/* */}
</>
);
};

31
src/components/mapDraw/naver/NaverMapControl.js

@ -0,0 +1,31 @@
import { useEffect } from 'react';
import { useSelector } from 'react-redux';
const NaverMapControl = props => {
const mapControl = useSelector(state => state.controlMapReducer);
useEffect(() => {
}, [mapControl]);
//맵타입 변경
if (mapControl.mapType === 'NORMAL') {
props.map.setMapTypeId(naver.maps.MapTypeId.NORMAL);
} else if (mapControl.mapType === 'TERRAIN') {
props.map.setMapTypeId(naver.maps.MapTypeId.TERRAIN);
} else if (mapControl.mapType === 'HYBRID') {
props.map.setMapTypeId(naver.maps.MapTypeId.HYBRID);
}
//그리기타입 변경
// if(mapControl.drawType === 'CIRCLE') {
// console.log("circle")
// } else if(mapControl.drawType === 'LINE') {
// console.log("line")
// } else if(mapControl.drawType === 'POLYGON') {
// console.log("polygon")
// }
return null;
};
export default NaverMapControl;

129
src/components/mapDraw/naver/draw/DrawPath.js

@ -0,0 +1,129 @@
import { useEffect, useState } from "react";
import { BiCaretLeftCircle } from "react-icons/bi";
import { useSelector } from "react-redux";
export const DrawPath = props => {
const {naver} = props;
const {map} = props;
const {drawType} = useSelector(state => state.controlMapReducer);
let linePath = ([]);
let circleCenter = '';
// let events = ([]);
const [eventGroup, setEventGroup] = useState([]);
const [polylines, setPolylines] = useState([]);
const [circleLayers, setCircleLayers] = useState([]);
useEffect(() => {
init();
}, [drawType]);
useEffect(() => {
}, [eventGroup]);
useEffect(() => {
moveCircle();
}, [circleLayers]);
const init = () => {
removeEvent();
removeLayers();
}
const removeEvent = () => {
eventGroup.forEach(prev => naver.maps.Event.removeListener(prev));
setEventGroup([]);
addEvent();
}
const removeLayers = () => {
if(polylines) {
polylines.forEach(prev => prev.setMap(null));
setPolylines([]);
};
if(circleLayers) {
circleLayers.forEach(prev => prev.setMap(null));
setCircleLayers([]);
};
linePath = [];
// circleCenter = '';
}
const addEvent = () => {
let addClick = naver.maps.Event.addListener(map, 'click', function(e) {
if(drawType) {
linePath.push(e.coord);
circleCenter = e.coord;
startDraw();
} else {
// console.log('1');
}
});
let escDown = naver.maps.Event.addListener(map, 'keydown', function(e) {
const keyboardEvent = e.keyboardEvent,
keyCode = keyboardEvent.keyCode || keyboardEvent.which;
const ESC = 27;
if(keyCode === ESC) {
keyboardEvent.preventDefault();
// removeLayers();
}
});
setEventGroup(prev => ([...prev, addClick, escDown]));
}
const startDraw = () => {
if(drawType === 'LINE') {
createPolyline();
} else if(drawType === 'CIRCLE') {
createCircle();
}
}
const createPolyline = () => {
if(linePath.length >= 2) {
const polyline = new naver.maps.Polyline({
path: linePath,
strokeColor: '#ff0000',
strokeWeight: 2,
strokeOpacity: 0.5,
map: map
});
linePath.shift();
setPolylines(prev => ([...prev, polyline]));
}
}
const createCircle = () => {
const circle = new naver.maps.Circle({
center: circleCenter,
strokeColor: '#ff0000',
strokeWeight: 2,
strokeOpacity: 1,
fillColor: '#0000ff',
fillOpacity: 0.35,
radius: 1000,
clickable: false,
map: map
});
// circleCenter = '';
setCircleLayers(prev => ([...prev, circle]));
}
const moveCircle = () => {
if(circleLayers.length >= 2) {
circleLayers[0].setMap(null);
setCircleLayers(prev => ([prev[circleLayers.length-1]]));
}
// else {
// console.log(circleLayers);
// }
}
return null;
};

71
src/components/mapDraw/naver/draw/DrawTest0.js

@ -0,0 +1,71 @@
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
export const DrawTest0 = props => {
const {naver} = props;
const {map} = props;
const mapControl = useSelector(state => state.controlMapReducer);
// const [linePositions, setLinePositions] = useState([]);
const positions = ([]);
const [lineZips, setLineZips] = useState([]);
useEffect(() => {
}, [mapControl.drawType]);
if(mapControl.drawType === 'LINE') {
naver.maps.Event.addListener(map, 'click', function(e) {
// const position = e.coord;
positions.push(e.coord);
createPolyline(positions);
})
// naver.maps.Event.addListener(map, 'dbclick', function(e) {
// console.log("dbclick")
// })
naver.maps.Event.addListener(map, 'keydown', function(e) {
const keyboardEvent = e.keyboardEvent,
keyCode = keyboardEvent.keyCode || keyboardEvent.which;
const ESC = 27;
if(keyCode === ESC) {
keyboardEvent.preventDefault();
// for(var i=0, ii=lineZips.length; i<ii; i++) {
// lineZips[i].setMap(null);
// // console.log(lineZips[i]);
// }
lineZips.forEach(line => line.setMap(null));
setLineZips([]);
console.log(lineZips);
}
})
}
const createPolyline = (positions) => {
if(positions.length >= 2) {
const polyline = new naver.maps.Polyline({
path: [positions[(positions.length)-1], positions[(positions.length)-2]],
strokeWeight: 2,
strokeOpacity: 1,
strokeColor: '#ff0000',
map: map
})
// polyline.setMap(map);
setLineZips([...lineZips, positions]);
}
}
const removeLine = () => {
}
return null;
}

157
src/components/mapDraw/naver/draw/DrawTest1.js

@ -0,0 +1,157 @@
import { useEffect, useState } from "react";
import { BiCaretLeftCircle } from "react-icons/bi";
import { useSelector } from "react-redux";
export const DrawTest1 = props => {
const {naver} = props;
const {map} = props;
const {drawType} = useSelector(state => state.controlMapReducer);
let linePath = ([]);
let circleCenter = '';
// let positions = ([]);
// let po = '';
const r = 1000;
// const [polylines, setPolylines] = useState([]);
// const [circleLayers, setCircleLayers] = useState();
let polylines = ([]);
// let circleLayers = ('');
let circleLayers = ([]);
useEffect(() => {
init();
}, []);
useEffect(() => {
remove();
console.log(drawType)
// init();
}, [drawType]);
const event = () => {
let addClick = naver.maps.Event.addListener(map, 'click', function(e) {
if(drawType) {
linePath.push(e.coord);
circleCenter = e.coord
clickDraw();
} else {
}
})
let escDown = naver.maps.Event.addListener(map, 'keydown', function(e) {
const keyboardEvent = e.keyboardEvent,
keyCode = keyboardEvent.keyCode || keyboardEvent.which;
const ESC = 27;
if(keyCode === ESC) {
keyboardEvent.preventDefault();
remove();
}
})
}
const init = () => {
remove();
event();
}
const clickDraw = () => {
// if(!drawType) {
// alert("path option을 선택해주세요.")
// } else {
// if(drawType === 'LINE') {
// console.log("LINE")
// createPolyline();
// } else if(drawType === 'CIRCLE') {
// console.log("CIRCLE")
// createCircle();
// }
// }
if(drawType === 'LINE') {
console.log('1')
createPolyline();
} else if(drawType === 'CIRCLE') {
createCircle();
}
}
const createPolyline = () => {
if(linePath.length >= 2) {
const polyline = new naver.maps.Polyline({
// path: [positions[positions.length-1], po],
path: linePath,
strokeColor: '#ff0000',
strokeWeight: 2,
strokeOpacity: 0.5,
map: map
});
linePath.shift();
// setPolylines(prev => ([...prev, polyline]));
polylines.push(polyline);
}
}
// const createCircle = (positions) => {
const createCircle = () => {
if(circleLayers) remove();
// const circleCenter = positions[0];
// console.log(circleCenter)
// console.log(po)
// const te = positions[0];
const circle = new naver.maps.Circle({
center: circleCenter,
// center: positions[0],
strokeColor: '#ff0000',
strokeWeight: 2,
strokeOpacity: 1,
fillColor: '#0000ff',
fillOpacity: 0.35,
radius: r,
clickable: false,
map: map
})
// circleCenter.shift();
// setCircleLayers(circle);
// circleLayers = circle;
circleLayers.push(circle);
}
// const reCircle = () => {
// // circle.setMap(null);
// // positions = ([]);
// // circleLayers.forEach(cir => cir.setMap(null));
// circleLayers.setMap(null);
// // setCircleLayers();
// circleLayers = '';
// }
const remove = () => {
// debugger;
if(polylines) {
polylines.forEach(poly => poly.setMap(null));
polylines = ([]);
// console.log("poly remove")
}
if(circleLayers) {
circleLayers.forEach(cir => cir.setMap(null));
circleLayers = ([]);
// console.log("circle remove")
}
// circleLayers.forEach(cir => cir.setMap(null));
// circleLayers = ([]);
circleCenter = '';
linePath = ([]);
// console.log("remove!!")
// setClickable(0);
}
return null;
};

180
src/components/mapDraw/naver/draw/DrawTest2.js

@ -0,0 +1,180 @@
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
export const DrawTest2 = props => {
const {naver} = props;
const {map} = props;
let draw = '';
const {drawType} = useSelector(state => state.controlMapReducer);
const r = 1000;
let positions = ([]);
const [polyGroup, setPolyGroup] = useState([]);
const [eventGroup, setEventGrouop] = useState([]);
const [circleGroup, setCircleGroup] = useState([]);
useEffect(() => {
remove2();
clickEvent();
}, [drawType]);
useEffect(() => {
remove();
}, [polyGroup, eventGroup]);
useEffect(() => {
// moveCircle();
remove();
}, [circleGroup]);
const moveCircle = () => {
if(circleGroup) {
circleGroup.forEach(prev => prev.setMap(null));
}
};
const movePoly = () => {
if(polyGroup) {
polyGroup.forEach(prev => prev.setMap(null));
}
}
const clickEvent = () => {
console.log("d")
// remove2();
// drawType =
if(drawType === 'CIRCLE') {
console.log("circle")
} else if(drawType === 'LINE') {
console.log("LINE")
}else if(drawType === 'POLYGON') {
console.log("POLYGON")
}
addPositions();
}
const remove2 = () => {
polyGroup.forEach(poly => poly.setMap(null));
setPolyGroup([]);
circleGroup.forEach(cir => cir.setMap(null));
setCircleGroup([]);
eventGroup.forEach(eve => naver.maps.Event.removeListener(eve));
setEventGrouop([]);
positions = [];
}
const addPositions = () => {
if(event) naver.maps.Event.removeListener(event);
var event = naver.maps.Event.addListener(map, 'click', function(e) {
debugger;
if(drawType === 'LINE') {
positions.push(e.coord);
createPolyline(positions);
} else if(drawType === 'CIRCLE') {
positions = e.coord;
createCircle(positions);
}
})
// setEventGrouop(prev => ([...prev, event]));
}
const createCircle = (positions) => {
moveCircle();
const circle = new naver.maps.Circle({
center: positions,
strokeColor: '#ff0000',
strokeWeight: 2,
strokeOpacity: 1,
fillColor: '#0000ff',
fillOpacity: 0.35,
radius: r,
clickable: false,
map: map
})
draw = drawType;
setCircleGroup(prev => ([...prev, circle]));
}
const createPolyline = (positions) => {
if(positions.length >= 2) {
movePoly();
const polyline = new naver.maps.Polyline({
// path: [positions[(positions.length)-1], positions[(positions.length)-2]],
path: positions,
strokeColor: '#ff0000',
strokeWeight: 2,
strokeOpacity: 1,
map: map
})
positions.shift();
console.log(positions)
draw = drawType;
setPolyGroup(prev => ([...prev, polyline]));
}
}
const remove = () => {
if(drawType!=draw) {
naver.maps.Event.addListener(map, 'keydown', function(e) {
const keyboardEvent = e.keyboardEvent,
keyCode = keyboardEvent.keyCode || keyboardEvent.which;
const ESC = 27;
if(keyCode === ESC) {
keyboardEvent.preventDefault();
polyGroup.forEach(poly => poly.setMap(null));
setPolyGroup([]);
circleGroup.forEach(cir => cir.setMap(null));
setCircleGroup([]);
// eventGroup.forEach(eve => naver.maps.Event.removeListener(eve));
// setEventGrouop([]);
positions = [];
// debugger;
}
})
}
}
// const drawTypeChange = () => {
// remove();
// draw = drawType;
// }
// const init = () => {
// // draw = drawType;
// if(draw) {
// var event = naver.maps.Event.addListener(map, 'click', function(e) {
// draw = drawType;
// console.log(drawType, "drawType")
// // remove(draw, event);
// drawTypeChange();
// // naver.maps.Event.removeListener(event);
// })
// }
// // remove(event);
// }
// const remove = (draw, event) => {
// if(draw == drawType) {
// console.log("안지워")
// } else {
// console.log("지워")
// naver.maps.Event.removeListener(event);
// }
// if(positions) naver.maps.Event.removeListener(map, 'click', function(e) {
// console.log(e);
// });
// naver.maps.removeListener(event);
// }
return null;
}

63
src/components/mapDraw/naver/dron/DronHistory.js

@ -0,0 +1,63 @@
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { controlGpHisAction } from '../../../../modules/control/gp';
export const DronHistory = props => {
const { controlGpHistory } = useSelector(state => state.controlGpHisState);
const { objectId, isClickObject } = useSelector(
state => state.controlMapReducer
);
let naver = props.naver;
let polyline;
let polylinePath = [];
const dispatch = useDispatch();
useEffect(() => {
// console.log('>>>', controlGpHistory);
polylineRemove();
polylineInit();
}, [controlGpHistory]);
useEffect(() => {
if (isClickObject) {
dispatch(controlGpHisAction.request({ id: objectId }));
} else {
polylineRemove();
}
}, [objectId, isClickObject]);
const polylineRemove = () => {
if (props.arrPolyline) {
props.arrPolyline.map(item => {
item.setMap(null);
});
}
};
const polylineInit = () => {
if (controlGpHistory) {
polyline = new naver.maps.Polyline({
clickable: false,
strokeColor: '#ff4961',
strokeStyle: 'solid',
strokeOpacity: 5,
strokeWeight: 1.5
});
controlGpHistory.map(item => {
if (item.lat > 0 && item.lng > 0) {
const position = new naver.maps.LatLng(item.lat, item.lng);
polylinePath.push(position);
}
// console.log('>>>>>>>>>>>', item);
});
polyline.setPath(polylinePath);
polyline.setMap(props.map);
props.arrPolyline.push(polyline);
}
};
return null;
};

158
src/components/mapDraw/naver/dron/DronMarker.js

@ -0,0 +1,158 @@
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import '../../../../assets/css/custom.css';
import DronIconPulple from '../../../../assets/images/drone-marker-icon-pulple.png';
import DronIcon from '../../../../assets/images/drone-marker-icon.png';
import { controlGpDtlAction } from '../../../../modules/control/gp';
import { objectClickAction } from '../../../../modules/control/map/actions/controlMapActions';
export const DronMarker = props => {
const { controlGpList } = useSelector(state => state.controlGpState);
const { objectId, isClickObject } = useSelector(
state => state.controlMapReducer
);
const dispatch = useDispatch();
let naver = props.naver;
var contentString = ['<div class="iw_inner"> dddd', '</div>'].join('');
var infowindow = new naver.maps.InfoWindow({
content: contentString
});
useEffect(() => {
markerInit();
}, [controlGpList]);
useEffect(() => {
console.log('>>>>>>>>>>>>>>>>', objectId, isClickObject);
props.arrMarkers.map(clickMarker => {
if (objectId === clickMarker.id && isClickObject) {
clickMarker.setIcon(DronIconPulple);
} else {
clickMarker.setIcon(DronIcon);
}
});
// }else{
// }
}, [objectId, isClickObject]);
useEffect(() => {
props.arrMarkers.map(clickMarker => {
if (objectId === clickMarker.id) {
console.log(clickMarker);
props.map.setCenter(clickMarker.getPosition());
// $('#btn_modal').click();
props.map.setZoom(13, true);
}
});
}, [objectId]);
//마커를 그린다.
const addMarkers = (position, id, controlId) => {
var marker = new naver.maps.Marker({
position: position,
title: id,
id: id,
controlId: controlId,
icon: {
// content: [
// '<div>dddd</div>',
// ].join(''),
url: DronIcon,
// scaledSize: new naver.maps.scaledSize(50, 50)
// size: new naver.maps.Size(1000, 1000),
// origin: new naver.maps.Point(0, 0)
// anchor: new naver.maps.Point(25, 25)
}
});
marker.setMap(props.map);
naver.maps.Event.addListener(marker, 'click', function (e) {
handlerDronClick(marker);
});
props.arrMarkers.push(marker);
};
const handlerDronClick = marker => {
if (marker.getAnimation() != null) {
// marker.setAnimation(null);
// infowindow.close();
// dispatch(Actions.controlGpHisAction.request(controlGpList));
} else {
// infowindow.open(props.map, marker);
// marker.setAnimation(naver.maps.Animation.BOUNCE);
}
// marker.setIcon(DronIconPulple);
// console.log(marker.id);
const markerId = marker.id;
const contorlId = marker.controlId;
console.log('contorlId ::::::::::< ', marker.controlId);
//히스토리 불러오기
dispatch(objectClickAction(markerId));
dispatch(controlGpDtlAction.request(contorlId));
};
//마커를 삭제 한다.
const removeMarkers = marker => {
marker.setMap(null);
};
//마커에 위치를 이동한다.
const moveMarkers = (marker, position) => {
// console.log(marker);
marker.setPosition(position);
};
//데이터가 없는 마커를 모두 삭제 한다.
const allRemoveMarkers = () => {
if (props.arrMarkers && controlGpList) {
props.arrMarkers.map(marker => {
const isExists = controlGpList.find(
item => item.objectId === marker.id
);
if (!isExists) {
removeMarkers(marker);
const arrData = props.arrMarkers.filter(
item => item.objectId != marker.id
);
props.removeArrMarkers(arrData);
}
});
}
// }
};
//마커를 셋팅 한다.
const markerInit = () => {
if (controlGpList) {
allRemoveMarkers();
controlGpList.map(item => {
const position = new naver.maps.LatLng(item.lat, item.lng);
if (props.arrMarkers) {
const isExists = props.arrMarkers.find(
ele => ele.id === item.objectId
);
if (isExists) {
moveMarkers(isExists, position);
} else {
// console.log(' ADD >>>', props.arrMarkers);
addMarkers(position, item.objectId, item.controlId);
}
} else {
addMarkers(position, item.objectId, item.controlId);
}
});
}
};
return null;
};

150
src/components/mapDraw/naver/feature/FeatureAirZone.js

@ -0,0 +1,150 @@
import { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import '../../../../assets/css/custom.css';
export const FeatureAirZone = props => {
const mapControl = useSelector(state => state.controlMapReducer);
let infoWindow;
useEffect(() => {
// console.log('>>>>>', mapControl);
featureAirZoneInit();
featureAirEvent();
}, [mapControl]);
useEffect(() => {
// console.log(">>>>>>>>" , props.features)
}, []);
const infowindowOpen = data => {
const content =
'<div class="tooltip-box">' +
'<div class="tooltip-ti">' +
'<span>' +
data.title +
'</span>' +
'</div>' +
'<div class="tooltip-txt">' +
'<div class="tooltip-txt-list">' +
// '<span class="ti">설명</span>' +
'<span>' +
data.description +
'</span>' +
'</div>' +
// '<div class="tooltip-txt-list">' +
// '<span class="ti">좌표정보</span>' +
// '<span>'+data.coord+'</span>' +
// '</div>' +
'</div>' +
// '<span class="arrow"></span>' +
'</div>';
infoWindow = new props.naver.maps.InfoWindow({
class: 'tooltip-test',
content: content,
maxWidth: 200,
backgroundColor: '#283046', //박스안쪽영역 컬러
// borderColor: '#333', //테두리컬러
// borderWidth: 3, //테두리 굵기
anchorSize: new props.naver.maps.Size(30, -10),
anchorSkew: false,
anchorColor: '#283046',
pixelOffset: new props.naver.maps.Point(20, -20)
});
infoWindow.open(props.map, data.coord);
};
const featureAirZoneInit = () => {
let arrGeoJson = [];
// props.map.data.removeGeoJson(props.geoJson);
// let geoJson = originGeoJson;
let useGeoJson = { type: 'FeatureCollection' };
useGeoJson.features = props.features;
props.map.data.removeGeoJson(useGeoJson);
props.features.map(item => {
if (item.properties.type === '0001' && mapControl.area0001) {
arrGeoJson.push(item);
} else if (item.properties.type === '0002' && mapControl.area0002) {
arrGeoJson.push(item);
} else if (item.properties.type === '0003' && mapControl.area0003) {
arrGeoJson.push(item);
} else if (item.properties.type === '0004' && mapControl.area0004) {
arrGeoJson.push(item);
} else if (item.properties.type === '0005' && mapControl.area0005) {
arrGeoJson.push(item);
} else if (item.properties.type === '0006' && mapControl.area0006) {
arrGeoJson.push(item);
}
});
useGeoJson.features = arrGeoJson;
props.map.data.addGeoJson(useGeoJson);
props.map.data.setStyle(feature => {
var color;
//0001 비행금지구역 #FF3648
//0002 비행제한구역 #FFA1AA
//0003 관제권(공항) #FFA800
//0004 비행장(군사) #A16B00
//0005 이착륙장(RC비행장) #AB40FF
//0006 초경량비행장치 #009cad
// 공역 색상 변경
const type = feature.getProperty('type');
if (type === '0001') {
color = '#FF3648';
} else if (type === '0002') {
color = '#FFA1AA';
} else if (type === '0003') {
color = '#FFA800';
} else if (type === '0004') {
color = '#A16B00';
} else if (type === '0005') {
color = '#AB40FF';
} else if (type === '0006') {
color = '#009cad';
}
return {
fillColor: color,
strokeColor: color,
strokeWeight: 0.7,
icon: null
};
});
};
const featureAirEvent = () => {
props.map.data.addListener('click', function (e) {
// e.feature.setProperty('isColorful', true);
console.log(e.feature.property_name);
});
props.map.data.addListener('mouseover', function (e) {
const data = {};
data.coord = e.coord;
data.title = e.feature.property_name;
data.description = e.feature.property_description;
props.map.data.overrideStyle(e.feature, {
strokeWeight: 3
// icon: HOME_PATH +'/img/example/pin_spot.png'
});
infowindowOpen(data);
});
props.map.data.addListener('mouseout', function (e) {
props.map.data.revertStyle();
if (infoWindow) {
infoWindow.close();
}
});
};
return null;
};

25
src/components/mapDraw/naver/search/NaverMapSearch.js

@ -0,0 +1,25 @@
import { useEffect } from 'react';
export const NaverMapSearch = props => {
useEffect(() => {
console.log('>>>>', props.naver.maps.Service);
props.naver.maps.Service.geocode(
{
address: '산곡동'
},
function (status, response) {
if (status !== naver.maps.Service.Status.OK) {
return alert('Something wrong!');
}
var result = response.result, // 검색 결과의 컨테이너
items = result.items; // 검색 결과의 배열
console.log(result);
// do Something
}
);
});
return null;
};

488
src/components/mapDraw/naver/sensor/SensorZone.js

@ -0,0 +1,488 @@
import React, {useEffect, useState} from 'react';
import {useSelector} from "react-redux";
const SENSOR_RADIUS = '100';
const SENSOR_RADIUS_DIVISION = '3';
let lenderCnt = 0;
const SensorZone = (props) => {
const {naver} = props;
// 드론 실시간 정보
const {controlGpList} = useSelector(state => state.controlGpState);
// 환경지표 타입(dust, co, o3, no2, so2)
const {sensor} = useSelector(state => state.controlMapReducer);
// 센서레이어(환경지표) 관리
const [circleLayers, setCircleLayers] = useState([]);
const [polilineGroupLayers, setPolilineGroupLayers] = useState({});
// console.log('########## SensorZone ###########', lenderCnt, {controlGpList, circleLayer: circleLayers, polilineLayer: polilineGroupLayers});
useEffect(() => {
lenderCnt++
if (!sensor) {
removeSensorLayers();
} else {
initSensorLayer();
}
}, [controlGpList, sensor]);
let infoWindow;
// 센서 레이어 Info
const infowindowOpen = data => {
// console.log('data', data)
const content = `
<div class="tooltip-box" style="max-width: 300px;">
<div class="tooltip-ti">
<span>${data.title}</span>
</div>
<div class="tooltip-txt">
<div class="tooltip-txt-list">
<div style="color: ${data.sensor.sensorDust.color};">
<span style="width: 120px; display: inline-block;">${data.sensor.sensorDust.title}(${data.sensor.sensorDust.text})</span>
<span>${data.sensor.sensorDust.value}</span>
</div>
<div style="color: ${data.sensor.sensorO3.color};">
<span style="width: 120px; display: inline-block;">${data.sensor.sensorO3.title}(${data.sensor.sensorO3.text})</span>
<span>${data.sensor.sensorO3.value}</span>
</div>
<div style="color: ${data.sensor.sensorNo2.color};">
<span style="width: 120px; display: inline-block;">${data.sensor.sensorNo2.title}(${data.sensor.sensorNo2.text})</span>
<span>${data.sensor.sensorNo2.value}</span>
</div>
<div style="color: ${data.sensor.sensorCo.color};">
<span style="width: 120px; display: inline-block;">${data.sensor.sensorCo.title}(${data.sensor.sensorCo.text})</span>
<span>${data.sensor.sensorCo.value}</span>
</div>
<div style="color: ${data.sensor.sensorSo2.color};">
<span style="width: 120px; display: inline-block;">${data.sensor.sensorSo2.title}(${data.sensor.sensorSo2.text})</span>
<span>${data.sensor.sensorSo2.value}</span>
</div>
</div>
</div>
</div>
`;
infoWindow = new naver.maps.InfoWindow({
class: 'tooltip-sensor',
content: content,
maxWidth: 300,
backgroundColor: '#283046', //박스안쪽영역 컬러
// borderColor: '#333', //테두리컬러
// borderWidth: 3, //테두리 굵기
anchorSize: new naver.maps.Size(30, -10),
anchorSkew: false,
anchorColor: '#283046',
pixelOffset: new naver.maps.Point(20, -20)
});
infoWindow.open(props.map, data.coord);
};
// 센서레이어 초기화
const initSensorLayer = () => {
emtpyLayerRemove();
if (controlGpList) {
controlGpList.forEach(controlGp => {
const {controlId, lat, lng, objectId} = controlGp;
let color = undefined;
const sensorData = convtSensorData(controlGp);
if (sensorData) {
if (sensor === 'dust') color = sensorData.sensorDust.color;
else if (sensor === 'co') color = sensorData.sensorCo.color;
else if (sensor === 'so2') color = sensorData.sensorSo2.color;
else if (sensor === 'no2') color = sensorData.sensorNo2.color;
else if (sensor === 'o3') color = sensorData.sensorO3.color;
}
const position = new naver.maps.LatLng(controlGp.lat, controlGp.lng);
const polilineLayers = polilineGroupLayers[controlId];
if (polilineLayers) {
// const prevPosition = polilineLayers[0].position;
// if(!prevPosition.equals(position)){
movePolilineLayers(polilineLayers, position, color);
// }
} else {
addPolilineLayers(controlId, objectId, position, color);
}
const circleLayer = circleLayers.find(layer => layer.controlId === controlId);
if (circleLayer) moveCircleLayer(circleLayer, position, color, sensorData);
else addCircleLayer(controlId, objectId, position, color, sensorData);
});
}
}
// 센서레이어 생성
const addSensorLayer = (position, id, controlId, color, sensorData) => {
addPolilineLayers(controlId, id, position, color);
addCircleLayer(controlId, id, position, color, sensorData);
}
// Circle 레이어 생성
const addCircleLayer = (controlId, id, position, color, sensorData) => {
// console.log({controlId, id, position, color, sensorData})
const circleLayer = new naver.maps.Circle({
title: id,
id: id,
controlId: controlId,
clickable: true,
center: position,
radius: SENSOR_RADIUS,
// map: props.map,
strokeColor: color,
strokeOpacity: 1,
strokeWeight: 2,
fillColor: color,
fillOpacity: 0.2,
sensorData: sensorData
})
// Circle 이벤트 주입
naver.maps.Event.addListener(circleLayer, 'mouseover', function (e) {
const data = {};
data.coord = e.coord;
data.title = '환경지표';
data.controlId = e.overlay.controlId;
data.sensor = e.overlay.sensorData;
e.overlay.setOptions({
strokeWeight: 5,
fillOpacity: 0.5
})
infowindowOpen(data);
});
naver.maps.Event.addListener(circleLayer, 'mouseout', function (e) {
e.overlay.setOptions({
strokeWeight: 2,
fillOpacity: 0.2
})
// props.map.Event.revertStyle();
if (infoWindow) {
infoWindow.close();
}
});
circleLayer.setMap(props.map)
setCircleLayers(prev => ([...prev, circleLayer]));
}
const addPolilineLayers = (controlId, id, position, color) => {
// 지도에 적용 및 레이어 관리 추가
// console.log('addPolilineLayers', controlId)
const polilineLayers = createCircleInGrid(position, id, controlId, color);
polilineLayers.forEach(layer => layer.setMap(props.map));
setPolilineGroupLayers(prev => ({
...prev,
[controlId]: polilineLayers
}));
}
// 센서레이어 이동
const moveSensorLayer = (controlId, position, color) => {
const circleLayer = circleLayers.find(layer => layer.controlId === controlId);
moveCircleLayer(circleLayer, position, color);
const polilineLayers = polilineGroupLayers[controlId];
movePolilineLayers(polilineLayers, position, color);
}
const moveCircleLayer = (circleLayer, position, color, sensorData) => {
// const circleLayer = circleLayers.find(layer => layer.controlId === controlId);
if (circleLayer) {
circleLayer.sensorData = sensorData;
circleLayer.setOptions({center: position, strokeColor: color, fillColor: color})
}
}
const movePolilineLayers = (polilineLayers, position, color) => {
const {controlId, id, position: prevPosition} = polilineLayers[0];
if (prevPosition.equals(position)) {
if (polilineLayers) {
polilineLayers.forEach(layer => layer.setOptions({strokeColor: color}));
}
} else {
if (polilineLayers) {
polilineLayers.forEach(layer => layer.setMap(null));
}
const newPolilineLayers = createCircleInGrid(position, id, controlId, color);
newPolilineLayers.forEach(layer => layer.setMap(props.map));
setPolilineGroupLayers(prev => ({
...prev,
[controlId]: newPolilineLayers
}));
}
}
// 센서레이어 제거
const removeSensorLayer = (controlId) => {
removeCircleLayer(controlId);
removePolilineLayer(controlId);
}
const removeCircleLayer = (controlId) => {
const idx = circleLayers.findIndex(layer => layer.controlId === controlId);
circleLayers[idx].setMap(null);
setCircleLayers(prev => {
prev.splice(idx, 1);
return prev;
})
}
const removePolilineLayer = (controlId) => {
const polilineLayers = polilineGroupLayers[controlId];
if (polilineLayers) polilineLayers.forEach(layer => layer.setMap(null));
setPolilineGroupLayers(prev => {
delete prev[controlId];
return prev;
})
}
// 센서레이어 모두 제거
const removeSensorLayers = () => {
circleLayers.forEach(layer => layer.setMap(null));
setCircleLayers([]);
const keys = Object.keys(polilineGroupLayers);
keys.forEach((key) => {
polilineGroupLayers[key].forEach(layer => layer.setMap(null));
})
setPolilineGroupLayers({});
}
// 레이어관리시 새로운 데이터에 없는 좌표 제거
const emtpyLayerRemove = () => {
setCircleLayers(prev => {
const remainCircleLayers = prev.filter((circleLayer, i) => {
const controlId = circleLayer.controlId;
const findObj = controlGpList.find(controlGp => controlGp.controlId === controlId);
if (findObj) {
return circleLayer;
} else {
circleLayer.setMap(null);
}
})
return remainCircleLayers;
})
setPolilineGroupLayers(prev => {
const keys = Object.keys(prev);
const remainPolilineGroupLayer = {};
keys.forEach((controlId, i) => {
const findObj = controlGpList.find(controlGp => controlGp.controlId === controlId);
if (findObj) {
remainPolilineGroupLayer[controlId] = prev[controlId];
} else {
const polilineLayers = prev[controlId];
polilineLayers.forEach(layer => {
layer.setMap(null);
})
}
})
return remainPolilineGroupLayer;
})
}
// Circle안에 격자 무늬 생성
const createCircleInGrid = (position, id, controlId, color) => {
// Circle 레이어 안의 격자무늬
const polilineLayers = [];
for (let i = 0; i <= SENSOR_RADIUS_DIVISION; i++) {
// 각 사분면 각도
const diff = 90 / SENSOR_RADIUS_DIVISION;
const angleQuadrant1 = diff * i;
const angleQuadrant2 = 180 - (diff * i);
const angleQuadrant3 = 180 + (diff * i);
const angleQuadrant4 = diff * -i;
// 각 사분면 좌표
const coord1 = new naver.maps.EPSG3857.getDestinationCoord(position, angleQuadrant1, SENSOR_RADIUS);
const coord2 = new naver.maps.EPSG3857.getDestinationCoord(position, angleQuadrant2, SENSOR_RADIUS);
const coord3 = new naver.maps.EPSG3857.getDestinationCoord(position, angleQuadrant3, SENSOR_RADIUS);
const coord4 = new naver.maps.EPSG3857.getDestinationCoord(position, angleQuadrant4, SENSOR_RADIUS);
const polyline12 = new naver.maps.Polyline({
id,
position,
controlId,
path: [coord1, coord2],
strokeWeight: 0.8,
// strokeWeight: 2,
strokeOpacity: 1,
strokeColor: color,
strokeStyle: 'shortdash'
})
polilineLayers.push(polyline12);
const polyline23 = new naver.maps.Polyline({
id,
position,
controlId,
path: [coord2, coord3],
strokeWeight: 0.8,
// strokeWeight: 2,
strokeOpacity: 1,
strokeColor: color,
strokeStyle: 'shortdash'
})
polilineLayers.push(polyline23);
const polyline34 = new naver.maps.Polyline({
id,
position,
controlId,
path: [coord3, coord4],
strokeWeight: 0.8,
// strokeWeight: 2,
strokeOpacity: 1,
strokeColor: color,
strokeStyle: 'shortdash'
})
polilineLayers.push(polyline34);
const polyline41 = new naver.maps.Polyline({
id,
position,
controlId,
path: [coord4, coord1],
strokeWeight: 0.8,
// strokeWeight: 2,
strokeOpacity: 1,
strokeColor: color,
strokeStyle: 'shortdash'
})
polilineLayers.push(polyline41);
}
return polilineLayers;
}
// 환경지표 필요한 데이터로 변환
const convtSensorData = (sensorData) => {
const r = {
sensorDust: {
title: '미세먼지',
value: '-',
text: '-',
color: undefined
},
sensorCo: {
title: '일산화탄소',
value: '-',
text: '-',
color: undefined
},
sensorSo2: {
title: '아황산가스',
value: '-',
text: '-',
color: undefined
},
sensorNo2: {
title: '이산화질소',
value: '-',
text: '-',
color: undefined
},
sensorO3: {
title: '오존',
value: '-',
text: '-',
color: undefined
}
}
// 정수: 미세먼지 || 소수점 1자리 : 일산화탄소 || 소수점 3자리 : 오존, 이산화질소, 아황산가스
// 좋음 : 파랑, 보통 : 노랑, 나쁨 : 주황, 매우나쁨 : 빨강
// 미세먼지 : 좋음(0~30) 보통(31~80) 나쁨(81~150) 매우나쁨(151~)
if (sensorData.sensorDust != undefined && sensorData.sensorDust != null) {
const val = r.sensorDust.value = Math.round(sensorData.sensorDust);
if (val <= 30) {
r.sensorDust.text = '좋음';
r.sensorDust.color = '#37c9ff';
} else if (val <= 80) {
r.sensorDust.text = '보통';
r.sensorDust.color = '#ffff44';
} else if (val <= 150) {
r.sensorDust.text = '나쁨';
r.sensorDust.color = '#ffa044';
} else if (val > 150) {
r.sensorDust.text = '매우나쁨';
r.sensorDust.color = '#ff5959';
} else {
r.sensorDust.text = '-';
r.sensorDust.color = '#a1a1a1';
}
}
// 일산화탄소 : 좋음(0~2) 보통(2.1~9) 나쁨(9.1~15) 매우나쁨(15.1~)
if (sensorData.sensorCo != undefined && sensorData.sensorCo != null) {
const val = r.sensorCo.value = Math.round(sensorData.sensorCo * 10) / 10;
if (val <= 0.2) {
r.sensorCo.text = '좋음';
r.sensorCo.color = '#37c9ff';
} else if (val <= 9) {
r.sensorCo.text = '보통';
r.sensorCo.color = '#ffff44';
} else if (val <= 15) {
r.sensorCo.text = '나쁨';
r.sensorCo.color = '#ffa044';
} else if (val > 15) {
r.sensorCo.text = '매우나쁨';
r.sensorCo.color = '#ff5959';
} else {
r.sensorCo.text = '-';
r.sensorCo.color = '#a1a1a1';
}
}
// 아황산가스 : 좋음(0~0.02) 보통(0.021~0.05) 나쁨(0.051~0.15) 매우나쁨 (0.151 ~)
if (sensorData.sensorSo2 != undefined && sensorData.sensorSo2 != null) {
const val = r.sensorSo2.value = Math.round(sensorData.sensorSo2 * 1000) / 1000;
if (val <= 0.02) {
r.sensorSo2.text = '좋음';
r.sensorSo2.color = '#37c9ff';
} else if (val <= 0.05) {
r.sensorSo2.text = '보통';
r.sensorSo2.color = '#ffff44';
} else if (val <= 0.15) {
r.sensorSo2.text = '나쁨';
r.sensorSo2.color = '#ffa044';
} else if (val > 0.15) {
r.sensorSo2.text = '매우나쁨';
r.sensorSo2.color = '#ff5959';
} else {
r.sensorSo2.text = '-';
r.sensorSo2.color = '#a1a1a1';
}
}
// 이산화질소 : 좋음(0~0.03) 보통(0.031~0.06) 나쁨(0.061~0.2) 매우나쁨(0.201~)
if (sensorData.sensorNo2 != undefined && sensorData.sensorNo2 != null) {
const val = r.sensorNo2.value = Math.round(sensorData.sensorNo2 * 1000) / 1000;
if (val <= 0.03) {
r.sensorNo2.text = '좋음';
r.sensorNo2.color = '#37c9ff';
} else if (val <= 0.06) {
r.sensorNo2.text = '보통';
r.sensorNo2.color = '#ffff44';
} else if (val <= 0.2) {
r.sensorNo2.text = '나쁨';
r.sensorNo2.color = '#ffa044';
} else if (val > 0.2) {
r.sensorNo2.text = '매우나쁨';
r.sensorNo2.color = '#ff5959';
} else {
r.sensorNo2.text = '-';
r.sensorNo2.color = '#a1a1a1';
}
}
// 오존 : 좋음(0~0.03) 보통(0.031~0.09) 나쁨(0.091~0.15) 매우나쁨(0.151~)
if (sensorData.sensorO3 != undefined && sensorData.sensorO3 != null) {
const val = r.sensorO3.value = Math.round(sensorData.sensorO3 * 1000) / 1000;
if (val <= 0.03) {
r.sensorO3.text = '좋음';
r.sensorO3.color = '#37c9ff';
} else if (val <= 0.09) {
r.sensorO3.text = '보통';
r.sensorO3.color = '#ffff44';
} else if (val <= 0.15) {
r.sensorO3.text = '나쁨';
r.sensorO3.color = '#ffa044';
} else if (val > 0.15) {
r.sensorO3.text = '매우나쁨';
r.sensorO3.color = '#ff5959';
} else {
r.sensorO3.text = '-';
r.sensorO3.color = '#a1a1a1';
}
}
return r;
}
return null;
};
export default SensorZone;

42
src/components/mapDraw/nhn/NMap.js

@ -0,0 +1,42 @@
import { useEffect, useState } from 'react';
export const NMap = props => {
const naver = window.naver;
const [mapObject, setMapObject] = useState(null);
useEffect(() => {
mapInit();
// console.log(map);
// console.log(features);
// setIsMapLoad(true);
}, []);
const mapInit = () => {
// const mapOptions = {
// center: new naver.maps.LatLng(36.56793936069445, 127.85101412107547),
// // ceneter: new naver.maps.LatLng(37.445949, 126.673868),
// zoom: 15,
// zoomControl: true,
// mapTypeId: naver.maps.MapTypeId.HYBRID,
// zoomControlOptions: {
// position: naver.maps.Position.TOP_LEFT,
// style: naver.maps.ZoomControlStyle.SMALL
// }
// };
// map = ;
props.setMapObject(new naver.maps.Map('map', mapOptions));
// naver.maps.Event.addListener(map, 'click', function (e) {
// console.log(e);
// });
// naver.maps.Event.addListener(map, 'idle', function (e) {
// console.log(e);
// });
};
return <div id='map' style={{ width: '100%', height: '100vh' }}></div>;
};

62
src/components/mapDraw/nhn/NMapMarker.js

@ -0,0 +1,62 @@
import { useEffect } from 'react';
import DronIcon from '../../../assets/images//drone-marker-icon.png';
export const NMapMarker = props => {
const naver = window.naver;
useEffect(() => {
if (props.selMarker && props.selMarker.setMap) {
props.selMarker.setMap(null);
}
if (props.data) {
for (let i = 0; i < props.data?.length; i++) {
if (props.data[i].lat > 0 && props.data[i].lon > 0) {
const position = new naver.maps.LatLng(
props.data[i]?.lat,
props.data[i]?.lon
);
addMarkers(position, props.data[i]?.cntrlId);
return;
}
}
props.data?.map((item, index) => {});
}
}, [props.data]);
useEffect(() => {
// console.log('info>>>:' + props.info.lat);
// console.log(props.selMarker);
if (props.selMarker && props.selMarker) {
const position = new naver.maps.LatLng(props.info?.lat, props.info?.lon);
props.selMarker?.setPosition(position);
// moveMarkers(props.selMarker, position);
}
}, [props.info]);
const addMarkers = (position, id) => {
//이미 지정된 마커 제거
var marker = new naver.maps.Marker({
position: position,
title: id,
id: id,
icon: {
url: DronIcon
}
});
props.map.setCenter(position);
props.map.setZoom(14);
marker.setMap(props.map);
props.setSelMarker(marker);
};
const moveMarkers = (marker, position) => {
// console.log('dddddddddddddddddddd', marker, position);
// marker.setPositon(position);
};
return null;
};

47
src/components/mapDraw/nhn/NMapPolyline.js

@ -0,0 +1,47 @@
import { useEffect } from 'react';
export const NMapPolyline = props => {
const naver = window.naver;
// console.log(props);
let polyline;
let polylinePath = [];
useEffect(() => {
//기존 폴리라인 삭제 처리
if (props.selPolyline && props.selPolyline.setMap) {
props.selPolyline.setMap(null);
}
addPolyline();
}, [props.data]);
const addPolyline = () => {
if (props.data) {
polyline = new naver.maps.Polyline({
clickable: false,
strokeColor: '#ff4961',
strokeStyle: 'solid',
strokeOpacity: 5,
strokeWeight: 1.5
});
props.data.map(item => {
if (item.lat > 0 && item.lon > 0) {
const position = new naver.maps.LatLng(item.lat, item.lon);
polylinePath.push(position);
}
// console.log('>>>>>>>>>>>', item);
});
polyline.setPath(polylinePath);
polyline.setMap(props.map);
props.setSelPolyline(polyline);
// props.arrPolyline.push(polyline);
}
};
return null;
};

4
src/modules/control/map/actions/controlMapActions.ts

@ -2,6 +2,10 @@
export const mapTypeChangeAction = (value: any) => dispatch =>
dispatch({ type: 'MAP_TYPE_CHANGE', value });
// draw 옵션 변경 Action
export const drawTypeChangeAction = (value: any) => dispatch =>
dispatch({type: 'DRAW_TYPE_CHANGE', value})
// 드론체 클릭 시 Action
export const objectClickAction = (value: any) => dispatch =>
dispatch({ type: 'OBJECT_CLICK', value });

10
src/modules/control/map/reducers/controlMapReducer.ts

@ -9,7 +9,9 @@ const initialState = {
area0004: true, // 비행장(군사)
area0005: true, // 이착륙장(RC비행장)
area0006: true, // 초경량비행장치
sensor: 'dust'
sensor: 'dust',
drawType: ''
};
const controlReducerReducer = (state = initialState, action) => {
@ -67,6 +69,12 @@ const controlReducerReducer = (state = initialState, action) => {
break;
default:
return state;
case 'DRAW_TYPE_CHANGE':
return {
...state,
drawType: action.value
};
}
};

7
src/router/routes/index.js

@ -78,6 +78,13 @@ const Routes = [
component: lazy(() => import('../../views/control')),
layout: 'BlankLayout'
},
{
path: '/testDraw',
component: lazy(() => import('../../views/testDraw')),
layout: 'BlankLayout'
},
{
path: '/history/record/sample1',
component: lazy(() =>

66
src/views/testDraw/alarm/ControlAlarmList.js

@ -0,0 +1,66 @@
import { X } from 'react-feather';
const ControlAlarmList = props => {
return (
<div className='left-layer'>
<div className='layer-content'>
<div className='layer-ti'>
<h4>알림 리스트</h4>
<button
className='btn-icon'
outline
color='primary'
onClick={() => props.setOpenAlarmList(false)}
>
<X size={20} />
</button>
</div>
<div className='layer-content-list'>
<dl className='notice-list'>
<dt>
<div className='list-ti'>
<div className='list-left-txt'>전체 2000</div>
<div className='list-right-txt'>오늘 120</div>
</div>
</dt>
</dl>
</div>
</div>
<div className='layer-content'>
<div className='layer-ti'>
<h4>알림 목록</h4>
</div>
<div className='layer-content-list'>
<dl className='notice-list'>
<dt>
<div className='list-ti'>
<div className='list-left-txt'>통신 장애 알림</div>
<div className='list-right-txt'>6 17</div>
</div>
<div className='list-txt'>
통신장애 통신장애 통신장애 통신장애 통신장애 통신장애 통신장애
통신장애 통신장애{' '}
</div>
</dt>
</dl>
</div>
<div className='layer-content-list'>
<dl className='notice-list'>
<dt>
<div className='list-ti'>
<div className='list-left-txt'>비행 경로 이탈</div>
<div className='list-right-txt'>6 17</div>
</div>
<div className='list-txt'>
비행경로이탈 비행경로이탈 비행경로이탈 비행경로이탈 비행경로이탈
비행경로이탈 비행경로이탈 비행경로이탈 비행경로이탈 비행경로이탈
</div>
</dt>
</dl>
</div>
</div>
</div>
);
};
export default ControlAlarmList;

45
src/views/testDraw/alarm/ControlAlarmNotice.js

@ -0,0 +1,45 @@
import { Bell, ChevronDown, ChevronUp } from "react-feather";
import { ReactComponent as DroneMenuIcon } from '../../../assets/images/drone_menu_icon.svg';
const ControlAlarmNotice = () => {
{/* 알림 위아래 롤링은 구현해주셔야되는데 따른 컴포넌트있으면 그거사용해도됩니다...제가 만들어논거는 45px씩 움직여주면되거든요..저도자세히는모르겠습니다...제이쿼리로만써봐서... */}
return(
<div>
{/* <div className='notice'>
<div className='notice-icon'>
<Bell size={20} />
</div>
<div className='notice-txt'>
<dl>
<dt>
<span className='time'>2021-06-17 12:00:00</span>AVSF123
지역에 접근하였습니다111.
</dt>
<dt>
<span className='time'>2021-06-30 13:00:00</span>AVSF123
비행금지구역에 접근하였습니다.
</dt>
<dt>
<span className='time'>2021-08-20 14:00:00</span>AVSF123
국립공원구역에 접근하였습니다.
</dt>
</dl>
</div>
<div className='notice-btn'>
<button>
<ChevronUp size={15} />
</button>
<button>
<ChevronDown size={15} />
</button>
</div>
</div> */}
</div>
)
}
export default ControlAlarmNotice;

18
src/views/testDraw/index.js

@ -0,0 +1,18 @@
import React, { useEffect, useState } from 'react';
import { MapControlDraw } from '../../components/mapDraw/MapControlDraw';
// import { WebsocketClient } from '../../components/websocket/WebsocketClient';
import ControlMainDraw from './main/ControlMainDraw';
const ControlViewDraw = () => {
return (
<div className='pal-container'>
<div className='map'>
<MapControlDraw />
</div>
<ControlMainDraw />
</div>
);
};
export default ControlViewDraw;

183
src/views/testDraw/main/ControlMainDraw.js

@ -0,0 +1,183 @@
import React, { useEffect, useState } from 'react';
import '../../../assets/css/custom.css';
import logo from '../../../assets/images/pal_logo.png';
import { Sun, Map, Bell } from 'react-feather';
import { AiOutlinePoweroff } from 'react-icons/ai';
import { ReactComponent as DroneMenuIcon } from '../../../assets/images/drone_menu_icon.svg';
import ControlAlarmNotice from '../alarm/ControlAlarmNotice';
import ControlReportList from '../report/ControlReportList';
import ControlReportDetail from '../report/ControlReportDetail';
import WeatherList from '../weather/WeatherList';
import ControlAlarmList from '../alarm/ControlAlarmList';
import ControlSetting from '../setting/ControlSetting';
import WebsocketClient from '../../../components/websocket/WebsocketClient';
import { useDispatch, useSelector } from 'react-redux';
import * as Actions from '../../../modules/account/login/actions/authAction';
import {
ButtonGroup,
Button,
Badge,
CustomInput
} from 'reactstrap'
import {
drawTypeChangeAction
} from '../../../modules/control/map/actions/controlMapActions';
const ControlMainDraw = () => {
const dispatch = useDispatch();
const { isClickObject } = useSelector(state => state.controlMapReducer);
const [oepnReportList, setOpenReportList] = useState(false);
const [openReportDetail, setOpenReportDetail] = useState(false);
const [openWeatherList, setOpenWeatherList] = useState(false);
const [openAlarmList, setOpenAlarmList] = useState(false);
const [openSetting, setOpenSetting] = useState(false);
const mapControl = useSelector(state => state.controlMapReducer);
const openMenu = val => {
if (val === 'reportList') {
setOpenReportList(true);
setOpenReportDetail(false);
setOpenWeatherList(false);
setOpenAlarmList(false);
} else if (val === 'weatherList') {
setOpenReportList(false);
setOpenReportDetail(false);
setOpenWeatherList(true);
setOpenAlarmList(false);
} else if (val === 'alarmList') {
setOpenReportList(false);
setOpenReportDetail(false);
setOpenWeatherList(false);
setOpenAlarmList(true);
}
};
const openReportDetailParam = val => {
console.log(val);
setOpenReportDetail(true);
};
const handlerLogout = () => {
dispatch(Actions.logout.request());
};
const handlerDrawType = val => {
dispatch(drawTypeChangeAction(val));
};
return (
<>
<ControlAlarmNotice />
<div className='left-menu'>
<h1 className='logo'>
<img src={logo} width='80' />
<span>PAL</span>
</h1>
<ul className='left-menu-nav'>
<li>
<button onClick={() => openMenu('reportList')}>
<DroneMenuIcon width='30' height='30' />
</button>
</li>
</ul>
{/* pathDraw Test */}
<ul className='left-menu-nav'>
<li>
<CustomInput
type='button'
onClick={e => handlerDrawType('CIRCLE')}
value='CIRCLE'
/>
<CustomInput
type='button'
onClick={e => handlerDrawType('LINE')}
value='LINE'
/><br/>
<CustomInput
type='button'
onClick={e => handlerDrawType('')}
value='X'
/>
</li>
</ul>
<ul className='left-menu-footer'>
<li>
<AiOutlinePoweroff
size={25}
className='logout-btn'
onClick={handlerLogout}
/>
</li>
<WebsocketClient />
</ul>
</div>
{oepnReportList ? (
<ControlReportList
openReportDetailParam={openReportDetailParam}
setOpenReportList={setOpenReportList}
/>
) : (
<div />
)}
{isClickObject ? (
<ControlReportDetail setOpenReportDetail={setOpenReportDetail} />
) : (
<div />
)}
{openWeatherList ? (
<WeatherList setOpenWeatherList={setOpenWeatherList} />
) : (
<div />
)}
{openAlarmList ? (
<ControlAlarmList setOpenAlarmList={setOpenAlarmList} />
) : (
<div />
)}
{openSetting ? (
<div className='right-menu active'>
<button
className='right-layer-btn'
onClick={() => setOpenSetting(false)}
>
<Map size={18} />
</button>
<div className='right-layer active'>
<ControlSetting />
</div>
</div>
) : (
<div className='right-menu'>
<button
className='right-layer-btn'
onClick={() => setOpenSetting(true)}
>
<Map size={18} />
</button>
<div className='right-layer'></div>
</div>
)}
</>
);
};
export default ControlMainDraw;

10
src/views/testDraw/menu/ControlMenuLeft.js

@ -0,0 +1,10 @@
import React, { useEffect, useState } from 'react';
const ControlMenuLeft = () => {
return(
<></>
)
}
export default ControlMenuLeft();

219
src/views/testDraw/report/ControlReportDetail.js

@ -0,0 +1,219 @@
import moment from 'moment';
import React from 'react';
import { X } from 'react-feather';
import { useDispatch, useSelector } from 'react-redux';
import drone_img from '../../../assets/images/drone.jpg';
import drone_yellow from '../../../assets/images/drone_yellow.png';
import { IMG_PATH } from '../../../configs/constants';
import { objectUnClickAction } from '../../../modules/control/map/actions/controlMapActions';
import {
GET_ARCTFT_TYPE_CD,
GET_WGHT_TYPE_CD
} from '../../../utility/CondeUtil';
const ControlReportDetail = props => {
const dispatch = useDispatch();
const { controlGpDetail, controlDetail } = useSelector(
state => state.controlGpDtlState
);
// useEffect(() => {
// // console.log(controlGpDetail);
// }, [controlGpDetail]);
const handlerClose = () => {
// console.log('================');
dispatch(objectUnClickAction());
};
const nullMessage = val => {
if (val) {
return val;
} else {
return '-';
}
};
return (
<div className='left-layer'>
<div className='layer-content'>
<div className='layer-ti'>
<h4>드론 상세정보</h4>
<button
className='btn-icon'
color='primary'
// onClick={() => props.setOpenReportDetail(false)}
onClick={() => handlerClose()}
>
<X size={20} />
</button>
</div>
<div className='layer-content-box'>
<div className='drone-ti'>
<img src={drone_yellow} width='40' />
{controlDetail?.arcrftModelNm
? controlDetail?.arcrftModelNm
: controlGpDetail?.objectId}
</div>
<div className='drone-img'>
{controlDetail?.imageUrl ? (
<img src={IMG_PATH + controlDetail?.imageUrl} />
) : (
<img src={drone_img} />
)}
</div>
<div className='layer-content-info'>
<dl>
<dt>
<div className='list-left-txt'>제작번호</div>
<div className='list-right-txt'>
{nullMessage(controlDetail?.prdctNum)}
</div>
</dt>
<dt>
<div className='list-left-txt'>식별번호</div>
<div className='list-right-txt'>
{controlGpDetail?.objectId}
</div>
</dt>
<dt>
<div className='list-left-txt'>중량</div>
<div className='list-right-txt'>
{GET_WGHT_TYPE_CD(controlDetail?.wghtTypeCd)}
</div>
</dt>
<dt>
<div className='list-left-txt'>종류</div>
<div className='list-right-txt'>
{GET_ARCTFT_TYPE_CD(controlDetail?.arcrftTypeCd)}
</div>
</dt>
<dt>
<div className='list-left-txt'>배터리 잔량</div>
<div className='list-right-txt'>
{controlGpDetail?.betteryLevel} %
</div>
</dt>
<dt>
<div className='list-left-txt'>배터리 전압</div>
<div className='list-right-txt'>
{controlGpDetail?.betteryVoltage} volt
</div>
</dt>
</dl>
</div>
</div>
</div>
<div className='layer-content'>
<div className='layer-ti'>
<h4>비행정보</h4>
</div>
<div className='layer-content-box'>
<div className='layer-content-info'>
<dl>
<dt>
<div className='list-left-txt'>시작위치</div>
<div className='list-right-txt'>
{nullMessage(controlDetail?.stAreaNm)}
</div>
</dt>
<dt>
<div className='list-left-txt'>시작시간</div>
<div className='list-right-txt'>
{moment(
controlGpDetail?.controlStartDt,
'YYYYMMDDHHmmss'
).format('MM-DD HH:mm:ss')}
</div>
</dt>
{/* <dt>
<div className='list-left-txt'>현재위치</div>
<div className='list-right-txt'>
인천광역시 부평구 안남로 272
</div>
</dt> */}
<dt>
<div className='list-left-txt'>속도</div>
<div className='list-right-txt'>
{controlGpDetail?.speed} {controlGpDetail?.speedType}
</div>
</dt>
<dt>
<div className='list-left-txt'>고도</div>
<div className='list-right-txt'>
{controlGpDetail?.elev} {controlGpDetail?.elevType}
</div>
</dt>
<dt>
<div className='list-left-txt'>좌표</div>
<div className='list-right-txt'>
{controlGpDetail?.lat} , {controlGpDetail?.lng}
</div>
</dt>
<dt>
<div className='list-left-txt'>비행거리</div>
<div className='list-right-txt'>
{nullMessage(controlGpDetail?.moveDistance)}{' '}
{controlGpDetail?.moveDistanceType}
</div>
</dt>
<dt>
<div className='list-left-txt'>헤딩 방위각</div>
<div className='list-right-txt'>
{controlGpDetail?.heading} °
</div>
</dt>
<dt>
<div className='list-left-txt'>상태</div>
<div className='list-right-txt'>
{nullMessage(controlGpDetail?.dronStatus)}
</div>
</dt>
<dt>
<div className='list-left-txt'>위치정보 수신 시간</div>
<div className='list-right-txt'>
{' '}
{moment(
controlGpDetail?.serverRcvDt,
'YYYYMMDDHHmmss'
).format('MM-DD HH:mm:ss')}
</div>
</dt>
</dl>
</div>
</div>
</div>
<div className='layer-content'>
<div className='layer-ti'>
<h4>운영자 정보</h4>
</div>
<div className='layer-content-box'>
<div className='layer-content-info'>
<dl>
{/* <dt>
<div className='list-left-txt'>소속기관</div>
<div className='list-right-txt'>팔네트웍스</div>
</dt> */}
<dt>
<div className='list-left-txt'>담당자 이름</div>
<div className='list-right-txt'>
{' '}
{nullMessage(controlDetail?.ownerNm)}
</div>
</dt>
<dt>
<div className='list-left-txt'>담당자 연락처</div>
<div className='list-right-txt'>
{nullMessage(controlDetail?.hpno)}
</div>
</dt>
</dl>
</div>
</div>
</div>
</div>
);
};
export default ControlReportDetail;

115
src/views/testDraw/report/ControlReportList.js

@ -0,0 +1,115 @@
import moment from 'moment';
import React, { useEffect, useState } from 'react';
import { Search, X } from 'react-feather';
import { useDispatch, useSelector } from 'react-redux';
import { Badge, Button, Input, InputGroup } from 'reactstrap';
import { controlGpDtlAction } from '../../../modules/control/gp';
import { objectClickAction } from '../../../modules/control/map/actions/controlMapActions';
const ControlReportList = props => {
const { controlGpList } = useSelector(state => state.controlGpState);
const [filterId, setFilterId] = useState('');
const dispatch = useDispatch();
useEffect(() => {
// console.log('>>>>', filterId);
controlGpList;
}, [controlGpList]);
const handlerDetail = (objectId, cntrlId) => {
dispatch(objectClickAction(objectId));
dispatch(controlGpDtlAction.request(cntrlId));
};
// useEffect(() => {}, [filterId]);
return (
<div className='left-layer'>
<div className='layer-content'>
<div className='layer-ti'>
<h4>드론 비행 현황 정보{filterId}</h4>
<button
className='btn-icon'
color='primary'
onClick={() => props.setOpenReportList(false)}
>
<X size={20} />
</button>
</div>
<div className='layer-search'>
<InputGroup>
<Input
type='text'
placeholder='식별번호를 입력하세요'
value={filterId}
onChange={e => setFilterId(`${e.target.value}`)}
/>
<Button color='primary' outline>
<Search size={18} />
</Button>
</InputGroup>
</div>
</div>
<div className='layer-content drone-list'>
<div className='layer-ti'>
<h4>드론 현황</h4>
<Badge color='light-primary'>
{controlGpList ? controlGpList.length : 0} 비행중
</Badge>
</div>
{controlGpList?.map(item => {
// console.log(item);
if (item.objectId && item.objectId.indexOf(filterId) != -1) {
console.log(item);
return (
<div
className='layer-content-list'
onClick={() => handlerDetail(item.objectId, item.controlId)}
key={item.objectId}
>
<dl>
<dt>
<div className='list-left-txt'>식별번호</div>
<div className='list-right-txt'>{item.objectId}</div>
</dt>
<dt>
<div className='list-left-txt'>이륙 위치</div>
<div className='list-right-txt'>-</div>
</dt>
<dt>
<div className='list-left-txt'>이륙 시간</div>
<div className='list-right-txt'>
{moment(item.controlStartDt, 'YYYYMMDDHHmmss').format(
'MM-DD HH:mm:ss'
)}
</div>
</dt>
<dt>
<div className='list-left-txt'>속도(고도)</div>
<div className='list-right-txt'>
{item.speed ? item.speed : '-'}{' '}
{item.speed ? item.speedType : ''} &nbsp;(
{item.elev ? item.elev : '-'}{' '}
{item.elev ? item.elevType : ''})
</div>
</dt>
<dt>
<div className='list-left-txt'>상태</div>
<div className='list-right-txt'>
{item.dronStatus ? item.dronStatus : '-'}
</div>
</dt>
</dl>
</div>
);
}
})}
</div>
</div>
);
};
export default ControlReportList;

244
src/views/testDraw/setting/ControlSetting.js

@ -0,0 +1,244 @@
import React, { useEffect, useState } from 'react';
import { Search } from 'react-feather';
import { BiBuildings, BiGridAlt } from 'react-icons/bi';
import { CgTrees } from 'react-icons/cg';
import { VscRadioTower } from 'react-icons/vsc';
import { useDispatch, useSelector } from 'react-redux';
import {
Button,
InputGroup,
ButtonGroup,
InputGroupAddon,
Input,
CustomInput
} from 'reactstrap';
import {
areaClickAction, environmentClickAction,
mapTypeChangeAction, sensorClickAction, drawTypeChangeAction
} from '../../../modules/control/map/actions/controlMapActions';
const ControlSetting = props => {
const dispatch = useDispatch();
const mapControl = useSelector(state => state.controlMapReducer);
// console.log('111111111111111');
// useEffect(() => {
// console.log('111111111111111');
// }, []);
useEffect(() => {
console.log('>>>>', mapControl);
}, [mapControl]);
const handlerMapType = val => {
dispatch(mapTypeChangeAction(val));
};
const handlerAreaClick = val => {
dispatch(areaClickAction(val));
};
// const handlerDrawType = val => {
// dispatch(drawTypeChangeAction(val));
// };
const handlerSensorClick = (val, isChecked) => {
if(isChecked){
dispatch(sensorClickAction(val));
} else {
dispatch(sensorClickAction(''));
}
};
return (
<div className=''>
{/* <div className='layer-content'>
<div className='layer-ti'>
<h4>flight path option</h4>
</div>
<div className='map-btn'>
<ButtonGroup>
<Button
color={mapControl.drawType === 'CIRCLE' ? 'primary' : ''}
onClick={e => handlerDrawType('CIRCLE')}
>
circle
</Button>
<Button
color={mapControl.drawType === 'LINE' ? 'primary' : ''}
onClick={e => handlerDrawType('LINE')}
>
line
</Button>
<Button
color={mapControl.drawType === 'POLYGON' ? 'primary' : ''}
onClick={e => handlerDrawType('POLYGON')}
>
polygon
</Button>
</ButtonGroup>
</div>
</div> */}
<div className='layer-content'>
<div className='layer-ti'>
<h4>지도유형</h4>
{/* <button className='btn-icon' outline color='primary'><X size={20} /></button> */}
</div>
<div className='map-btn'>
<ButtonGroup>
<Button
color={mapControl.mapType === 'HYBRID' ? 'primary' : ''}
onClick={e => handlerMapType('HYBRID')}
>
위성지도
</Button>
<Button
color={mapControl.mapType === 'NORMAL' ? 'primary' : ''}
onClick={e => handlerMapType('NORMAL')}
>
일반지도
</Button>
<Button
color={mapControl.mapType === 'TERRAIN' ? 'primary' : ''}
onClick={e => handlerMapType('TERRAIN')}
>
지형지도
</Button>
</ButtonGroup>
</div>
</div>
<div className='layer-content'>
<div className='layer-ti'>
<h4>공역 표출 정보</h4>
</div>
<div className='layer-content-box'>
<div className='layer-content-info layer-switch-list'>
<dl>
<dt>
<div className='list-left-txt'>
<span className='dot-icon color-red'></span>
</div>
<div className='list-right-txt'>
<CustomInput
onClick={e => handlerAreaClick('0001')}
className='custom-control-primary'
type='switch'
id='test01'
name='test01'
inline
defaultChecked={mapControl.area0001}
/>
</div>
</dt>
<dt>
<div className='list-left-txt'>
<span className='dot-icon color-pink'></span>
</div>
<div className='list-right-txt'>
<CustomInput
onClick={e => handlerAreaClick('0002')}
className='custom-control-primary'
type='switch'
id='test02'
name='test02'
inline
defaultChecked={mapControl.area0002}
/>
</div>
</dt>
<dt>
<div className='list-left-txt'>
<span className='dot-icon color-orange'></span>()
</div>
<div className='list-right-txt'>
<CustomInput
onClick={e => handlerAreaClick('0003')}
className='custom-control-primary'
type='switch'
id='test03'
name='test03'
inline
defaultChecked={mapControl.area0003}
/>
</div>
</dt>
<dt>
<div className='list-left-txt'>
<span className='dot-icon color-brown'></span>()
</div>
<div className='list-right-txt'>
<CustomInput
onClick={e => handlerAreaClick('0004')}
className='custom-control-primary'
type='switch'
id='test04'
name='test04'
inline
defaultChecked={mapControl.area0004}
/>
</div>
</dt>
<dt>
<div className='list-left-txt'>
<span className='dot-icon color-purple'></span>
</div>
<div className='list-right-txt'>
<CustomInput
onClick={e => handlerAreaClick('0005')}
className='custom-control-primary'
type='switch'
id='test05'
name='test05'
inline
defaultChecked={mapControl.area0005}
/>
</div>
</dt>
<dt>
<div className='list-left-txt'>
<span className='dot-icon color-skyblue'></span>
초경량비행장치공역
</div>
<div className='list-right-txt'>
<CustomInput
onClick={e => handlerAreaClick('0006')}
className='custom-control-primary'
type='switch'
id='test06'
name='test06'
inline
defaultChecked={mapControl.area0006}
/>
</div>
</dt>
</dl>
</div>
</div>
</div>
{/* <dt>
<div className='list-left-txt'>
<span className='dot-icon color-red'></span>(DUST)
</div>
<div className='list-right-txt'>
<CustomInput
onChange={e => handlerSensorClick('dust', e.target.checked)}
className='custom-control-primary'
type='switch'
id='sensorDust'
name='sensorDust'
inline
checked={mapControl.sensor === 'dust'}
// defaultChecked={mapControl.sensor === 'dust'}
/>
</div>
</dt> */}
</div>
);
};
export default ControlSetting;

233
src/views/testDraw/weather/WeatherList.js

@ -0,0 +1,233 @@
import React, { useEffect, useState } from 'react';
import {
CloudDrizzle,
CloudLightning,
Navigation2,
X,
Search,
Compass,
Sun,
Cloud,
CloudRain,
CloudSnow
} from 'react-feather';
import { Button, InputGroup, InputGroupAddon, Input, Table } from 'reactstrap';
const WeatherList = props => {
const [clickTab, setClickTab] = useState(true);
return (
<div className='left-layer'>
<div className='layer-content'>
<div className='layer-ti'>
<h4>날씨 상세정보</h4>
<button
className='btn-icon'
outline
color='primary'
onClick={() => props.setOpenWeatherList(false)}
>
<X size={20} />
</button>
</div>
<div className='layer-search'>
<InputGroup>
<Input type='text' placeholder='검색어를 입력하세요' />
<Button color='primary' outline>
<Search size={18} />
</Button>
</InputGroup>
</div>
</div>
<div className='layer-content'>
<div className='layer-weather-box'>
<div className='layer-weather-info'>
<div className='layer-weather-table'>
<div className='layer-weather-address'>
검색하신 지역의 날씨 정보입니다.
<span>
<Compass size={20} /> 인천광역시 부평구 안남로 272
</span>
</div>
{/* 탭메뉴or탭내용 활성화 active */}
<div className='tab-menu'>
<ul>
{clickTab ? (
<>
<li className='active'>오늘</li>
<li className='' onClick={e => setClickTab(false)}>
주간
</li>
</>
) : (
<>
<li className='' onClick={e => setClickTab(true)}>
오늘
</li>
<li className='active'>주간</li>
</>
)}
</ul>
</div>
{clickTab ? (
<div className='tab-content active'>
<Table responsive>
<thead>
<tr>
<th>시각</th>
<th>날씨</th>
<th>기온</th>
<th>풍향</th>
<th>풍속</th>
</tr>
</thead>
<tbody>
<tr>
<td>10</td>
<td>
<Sun />
</td>
<td>27</td>
<td>
<Navigation2 className='rotate-45' />
</td>
<td>2m/s</td>
</tr>
<tr>
<td>12</td>
<td>
<CloudLightning />
</td>
<td>30</td>
<td>
<Navigation2 className='rotate-75' />
</td>
<td>3m/s</td>
</tr>
<tr>
<td>14</td>
<td>
<Cloud />
</td>
<td>28</td>
<td>
<Navigation2 className='rotate-90' />
</td>
<td>4m/s</td>
</tr>
<tr>
<td>16</td>
<td>
<CloudRain />
</td>
<td>27</td>
<td>
<Navigation2 className='rotate-135' />
</td>
<td>7m/s</td>
</tr>
<tr>
<td>18</td>
<td>
<CloudSnow />
</td>
<td>25</td>
<td>
<Navigation2 className='rotate-180' />
</td>
<td>2m/s</td>
</tr>
<tr>
<td>20</td>
<td>
<CloudDrizzle />
</td>
<td>26</td>
<td>
<Navigation2 className='rotate-225' />
</td>
<td>2m/s</td>
</tr>
</tbody>
</Table>
</div>
) : (
<div className='tab-content active'>
<Table responsive>
<thead>
<tr>
<th>날짜</th>
<th>날씨</th>
<th>기온</th>
</tr>
</thead>
<tbody>
<tr>
<td>06.19.() 오전</td>
<td>
<Sun />
</td>
<td>최저 27</td>
</tr>
<tr>
<td>06.19.() 오후</td>
<td>
<CloudLightning />
</td>
<td>30</td>
</tr>
<tr>
<td>06.20.() 오전</td>
<td>
<CloudLightning />
</td>
<td>30</td>
</tr>
<tr>
<td>06.20.() 오후</td>
<td>
<CloudLightning />
</td>
<td>30</td>
</tr>
<tr>
<td>06.21.() 오전</td>
<td>
<CloudLightning />
</td>
<td>30</td>
</tr>
<tr>
<td>06.21.() 오후</td>
<td>
<CloudLightning />
</td>
<td>30</td>
</tr>
<tr>
<td>06.22.() 오전</td>
<td>
<CloudLightning />
</td>
<td>30</td>
</tr>
<tr>
<td>06.2.() 오후</td>
<td>
<CloudLightning />
</td>
<td>30</td>
</tr>
</tbody>
</Table>
</div>
)}
</div>
</div>
</div>
</div>
</div>
);
};
export default WeatherList;
Loading…
Cancel
Save