From 02828e33e5021a834acf3a690c2effcfa993f903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?scnoh=28=EB=85=B8=EC=8A=B9=EC=B2=A0=29?= Date: Mon, 25 Jul 2022 15:07:28 +0900 Subject: [PATCH] =?UTF-8?q?[=EB=B9=84=ED=96=89=20=EA=B4=80=EC=A0=9C]=20?= =?UTF-8?q?=EA=B7=B8=EB=A3=B9=20=EB=B3=84=20=EB=93=9C=EB=A1=A0=20=ED=91=9C?= =?UTF-8?q?=EC=B6=9C=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/map/naver/NaverMap.js | 28 ++---- src/components/map/naver/dron/DronMarker.js | 88 ++++++++----------- src/components/websocket/WebsocketClient.js | 21 ++--- .../control/gp/actions/controlGpAction.ts | 18 +++- src/modules/control/gp/apis/controlGpApi.ts | 15 +++- .../control/gp/models/controlGpModel.ts | 22 ++++- .../control/gp/reducers/controlGpReducer.ts | 18 +++- src/modules/control/gp/sagas/controlGpSaga.ts | 77 ++++++++++++---- .../control/map/reducers/controlMapReducer.ts | 2 +- src/redux/reducers/rootReducer.ts | 4 +- 10 files changed, 182 insertions(+), 111 deletions(-) diff --git a/src/components/map/naver/NaverMap.js b/src/components/map/naver/NaverMap.js index 3f2aff7..7c95e6b 100644 --- a/src/components/map/naver/NaverMap.js +++ b/src/components/map/naver/NaverMap.js @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { useSelector } from 'react-redux'; +import { useSelector, useDispatch } from 'react-redux'; import dronicon from '../../../assets/control/icon/drone.png'; import { DronMarker } from './dron/DronMarker'; import { DronHistory } from './dron/DronHistory'; @@ -9,34 +9,26 @@ import { NaverMapSearch } from './search/NaverMapSearch'; import { FeatureAirZone } from './feature/FeatureAirZone'; import geoJson from '../geojson/airArea.json'; import SensorZone from "./sensor/SensorZone"; +import { controlGroupAuthAction } from '../../../modules/control/gp'; export const NaverCustomMap = () => { + const dispatch = useDispatch(); const naver = window.naver; - let map; const [isMapLoad, setIsMapLoad] = useState(false); - const [mapObject, setMapObject] = useState(null); + const [mapObject, setMapObject] = useState(null); let arrMarkers = []; // 마커 배열 let arrPolyline = []; // 폴리라인 배열 let features = geoJson.features; useEffect(() => { - NaverMapInit(); - // console.log(map); - - // console.log(features); - - // setIsMapLoad(true); + NaverMapInit(); + dispatch(controlGroupAuthAction.request()); }, []); - useEffect(() => { - // console.log('==============11111==================', mapObject); - }, [mapObject]); - - const removeArrMarkers = arrData => { - arrMarkers = arrData; - }; + useEffect(() => { + }, [mapObject]); const test = aaaa => { console.log(aaaa); @@ -73,9 +65,7 @@ export const NaverCustomMap = () => { <> diff --git a/src/components/map/naver/dron/DronMarker.js b/src/components/map/naver/dron/DronMarker.js index a703ff4..2681e28 100644 --- a/src/components/map/naver/dron/DronMarker.js +++ b/src/components/map/naver/dron/DronMarker.js @@ -1,9 +1,9 @@ -import { useEffect } from 'react'; +import { useEffect, useState } 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 { controlGpDtlAction, controlGpHisAction, controlDbHisAction } from '../../../../modules/control/gp'; import { objectClickAction } from '../../../../modules/control/map/actions/controlMapActions'; export const DronMarker = props => { @@ -21,14 +21,14 @@ export const DronMarker = props => { content: contentString }); + const [arrMarkers, setArrMarkers] = useState([]); + useEffect(() => { markerInit(); }, [controlGpList]); useEffect(() => { - console.log('>>>>>>>>>>>>>>>>', objectId, isClickObject); - - props.arrMarkers.map(clickMarker => { + arrMarkers.map(clickMarker => { if (objectId === clickMarker.id && isClickObject) { // clickMarker.setIcon(DronIconPulple); clickMarker.setIcon({ @@ -36,26 +36,20 @@ export const DronMarker = props => { origin: new naver.maps.Point(0, 0), anchor: new naver.maps.Point(15, 15), }); - } else { - // clickMarker.setIcon(DronIcon); + } else { clickMarker.setIcon({ url: DronIcon, origin: new naver.maps.Point(0, 0), anchor: new naver.maps.Point(15, 15), }); } - }); - // }else{ - - // } + }); }, [objectId, isClickObject]); useEffect(() => { - props.arrMarkers.map(clickMarker => { - if (objectId === clickMarker.id) { - console.log(clickMarker); - props.map.setCenter(clickMarker.getPosition()); - // $('#btn_modal').click(); + arrMarkers.map(clickMarker => { + if (objectId === clickMarker.id) { + props.map.setCenter(clickMarker.getPosition()); props.map.setZoom(13, true); } }); @@ -84,30 +78,18 @@ export const DronMarker = props => { naver.maps.Event.addListener(marker, 'click', function (e) { handlerDronClick(marker); - }); - - props.arrMarkers.push(marker); + }); + + setArrMarkers(m => [...m, 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); - //히스토리 불러오기 + const handlerDronClick = marker => { + // const markerId = marker.id; + const contorlId = marker.controlId; - dispatch(objectClickAction(markerId)); - dispatch(controlGpDtlAction.request(contorlId)); + //히스토리 불러오기 + dispatch(objectClickAction(contorlId)); + dispatch(controlGpDtlAction.request(contorlId)); }; //마커를 삭제 한다. @@ -116,52 +98,54 @@ export const DronMarker = props => { }; //마커에 위치를 이동한다. - const moveMarkers = (marker, position) => { - // console.log(marker); + const moveMarkers = (marker, position) => { marker.setPosition(position); }; //데이터가 없는 마커를 모두 삭제 한다. const allRemoveMarkers = () => { - if (props.arrMarkers && controlGpList) { - props.arrMarkers.map(marker => { + if (arrMarkers && controlGpList) { + 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 + const arrData = arrMarkers.filter( + item => item.id != marker.id ); - props.removeArrMarkers(arrData); + removeArrMarkers(arrData); } }); - } - // } + } }; //마커를 셋팅 한다. const markerInit = () => { if (controlGpList) { - allRemoveMarkers(); + allRemoveMarkers(); controlGpList.map(item => { const position = new naver.maps.LatLng(item.lat, item.lng); - if (props.arrMarkers) { - const isExists = props.arrMarkers.find( + + if (arrMarkers) { + const isExists = arrMarkers.find( ele => ele.id === item.objectId ); - if (isExists) { + if (isExists) { moveMarkers(isExists, position); } else { - // console.log(' ADD >>>', props.arrMarkers); addMarkers(position, item.objectId, item.controlId); } - } else { + } else { addMarkers(position, item.objectId, item.controlId); } }); } }; + const removeArrMarkers = arrData => { + setArrMarkers(arrData); + }; + return null; }; diff --git a/src/components/websocket/WebsocketClient.js b/src/components/websocket/WebsocketClient.js index 8e99bc3..9679ea1 100644 --- a/src/components/websocket/WebsocketClient.js +++ b/src/components/websocket/WebsocketClient.js @@ -1,6 +1,6 @@ import React, { useEffect, useState } from 'react'; import { VscLoading } from 'react-icons/vsc'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { WS_HOST } from '../../configs/constants'; import * as Actions from '../../modules/control/gp/actions/controlGpAction'; @@ -8,17 +8,14 @@ const WebsocketClient = () => { const dispatch = useDispatch(); const reConnectionTime = 5000; //5초 - const [isConnection, setIsConnection] = useState(false); + const [isConnection, setIsConnection] = useState(false); useEffect(() => { connect(); }, []); - const connect = () => { - // let websocket = new WebSocket('ws://localhost:8081/ws'); - // console.log('WS_HOST>>>>>>>>>>', WS_HOST); - let websocket = new WebSocket(WS_HOST); - // let websocket = new WebSocket("ws://localhost:8002/test2"); + const connect = () => { + let websocket = new WebSocket(WS_HOST); websocket.onopen = () => { setIsConnection(true); @@ -26,13 +23,9 @@ const WebsocketClient = () => { }; websocket.onmessage = e => { - const data = e.data; - // console.log(data); - const controlGpList = JSON.parse(data); - - // const controlGpList : ControlGpData[] = JSON.parse(messageObject.message); - // console.log(controlGpList); - + const data = e.data; + const controlGpList = JSON.parse(data); + dispatch(Actions.controlGpAction.request(controlGpList)); }; diff --git a/src/modules/control/gp/actions/controlGpAction.ts b/src/modules/control/gp/actions/controlGpAction.ts index a91c0db..825619c 100644 --- a/src/modules/control/gp/actions/controlGpAction.ts +++ b/src/modules/control/gp/actions/controlGpAction.ts @@ -1,11 +1,13 @@ import { AxiosError } from 'axios'; +import { create } from 'sortablejs'; import { ActionType, createAsyncAction } from 'typesafe-actions'; import { ControlDetailData, ControlGpData, ControlGpDtlState, ControlGpHisState, - ControlGpState + ControlGpState, + ControlGroupAuthState } from '../models/controlGpModel'; const CONTROL_GP_REQUEST = 'control/gp/CONTROL_GP_REQUEST'; @@ -24,6 +26,11 @@ const CONTROL_GP_RTDTL_REQUEST = 'control/gp/CONTROL_GP_RTDTL_REQUEST'; const CONTROL_GP_RTDTL_SUCCESS = 'control/gp/CONTROL_GP_RTDTL_SUCCESS'; const CONTROL_GP_RTDTL_FAILURE = 'control/gp/CONTROL_GP_RTDTL_FAILURE'; +// [관제] 그룹 권한 및 기체 식별번호 조회 +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'; + export const controlGpAction = createAsyncAction( CONTROL_GP_REQUEST, CONTROL_GP_SUCCESS, @@ -48,11 +55,18 @@ export const controlGpRtDtlAction = createAsyncAction( CONTROL_GP_RTDTL_FAILURE )(); +export const controlGroupAuthAction = createAsyncAction( + CONTROL_GROUP_AUTH_REQUEST, + CONTROL_GROUP_AUTH_SUCCESS, + CONTROL_GROUP_AUTH_FAILURE +)(); + const actions = { controlGpAction, controlGpHisAction, controlGpDtlAction, - controlGpRtDtlAction + controlGpRtDtlAction, + controlGroupAuthAction }; export type ControlGpAction = ActionType; diff --git a/src/modules/control/gp/apis/controlGpApi.ts b/src/modules/control/gp/apis/controlGpApi.ts index 020c5f2..218666f 100644 --- a/src/modules/control/gp/apis/controlGpApi.ts +++ b/src/modules/control/gp/apis/controlGpApi.ts @@ -1,5 +1,5 @@ import axios from '../../../utils/customAxiosUtil'; -import { ReponseControlGpHistory } from '../models/controlGpModel'; +import { ReponseControlGpHistory, ControlGroupAuthData, ResponseControlGroupAuth} from '../models/controlGpModel'; export const controlGpApi = { getHistory: async (id: string) => { @@ -8,12 +8,21 @@ export const controlGpApi = { return null; } const { data }: ReponseControlGpHistory = await axios.get( - `api/ctr/cntrl/history/${id}` + `api/ctr/cntrl/history/list/${id}` ); return data; }, getDetail: async (id: string) => { return await axios.get(`api/ctr/cntrl/detail/${id}`); - } + }, + getGroupAuth: async (id: number) => { + if(!id) { + return null; + } + const { data }:ResponseControlGroupAuth = await axios.get( + `api/ctr/cntrl/group?cstmrSno=${id}` + ); + return data; + }, }; diff --git a/src/modules/control/gp/models/controlGpModel.ts b/src/modules/control/gp/models/controlGpModel.ts index 2ba5c42..5870172 100644 --- a/src/modules/control/gp/models/controlGpModel.ts +++ b/src/modules/control/gp/models/controlGpModel.ts @@ -11,6 +11,10 @@ export interface ControlGpDtlState { controlDetail: ControlDetailData | undefined; } +export interface ControlGroupAuthState { + controlGroupAuthInfo : ControlGroupAuthData[] | undefined; +} + export interface ControlGpHistoryData { objectId: String; lat: number; @@ -78,13 +82,29 @@ export interface ControlGpData { heading: number; } +export interface ControlGroupAuthData { + cstmrSno: number, + userId: string, + groupId: string, + groupNm: string, + groupAuthCd: string, + arcrftSno: number, + idntfNum: string, + createUserId: string +} + export interface ReponseControlGpHistory { data: ControlGpHistoryData[]; } +export interface ResponseControlGroupAuth { + data: ControlGroupAuthData[]; +} + export const initiaResponseControlGpData = { controlGpList: undefined, controlGpDetail: undefined, controlGpHistory: undefined, - controlDetail: undefined + controlDetail: undefined, + controlGroupAuthInfo: undefined, }; diff --git a/src/modules/control/gp/reducers/controlGpReducer.ts b/src/modules/control/gp/reducers/controlGpReducer.ts index 0bfa794..32aef1b 100644 --- a/src/modules/control/gp/reducers/controlGpReducer.ts +++ b/src/modules/control/gp/reducers/controlGpReducer.ts @@ -5,13 +5,15 @@ import { controlGpAction, controlGpDtlAction, controlGpHisAction, - controlGpRtDtlAction + controlGpRtDtlAction, + controlGroupAuthAction } from '../actions/controlGpAction'; import { ControlDetailData, ControlGpDtlState, ControlGpHisState, - ControlGpState, + ControlGpState, + ControlGroupAuthState, initiaResponseControlGpData } from '../models/controlGpModel'; @@ -54,3 +56,15 @@ export const controlGpDtlReducer = createReducer< draft.controlDetail = data; }) ); + +export const controlGroupAuthReducer = createReducer< + ControlGroupAuthState, + ControlGpAction +>(initiaResponseControlGpData) + .handleAction(controlGroupAuthAction.success, (state, action) => + produce(state, draft => { + const { controlGroupAuthInfo } = action.payload; + + draft.controlGroupAuthInfo = controlGroupAuthInfo; + }) + ) diff --git a/src/modules/control/gp/sagas/controlGpSaga.ts b/src/modules/control/gp/sagas/controlGpSaga.ts index 2d54802..853592b 100644 --- a/src/modules/control/gp/sagas/controlGpSaga.ts +++ b/src/modules/control/gp/sagas/controlGpSaga.ts @@ -1,41 +1,63 @@ import { call, put, select, takeEvery } from '@redux-saga/core/effects'; import { ActionType } from 'typesafe-actions'; +import { LoginData } from '../../../account/login/models/authModel'; +import { cookieStorage, COOKIE_ACCESS_TOKEN } from '../../../account/login/service/cookie'; import * as Actions from '../actions/controlGpAction'; import { controlGpApi } from '../apis/controlGpApi'; +import decode from 'jwt-decode'; +import { ControlGpData } from '../models/controlGpModel'; function* getControlGpSaga( action: ActionType ) { try { - // console.log("-------------------------------") - const data = action.payload; + const data = action.payload; + const state = yield select(); + const { objectId, isClickObject } = state.controlMapReducer; + const { controlGroupAuthInfo } = state.controlGroupAuthState; + + let gpsData: ControlGpData[] = []; + + if(controlGroupAuthInfo.length > 0) { + controlGroupAuthInfo.forEach((auth) => { + if(auth.groupAuthCd === 'CREATER' || auth.groupAuthCd === 'ADMIN') { + if(gpsData.length > 0) return false; + + gpsData = data.filter(gps => auth.idntfNum === gps.objectId); + } + + if(auth.groupAuthCd === 'USER') { + if(gpsData.length > 0) return false; - // console.log(">>>>>>>>>>>" , data?.length); + gpsData.filter(gps => auth.createUserId && auth.idntfNum === gps.objectId); + } + }); + } yield put( Actions.controlGpAction.success({ - controlGpList: data + controlGpList: gpsData }) - ); - - const state = yield select(); + ); - const { objectId, isClickObject } = state.controlMapReducer; - let detailData; + if (objectId && isClickObject) { + let detailData; + //History 호출 yield put(Actions.controlGpHisAction.request({ id: objectId })); + //상세 정보에서 실시간 데이터 호출 data.map(item => { - if (item.objectId === objectId) { + if (item.controlId === objectId) { detailData = item; } - }); + }); yield put(Actions.controlGpRtDtlAction.request(detailData)); } - } catch (error) { + } catch (error) { yield put(Actions.controlGpAction.failure(error)); } } @@ -44,10 +66,10 @@ function* getControlGpHistorySaga( action: ActionType ) { try { - const { id } = action.payload; + const { id } = action.payload; + + const data = yield call(controlGpApi.getHistory, id); - const data = yield call(controlGpApi.getHistory, id); - // console.log('>>>>>>>1111>>>>> ', rsponse); yield put( Actions.controlGpHisAction.success({ controlGpHistory: data @@ -80,7 +102,7 @@ function* controlDtlSaga( action: ActionType ) { try { - const controlId = action.payload; + const controlId = action.payload; const { data } = yield call(controlGpApi.getDetail, controlId); console.log('data>>>>>>>>>>>>>>>>>>>>>', data); @@ -90,9 +112,32 @@ function* controlDtlSaga( } } +function* controlGroupAuthSaga ( + action: ActionType +) { + const token = cookieStorage.getCookie(COOKIE_ACCESS_TOKEN); + + try { + if(token) { + console.log("group auth token : ", 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 + })); + } + } catch (error) { + yield put(Actions.controlGroupAuthAction.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); } diff --git a/src/modules/control/map/reducers/controlMapReducer.ts b/src/modules/control/map/reducers/controlMapReducer.ts index a454b86..f822aa0 100644 --- a/src/modules/control/map/reducers/controlMapReducer.ts +++ b/src/modules/control/map/reducers/controlMapReducer.ts @@ -21,7 +21,7 @@ const controlReducerReducer = (state = initialState, action) => { case 'MAP_TYPE_CHANGE': return {...state, mapType: action.value}; - case 'OBJECT_CLICK': + case 'OBJECT_CLICK': return {...state, objectId: action.value, isClickObject: true}; case 'OBEJCT_UN_CLICK': diff --git a/src/redux/reducers/rootReducer.ts b/src/redux/reducers/rootReducer.ts index 57d7156..ae07618 100644 --- a/src/redux/reducers/rootReducer.ts +++ b/src/redux/reducers/rootReducer.ts @@ -18,8 +18,9 @@ import { controlGpDtlReducer, controlGpHisReducer, controlGpReducer, + controlGroupAuthReducer, controlGpSaga, - ControlGpState + ControlGpState, } from '../../modules/control/gp'; import controlMapReducer from '../../modules/control/map/reducers/controlMapReducer'; import { mainDahReducer } from '../../modules/main/dash/reducers/mainDashReducer'; @@ -62,6 +63,7 @@ const rootReducer = combineReducers({ controlGpState: controlGpReducer, controlGpHisState: controlGpHisReducer, controlGpDtlState: controlGpDtlReducer, + controlGroupAuthState: controlGroupAuthReducer, menuState: menuReducer, analysisHistoryState: analysisHistoryReducer, analysisSimulatorState: analysisSimulatorReducer,