diff --git a/src/components/basis/flight/plan/FlightPlanAreaMap.js b/src/components/basis/flight/plan/FlightPlanAreaMap.js
index f0c10f5..6ad848f 100644
--- a/src/components/basis/flight/plan/FlightPlanAreaMap.js
+++ b/src/components/basis/flight/plan/FlightPlanAreaMap.js
@@ -132,7 +132,7 @@ const FlightPlanAreaMap = (props) => {
handlerDrawType('RESET')}
+ onClick={e => handlerDrawType('RESET')}
>
초기화
diff --git a/src/components/map/naver/NaverMap.js b/src/components/map/naver/NaverMap.js
index 7c95e6b..df7ea63 100644
--- a/src/components/map/naver/NaverMap.js
+++ b/src/components/map/naver/NaverMap.js
@@ -10,6 +10,7 @@ import { FeatureAirZone } from './feature/FeatureAirZone';
import geoJson from '../geojson/airArea.json';
import SensorZone from "./sensor/SensorZone";
import { controlGroupAuthAction } from '../../../modules/control/gp';
+import DronPlan from './dron/DronPlan';
export const NaverCustomMap = () => {
const dispatch = useDispatch();
@@ -68,6 +69,10 @@ export const NaverCustomMap = () => {
naver={naver}
test={test}
/>
+
diff --git a/src/components/map/naver/dron/DronMarker.js b/src/components/map/naver/dron/DronMarker.js
index 2681e28..d4ab443 100644
--- a/src/components/map/naver/dron/DronMarker.js
+++ b/src/components/map/naver/dron/DronMarker.js
@@ -3,11 +3,13 @@ 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, controlGpHisAction, controlDbHisAction } from '../../../../modules/control/gp';
+import { controlGpDtlAction, controlGpHisAction, controlDbHisAction, controlGpFlightPlanAction } from '../../../../modules/control/gp';
import { objectClickAction } from '../../../../modules/control/map/actions/controlMapActions';
export const DronMarker = props => {
const { controlGpList } = useSelector(state => state.controlGpState);
+ const { controlGroupAuthInfo } = useSelector(state => state.controlGroupAuthState);
+
const { objectId, isClickObject } = useSelector(
state => state.controlMapReducer
);
@@ -36,20 +38,20 @@ export const DronMarker = props => {
origin: new naver.maps.Point(0, 0),
anchor: new naver.maps.Point(15, 15),
});
- } else {
+ } else {
clickMarker.setIcon({
url: DronIcon,
origin: new naver.maps.Point(0, 0),
anchor: new naver.maps.Point(15, 15),
});
}
- });
+ });
}, [objectId, isClickObject]);
useEffect(() => {
arrMarkers.map(clickMarker => {
- if (objectId === clickMarker.id) {
- props.map.setCenter(clickMarker.getPosition());
+ if (objectId === clickMarker.id) {
+ props.map.setCenter(clickMarker.getPosition());
props.map.setZoom(13, true);
}
});
@@ -78,18 +80,22 @@ export const DronMarker = props => {
naver.maps.Event.addListener(marker, 'click', function (e) {
handlerDronClick(marker);
- });
-
+ });
+
setArrMarkers(m => [...m, marker]);
};
- const handlerDronClick = marker => {
- // const markerId = marker.id;
- const contorlId = marker.controlId;
+ const handlerDronClick = marker => {
+ const idntfNum = marker.id;
+ const contorlId = marker.controlId;
+
+ // 클릭한 식별번호 정보를 가진 그룹 추출 (1건만 존재해야하는게 맞는 듯)
+ const group = controlGroupAuthInfo.find(group => group.idntfNum === idntfNum);
//히스토리 불러오기
dispatch(objectClickAction(contorlId));
- dispatch(controlGpDtlAction.request(contorlId));
+ dispatch(controlGpDtlAction.request(contorlId));
+ dispatch(controlGpFlightPlanAction.request(group));
};
//마커를 삭제 한다.
@@ -98,7 +104,7 @@ export const DronMarker = props => {
};
//마커에 위치를 이동한다.
- const moveMarkers = (marker, position) => {
+ const moveMarkers = (marker, position) => {
marker.setPosition(position);
};
@@ -117,33 +123,33 @@ export const DronMarker = props => {
removeArrMarkers(arrData);
}
});
- }
+ }
};
//마커를 셋팅 한다.
const markerInit = () => {
if (controlGpList) {
- allRemoveMarkers();
+ allRemoveMarkers();
controlGpList.map(item => {
const position = new naver.maps.LatLng(item.lat, item.lng);
- if (arrMarkers) {
+ if (arrMarkers) {
const isExists = arrMarkers.find(
ele => ele.id === item.objectId
);
- if (isExists) {
+ if (isExists) {
moveMarkers(isExists, position);
} else {
addMarkers(position, item.objectId, item.controlId);
}
- } else {
+ } else {
addMarkers(position, item.objectId, item.controlId);
}
});
}
};
- const removeArrMarkers = arrData => {
+ const removeArrMarkers = arrData => {
setArrMarkers(arrData);
};
diff --git a/src/components/map/naver/dron/DronPlan.js b/src/components/map/naver/dron/DronPlan.js
new file mode 100644
index 0000000..1d26d4e
--- /dev/null
+++ b/src/components/map/naver/dron/DronPlan.js
@@ -0,0 +1,180 @@
+import { useEffect, useState } from 'react';
+import { useSelector } from 'react-redux';
+
+
+const DronPlan = ({ naver, map }) => {
+ const { controlGpList } = useSelector(state => state.controlGpState);
+ const { controlGpFltPlanList } = useSelector(state => state.controlGpFltPlanState);
+ const { objectId, isClickObject } = useSelector(state => state.controlMapReducer);
+
+ const [area, setArea] = useState(); // 비행 구역 관리
+ const [buffer, setBuffer] = useState(); // 버퍼 구역 관리
+ const [controlId, setControlId] = useState(); // 식별번호 저장
+
+ useEffect(() => {
+ if (controlGpFltPlanList) {
+ init();
+ }
+ }, [controlGpFltPlanList])
+
+ useEffect(() => {
+ if (!isClickObject) {
+
+ // 관제 종료시 영역 초기화.
+ clear();
+
+ } else {
+ setControlId(objectId);
+ }
+
+ }, [objectId ,isClickObject]);
+
+ useEffect(() => {
+ // 구역 대상의 드론 데이터가 지도 상에 존재하고 있는지 체크해야 한다. (없을 경우 영역 제거)
+ if(controlId && isClickObject) {
+ if (controlGpList) {
+ const isExist = controlGpList.find(data => data.controlId === controlId)
+
+ if(!isExist) {
+ clear();
+ }
+ }
+ }
+ }, [controlGpList])
+
+
+ /* 비행 구역 그리기. */
+ const init = () => {
+ if(area) {
+ area.setMap(null);
+ }
+
+ /* 좌표 추출 */
+ const planList = controlGpFltPlanList;
+ planList.forEach(plan => {
+
+ const areaList = plan.areaList;
+
+ // 구역 정보는 계획서당 1개만 존재
+ areaList.forEach(area => {
+ const coordList = area.coordList; // 기초 좌표
+ const bufferList = area.bufferCoordList; // 기초 좌표의 버퍼 좌표
+ const bufferZone = area.bufferZone; // 반경 값
+ const areaType = area.areaType; // 도형 타입
+
+ const paths = [];
+ coordList.forEach((coord) => {
+ const path = new naver.maps.LatLng(coord.lat, coord.lon)
+
+ paths.push(path);
+ });
+
+ clear();
+
+ if (areaType === 'LINE') {
+ polyline(paths, bufferList);
+ }
+
+ if (areaType === 'POLYGON') {
+ polygon(paths);
+ }
+
+ if (areaType === 'CIRCLE') {
+ circle(paths, bufferZone);
+ }
+
+ });
+ })
+ }
+
+ /* Polyline Create */
+ const polyline = (paths, bufferList) => {
+ if (paths && paths.length > 1) {
+ const line = new naver.maps.Polyline({
+ strokeLineCap: 'round',
+ strokeLineJoin: 'round',
+ strokeColor: '#283046',
+ strokeWeight: 1,
+ strokeOpacity: 0.5,
+ path: paths,
+ map: map
+ });
+
+ setArea(line);
+ }
+
+ if (bufferList && bufferList.length > 1) {
+ const paths = [];
+ bufferList.forEach((buffer) => {
+ const path = new naver.maps.LatLng(buffer.lat, buffer.lon)
+
+ paths.push(path);
+ });
+
+ const lineBuffer = new naver.maps.Polygon({
+ strokeColor: '#283046',
+ strokeOpacity: 1,
+ fillColor: '#7367F0',
+ fillOpacity: 0.1,
+ paths: paths,
+ map: map
+ });
+
+ setBuffer(lineBuffer);
+ }
+ }
+
+ /* Polygon Create */
+ const polygon = (paths) => {
+ if (paths && paths.length > 1) {
+ const poly = new naver.maps.Polygon({
+ strokeColor: '#283046',
+ strokeOpacity: 1,
+ fillColor: '#7367F0',
+ fillOpacity: 0.1,
+ paths: paths,
+ map: map
+ });
+
+ setArea(poly);
+ }
+ }
+
+ /* Circle Create */
+ const circle = (paths, bufferZone) => {
+
+ if (paths[0].lat !== 0 && paths[0].lon !== 0) {
+ const circle = new naver.maps.Circle({
+ strokeColor: '#283046',
+ strokeOpacity: 1,
+ fillColor: '#7367F0',
+ fillOpacity: 0.1,
+ center: paths[0],
+ radius: bufferZone,
+ map: map,
+ clickable: true
+ });
+
+ setArea(circle);
+ }
+ }
+
+ /* 구역 초기화 */
+ const clear = () => {
+
+ if(area) {
+ area.setMap(null);
+
+ setArea();
+ if(buffer) {
+ buffer.setMap(null);
+ setBuffer();
+ }
+ }
+ }
+
+
+ return null;
+}
+
+export default DronPlan;
\ No newline at end of file
diff --git a/src/modules/control/gp/actions/controlGpAction.ts b/src/modules/control/gp/actions/controlGpAction.ts
index 825619c..404c500 100644
--- a/src/modules/control/gp/actions/controlGpAction.ts
+++ b/src/modules/control/gp/actions/controlGpAction.ts
@@ -5,6 +5,8 @@ import {
ControlDetailData,
ControlGpData,
ControlGpDtlState,
+ ControlGpFlightPlanDataList,
+ ControlGpFlightPlanRQ,
ControlGpHisState,
ControlGpState,
ControlGroupAuthState
@@ -31,6 +33,11 @@ const CONTROL_GROUP_AUTH_REQUEST = 'control/group/CONTROL_GROUP_AUTH_REQUEST';
const CONTROL_GROUP_AUTH_SUCCESS = 'control/group/CONTROL_GROUP_AUTH_SUCCESS';
const CONTROL_GROUP_AUTH_FAILURE = 'control/group/CONTROL_GROUP_AUTH_FAILURE';
+// [관제]
+const CONTROL_FLIGHT_PLAN_REQUEST = 'control/gp/flight/plan/CONTROL_FLIGHT_PLAN_REQUEST';
+const CONTROL_FLIGHT_PLAN_SUCCESS = 'control/gp/flight/plan/CONTROL_FLIGHT_PLAN_SUCCESS';
+const CONTROL_FLIGHT_PLAN_FAILURE = 'control/gp/flight/plan/CONTROL_FLIGHT_PLAN_FAILURE';
+
export const controlGpAction = createAsyncAction(
CONTROL_GP_REQUEST,
CONTROL_GP_SUCCESS,
@@ -61,12 +68,19 @@ export const controlGroupAuthAction = createAsyncAction(
CONTROL_GROUP_AUTH_FAILURE
)();
+export const controlGpFlightPlanAction = createAsyncAction(
+ CONTROL_FLIGHT_PLAN_REQUEST,
+ CONTROL_FLIGHT_PLAN_SUCCESS,
+ CONTROL_FLIGHT_PLAN_FAILURE,
+)();
+
const actions = {
controlGpAction,
controlGpHisAction,
controlGpDtlAction,
controlGpRtDtlAction,
- controlGroupAuthAction
+ controlGroupAuthAction,
+ controlGpFlightPlanAction
};
export type ControlGpAction = ActionType;
diff --git a/src/modules/control/gp/apis/controlGpApi.ts b/src/modules/control/gp/apis/controlGpApi.ts
index 218666f..3bfaa83 100644
--- a/src/modules/control/gp/apis/controlGpApi.ts
+++ b/src/modules/control/gp/apis/controlGpApi.ts
@@ -1,5 +1,6 @@
import axios from '../../../utils/customAxiosUtil';
-import { ReponseControlGpHistory, ControlGroupAuthData, ResponseControlGroupAuth} from '../models/controlGpModel';
+import { ReponseControlGpHistory, ControlGroupAuthData, ResponseControlGroupAuth, ControlGpFlightPlanRQ } from '../models/controlGpModel';
+import qs from 'qs';
export const controlGpApi = {
getHistory: async (id: string) => {
@@ -17,12 +18,28 @@ export const controlGpApi = {
return await axios.get(`api/ctr/cntrl/detail/${id}`);
},
getGroupAuth: async (id: number) => {
- if(!id) {
+ if (!id) {
return null;
}
- const { data }:ResponseControlGroupAuth = await axios.get(
+ const { data }: ResponseControlGroupAuth = await axios.get(
`api/ctr/cntrl/group?cstmrSno=${id}`
- );
+ );
return data;
},
+ getFlightPlan: async (rq: ControlGpFlightPlanRQ) => {
+ if (!rq.idntfNum) {
+ return null;
+ }
+
+ const queryString = qs.stringify(rq, {
+ addQueryPrefix: true,
+ arrayFormat: 'repeat'
+ });
+
+ const { data } = await axios.get(
+ `api/ctr/cntrl/flight_plan${queryString}`
+ );
+
+ return data;
+ }
};
diff --git a/src/modules/control/gp/models/controlGpModel.ts b/src/modules/control/gp/models/controlGpModel.ts
index 5870172..2ec8f97 100644
--- a/src/modules/control/gp/models/controlGpModel.ts
+++ b/src/modules/control/gp/models/controlGpModel.ts
@@ -1,5 +1,9 @@
export interface ControlGpState {
- controlGpList: ControlGpData[] | undefined;
+ controlGpList: ControlGpData[] | undefined;
+}
+
+export interface ControlGpFlightPlanState {
+ controlGpFltPlanList: ControlGpFlightPlanDataList | undefined;
}
export interface ControlGpHisState {
@@ -93,6 +97,66 @@ export interface ControlGroupAuthData {
createUserId: string
}
+export interface ControlGpFlightPlanDataList extends Array {};
+
+export interface ControlGpFlightPlanData {
+ planSno?: number,
+ groupId: string,
+ cstmrSno: number,
+ memberName: string,
+ email: string,
+ hpno: string,
+ clncd: string,
+ addr: string,
+ addrDtlCn: string,
+ zip: string,
+ schFltStDt: string,
+ schFltEndDt: string,
+ fltPurpose: string,
+ aprvlYn: string,
+ delYn: string,
+ createUserId: string,
+ createDt: string,
+ updateUserId: string,
+ updateDt: string,
+ areaList?: FlightPlanAreaDataList | undefined
+}
+
+export interface FlightPlanAreaDataList extends Array {};
+
+export interface FlightPlanAreaData {
+ planAreaSno?: number,
+ planSno: number,
+ areaType: string,
+ fltMethod: string,
+ bufferZone: number,
+ fltElev: string,
+ createUserId?: string,
+ createDt?: string,
+ updateUserId?: string,
+ updateDt?: string,
+ coordList?: FlightPlanAreaCoordDataList | undefined
+ bufferCoordList?: FlightPlanAreaCoordDataList | undefined
+}
+
+export interface FlightPlanAreaCoordDataList extends Array {};
+
+export interface FlightPlanAreaCoordData {
+ planAreaCoordSno?: number,
+ planAreaSno?: number,
+ lat: number,
+ lon: number,
+ createUserId?: string,
+ createDt?: string
+ // docState: string
+}
+
+export interface ControlGpFlightPlanRQ {
+ idntfNum: string,
+ groupId: string,
+ cstmrSno: number, // 흠
+}
+
export interface ReponseControlGpHistory {
data: ControlGpHistoryData[];
}
@@ -107,4 +171,5 @@ export const initiaResponseControlGpData = {
controlGpHistory: undefined,
controlDetail: undefined,
controlGroupAuthInfo: undefined,
+ controlGpFltPlanList: undefined,
};
diff --git a/src/modules/control/gp/reducers/controlGpReducer.ts b/src/modules/control/gp/reducers/controlGpReducer.ts
index 32aef1b..98a981f 100644
--- a/src/modules/control/gp/reducers/controlGpReducer.ts
+++ b/src/modules/control/gp/reducers/controlGpReducer.ts
@@ -4,13 +4,15 @@ import {
ControlGpAction,
controlGpAction,
controlGpDtlAction,
+ controlGpFlightPlanAction,
controlGpHisAction,
controlGpRtDtlAction,
controlGroupAuthAction
} from '../actions/controlGpAction';
import {
ControlDetailData,
- ControlGpDtlState,
+ ControlGpDtlState,
+ ControlGpFlightPlanState,
ControlGpHisState,
ControlGpState,
ControlGroupAuthState,
@@ -24,6 +26,15 @@ export const controlGpReducer = createReducer(
const { controlGpList } = action.payload;
draft.controlGpList = controlGpList;
})
+)
+
+export const controlGpFltPlanReducer = createReducer(
+ initiaResponseControlGpData
+).handleAction(controlGpFlightPlanAction.success, (state, action) =>
+ produce(state, draft => {
+ const list = action.payload;
+ draft.controlGpFltPlanList = list;
+ })
);
export const controlGpHisReducer = createReducer<
diff --git a/src/modules/control/gp/sagas/controlGpSaga.ts b/src/modules/control/gp/sagas/controlGpSaga.ts
index 853592b..14e45ee 100644
--- a/src/modules/control/gp/sagas/controlGpSaga.ts
+++ b/src/modules/control/gp/sagas/controlGpSaga.ts
@@ -39,7 +39,6 @@ function* getControlGpSaga(
controlGpList: gpsData
})
);
-
if (objectId && isClickObject) {
@@ -118,12 +117,10 @@ function* controlGroupAuthSaga (
const token = cookieStorage.getCookie(COOKIE_ACCESS_TOKEN);
try {
- if(token) {
- console.log("group auth token : ", token);
+ if(token) {
const user = decode(token);
-
const data = yield call(controlGpApi.getGroupAuth, user.cstmrSno);
- console.log("group auth data : ", data);
+
yield put(Actions.controlGroupAuthAction.success({
controlGroupAuthInfo: data
@@ -134,10 +131,28 @@ function* controlGroupAuthSaga (
}
}
+function* controlGpFlightPlanSaga (
+ action: ActionType
+) {
+ try {
+ const rq = action.payload;
+
+ const list = yield call(controlGpApi.getFlightPlan, rq);
+
+ console.log("flight plan list : ", list);
+
+ yield put(Actions.controlGpFlightPlanAction.success(list));
+
+ } catch (error) {
+ yield put(Actions.controlGpFlightPlanAction.failure(error));
+ }
+}
+
export function* controlGpSaga() {
yield takeEvery(Actions.controlGpAction.request, getControlGpSaga);
yield takeEvery(Actions.controlGpHisAction.request, getControlGpHistorySaga);
yield takeEvery(Actions.controlGpRtDtlAction.request, controlGpRtDtlSaga);
yield takeEvery(Actions.controlGpDtlAction.request, controlDtlSaga);
yield takeEvery(Actions.controlGroupAuthAction.request, controlGroupAuthSaga);
+ yield takeEvery(Actions.controlGpFlightPlanAction.request, controlGpFlightPlanSaga);
}
diff --git a/src/redux/reducers/rootReducer.ts b/src/redux/reducers/rootReducer.ts
index ae07618..35f4130 100644
--- a/src/redux/reducers/rootReducer.ts
+++ b/src/redux/reducers/rootReducer.ts
@@ -19,8 +19,9 @@ import {
controlGpHisReducer,
controlGpReducer,
controlGroupAuthReducer,
+ controlGpFltPlanReducer,
controlGpSaga,
- ControlGpState,
+ ControlGpState,
} from '../../modules/control/gp';
import controlMapReducer from '../../modules/control/map/reducers/controlMapReducer';
import { mainDahReducer } from '../../modules/main/dash/reducers/mainDashReducer';
@@ -63,7 +64,8 @@ const rootReducer = combineReducers({
controlGpState: controlGpReducer,
controlGpHisState: controlGpHisReducer,
controlGpDtlState: controlGpDtlReducer,
- controlGroupAuthState: controlGroupAuthReducer,
+ controlGroupAuthState: controlGroupAuthReducer,
+ controlGpFltPlanState: controlGpFltPlanReducer,
menuState: menuReducer,
analysisHistoryState: analysisHistoryReducer,
analysisSimulatorState: analysisSimulatorReducer,