Browse Source

Merge branch 'master' of http://gitea.palntour.com/pav/pav-home

feature/auth
junh_eee(이준희) 2 years ago
parent
commit
9cf985a5c7
  1. 2
      src/components/basis/flight/plan/FlightPlanAreaMap.js
  2. 5
      src/components/map/naver/NaverMap.js
  3. 42
      src/components/map/naver/dron/DronMarker.js
  4. 180
      src/components/map/naver/dron/DronPlan.js
  5. 16
      src/modules/control/gp/actions/controlGpAction.ts
  6. 25
      src/modules/control/gp/apis/controlGpApi.ts
  7. 67
      src/modules/control/gp/models/controlGpModel.ts
  8. 13
      src/modules/control/gp/reducers/controlGpReducer.ts
  9. 25
      src/modules/control/gp/sagas/controlGpSaga.ts
  10. 6
      src/redux/reducers/rootReducer.ts

2
src/components/basis/flight/plan/FlightPlanAreaMap.js

@ -132,7 +132,7 @@ const FlightPlanAreaMap = (props) => {
<Button.Ripple
color='primary'
className='area-button'
onClick={e => handlerDrawType('RESET')}
onClick={e => handlerDrawType('RESET')}
>
초기화
</Button.Ripple>

5
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}
/>
<DronPlan
map={mapObject}
naver={naver}
/>
<NaverMapControl map={mapObject} />

42
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);
};

180
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;

16
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
)<string, ControlGroupAuthState, AxiosError>();
export const controlGpFlightPlanAction = createAsyncAction(
CONTROL_FLIGHT_PLAN_REQUEST,
CONTROL_FLIGHT_PLAN_SUCCESS,
CONTROL_FLIGHT_PLAN_FAILURE,
)<ControlGpFlightPlanRQ, ControlGpFlightPlanDataList, AxiosError>();
const actions = {
controlGpAction,
controlGpHisAction,
controlGpDtlAction,
controlGpRtDtlAction,
controlGroupAuthAction
controlGroupAuthAction,
controlGpFlightPlanAction
};
export type ControlGpAction = ActionType<typeof actions>;

25
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;
}
};

67
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<ControlGpFlightPlanData> {};
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<FlightPlanAreaData> {};
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<FlightPlanAreaCoordData> {};
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,
};

13
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<ControlGpState, ControlGpAction>(
const { controlGpList } = action.payload;
draft.controlGpList = controlGpList;
})
)
export const controlGpFltPlanReducer = createReducer<ControlGpFlightPlanState, ControlGpAction>(
initiaResponseControlGpData
).handleAction(controlGpFlightPlanAction.success, (state, action) =>
produce(state, draft => {
const list = action.payload;
draft.controlGpFltPlanList = list;
})
);
export const controlGpHisReducer = createReducer<

25
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<LoginData>(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<typeof Actions.controlGpFlightPlanAction.request>
) {
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);
}

6
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,

Loading…
Cancel
Save