박상현
10 months ago
33 changed files with 912 additions and 914 deletions
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 33 KiB |
@ -0,0 +1,73 @@
|
||||
import { useSelector } from 'react-redux'; |
||||
import geoJson from '../../map/geojson/airArea.json'; |
||||
import flatGimpo from '../../map/geojson/flatGimpoAirportAirArea.json'; |
||||
|
||||
// 공역 생성
|
||||
export const handlerCreateAirSpace = ( |
||||
map, |
||||
mapControl, |
||||
useGeoJson = { |
||||
...geoJson, |
||||
...flatGimpo, |
||||
features: [...geoJson.features, ...flatGimpo.features] |
||||
} |
||||
) => { |
||||
if (map.getLayer('maine')) { |
||||
map.removeLayer('maine'); |
||||
map.removeSource('maine'); |
||||
} |
||||
let arrGeoJson = []; |
||||
useGeoJson.features.map(item => { |
||||
if (item.properties.type === '0001' && mapControl.area0001) { |
||||
arrGeoJson.push({ |
||||
...item, |
||||
properties: { ...item.properties, color: '#FF3648' } |
||||
}); |
||||
} else if (item.properties.type === '0002' && mapControl.area0002) { |
||||
arrGeoJson.push({ |
||||
...item, |
||||
properties: { ...item.properties, color: '#FFA1AA' } |
||||
}); |
||||
} else if (item.properties.type === '0003' && mapControl.area0003) { |
||||
arrGeoJson.push({ |
||||
...item, |
||||
properties: { ...item.properties, color: '#FFA800' } |
||||
}); |
||||
} else if (item.properties.type === '0004' && mapControl.area0004) { |
||||
arrGeoJson.push({ |
||||
...item, |
||||
properties: { ...item.properties, color: '#A16B00' } |
||||
}); |
||||
} else if (item.properties.type === '0005' && mapControl.area0005) { |
||||
arrGeoJson.push({ |
||||
...item, |
||||
properties: { ...item.properties, color: '#AB40FF' } |
||||
}); |
||||
} else if (item.properties.type === '0006' && mapControl.area0006) { |
||||
arrGeoJson.push({ |
||||
...item, |
||||
properties: { ...item.properties, color: '#009cad' } |
||||
}); |
||||
} |
||||
}); |
||||
useGeoJson.features = arrGeoJson.filter(i => i.geometry.type === 'Polygon'); |
||||
|
||||
// 공역 생성 start
|
||||
map.addSource('maine', { |
||||
type: 'geojson', |
||||
data: { |
||||
...useGeoJson |
||||
} |
||||
}); |
||||
map.addLayer({ |
||||
id: 'maine', |
||||
type: 'fill', |
||||
source: 'maine', |
||||
layout: {}, |
||||
paint: { |
||||
'fill-color': ['get', 'color'], |
||||
// 'fill-extrusion-height': 3000,
|
||||
'fill-opacity': 0.5 |
||||
} |
||||
}); |
||||
}; |
@ -1,56 +1,56 @@
|
||||
import { useState, useEffect } from 'react'; |
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Card } from 'reactstrap' |
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; |
||||
|
||||
const ControlAlarmDetail = ({ historyModal, setHistoryModal, controlGpWarnLog }) => { |
||||
return ( |
||||
<Modal |
||||
isOpen={historyModal} |
||||
toggle={() => setHistoryModal(!historyModal)} |
||||
className='modal-dialog-centered historyModal' |
||||
> |
||||
<ModalHeader toggle={() => setHistoryModal(!historyModal)}> |
||||
<div className='drone-ti'> |
||||
<span className="drone-name">{controlGpWarnLog?.idntfNum}</span> |
||||
<span>알림내역</span> |
||||
</div> |
||||
</ModalHeader> |
||||
const ControlAlarmDetail = ({ |
||||
historyModal, |
||||
setHistoryModal, |
||||
controlGpWarnLog |
||||
}) => { |
||||
return ( |
||||
<Modal |
||||
isOpen={historyModal} |
||||
toggle={() => setHistoryModal(!historyModal)} |
||||
className='modal-dialog-centered historyModal' |
||||
> |
||||
<ModalHeader toggle={() => setHistoryModal(!historyModal)}> |
||||
<div className='drone-ti'> |
||||
<span className='drone-name'>{controlGpWarnLog?.idntfNum}</span> |
||||
<span>알림내역</span> |
||||
</div> |
||||
</ModalHeader> |
||||
|
||||
<ModalBody> |
||||
<table className='table pal-table'> |
||||
<tr> |
||||
<th>번호</th> |
||||
<th>식별번호</th> |
||||
<th>날짜</th> |
||||
<th>내용</th> |
||||
</tr> |
||||
{controlGpWarnLog ? |
||||
controlGpWarnLog.map((p, i) => { |
||||
return ( |
||||
<tr key={i}> |
||||
<th>{i + 1}</th> |
||||
<th>{p.idntfNum}</th> |
||||
<th>{p.createDt}</th> |
||||
<th>{p.warnType}</th> |
||||
</tr> |
||||
) |
||||
}) |
||||
: |
||||
<tr> |
||||
<th colSpan={3}>데이터가 없습니다.</th> |
||||
</tr> |
||||
} |
||||
</table> |
||||
</ModalBody> |
||||
<ModalFooter> |
||||
<Button |
||||
color='info' |
||||
onClick={() => setHistoryModal(!historyModal)} |
||||
> |
||||
확인 |
||||
</Button> |
||||
</ModalFooter> |
||||
</Modal> |
||||
) |
||||
} |
||||
<ModalBody> |
||||
<table className='table pal-table'> |
||||
<tr> |
||||
<th>번호</th> |
||||
<th>식별번호</th> |
||||
<th>날짜</th> |
||||
<th>내용</th> |
||||
</tr> |
||||
{controlGpWarnLog ? ( |
||||
controlGpWarnLog.map((p, i) => { |
||||
return ( |
||||
<tr key={i}> |
||||
<th>{i + 1}</th> |
||||
<th>{p.idntfNum}</th> |
||||
<th>{p.createDt}</th> |
||||
<th>{p.warnType}</th> |
||||
</tr> |
||||
); |
||||
}) |
||||
) : ( |
||||
<tr> |
||||
<th colSpan={3}>데이터가 없습니다.</th> |
||||
</tr> |
||||
)} |
||||
</table> |
||||
</ModalBody> |
||||
<ModalFooter> |
||||
<Button color='info' onClick={() => setHistoryModal(!historyModal)}> |
||||
확인 |
||||
</Button> |
||||
</ModalFooter> |
||||
</Modal> |
||||
); |
||||
}; |
||||
|
||||
export default ControlAlarmDetail; |
@ -1,175 +1,151 @@
|
||||
import { useEffect, useState } from 'react'; |
||||
import { X } from 'react-feather'; |
||||
import { useDispatch, useSelector } from 'react-redux'; |
||||
import { controlGpArcrftWarnAction, controlGpLogAction } from '../../../modules/control/gp/actions/controlGpAction'; |
||||
import { controlGpLogAction } from '../../../modules/control/gp/actions/controlGpAction'; |
||||
import ControlAlarmDetail from './ControlAlarmDetail'; |
||||
import { Badge } from 'reactstrap'; |
||||
|
||||
const ControlAlarmList = props => { |
||||
const dispatch = useDispatch(); |
||||
|
||||
const [historyModal, setHistoryModal] = useState(false); |
||||
|
||||
const { controlGpList } = useSelector(state => state.controlGpState); |
||||
const { controlGpArcrftWarnList } = useSelector(state => state.controlGpLogState);
|
||||
const { controlGpWarnLog } = useSelector(state => state.controlGpLogState); |
||||
const { objectId, isClickObject } = useSelector(state => state.controlMapReducer); |
||||
|
||||
|
||||
const [total, setTotal] = useState({ |
||||
totalDroneCnt: 0, |
||||
totalWarnCnt: 0, |
||||
warnList: [] |
||||
});
|
||||
|
||||
const handleWarnDetail = (cntrlId) => { |
||||
setHistoryModal(prev => !prev); |
||||
|
||||
dispatch(controlGpLogAction.request({id : cntrlId})); |
||||
const dispatch = useDispatch(); |
||||
// 비정상상황 상세 히스토리 모달
|
||||
const [historyModal, setHistoryModal] = useState(false); |
||||
|
||||
// 비정상상황 상세 히스토리
|
||||
const { controlGpWarnLog } = useSelector(state => state.controlGpLogState); |
||||
|
||||
// 비정상상황 기체 목록
|
||||
const { controlGpArcrftWarnList } = useSelector( |
||||
state => state.controlGpLogState |
||||
); |
||||
|
||||
// 클릭한 기체 Id, 비행중인 기체 클릭 여부
|
||||
const { objectId, isClickObject } = useSelector( |
||||
state => state.controlMapReducer |
||||
); |
||||
|
||||
// 전체 드론, 비정상 드론 개수
|
||||
const [total, setTotal] = useState({ |
||||
totalDroneCnt: 0, |
||||
totalWarnCnt: 0, |
||||
warnList: [] |
||||
}); |
||||
|
||||
// 비정상상황 상세 히스토리 모달 표출
|
||||
const handleWarnDetail = cntrlId => { |
||||
setHistoryModal(prev => !prev); |
||||
dispatch(controlGpLogAction.request({ id: cntrlId })); |
||||
}; |
||||
|
||||
// 비행중인 기체 클릭 시 비정상상황 사이드메뉴 닫힘
|
||||
useEffect(() => { |
||||
if (isClickObject) { |
||||
props.setOpenAlarmList(false); |
||||
} |
||||
|
||||
useEffect(() => { |
||||
if(isClickObject) {
|
||||
props.setOpenAlarmList(false); |
||||
} |
||||
|
||||
}, [objectId, isClickObject]) |
||||
|
||||
useEffect(() => { |
||||
if(controlGpArcrftWarnList) { |
||||
let totalWarnCnt = 0; |
||||
|
||||
if(controlGpArcrftWarnList.length > 0) { |
||||
controlGpArcrftWarnList.forEach(warn => { |
||||
totalWarnCnt += warn.warnCount; |
||||
}); |
||||
}
|
||||
|
||||
setTotal(total => { |
||||
return { |
||||
totalDroneCnt : controlGpArcrftWarnList.length, |
||||
totalWarnCnt : totalWarnCnt, |
||||
warnList : controlGpArcrftWarnList |
||||
}
|
||||
}) |
||||
} |
||||
|
||||
}, [controlGpArcrftWarnList]); |
||||
|
||||
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'>드론 현황</div> |
||||
<div className='list-right-txt'>
|
||||
<Badge color='light-primary'> |
||||
{total? total.totalDroneCnt: 0}대 비행 중 |
||||
</Badge> |
||||
</div> |
||||
</div> |
||||
</dt> |
||||
<dt> |
||||
<div className='list-ti'>
|
||||
<div className='list-left-txt'>비정상 알림 전체</div> |
||||
<div className='list-right-txt'> |
||||
<Badge color='light-primary'> |
||||
{total? total.totalWarnCnt : 0}건 |
||||
</Badge> |
||||
</div> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
</div> |
||||
</div> |
||||
<div className='layer-content'> |
||||
<div className='layer-ti'> |
||||
<h4>알림 목록</h4> |
||||
</div> |
||||
{total?.warnList.map((warn, i) => { |
||||
const warnContent = warn.warnType === 'PLAN' ? '비행 경로 이탈' : '비정상 상황 발생' |
||||
|
||||
return ( |
||||
<div className='layer-content-list' key={i} onClick={() => handleWarnDetail(warn.cntrlId)}> |
||||
<dl className='notice-list'> |
||||
<dt> |
||||
<div className='list-ti'> |
||||
<div className='list-left-txt'>{warn.idntfNum}</div> |
||||
<div className='list-right-txt'>{warn.occurDt ? warn.occurDt : '-'}</div> |
||||
</div> |
||||
<div className='list-ti'> |
||||
<div className='list-left-txt'>{warnContent ? warnContent : '-'}</div> |
||||
<div className='list-right-txt'>{warn.warnCount ? warn.warnCount : '-'}건</div> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
</div> |
||||
) |
||||
})} |
||||
{/* <div className='layer-content-list'> |
||||
<dl className='notice-list'> |
||||
<dt> |
||||
<div className='list-ti'> |
||||
<div className='list-left-txt'>PAV-001</div> |
||||
<div className='list-right-txt'>2022. 09. 02 10:00:30</div> |
||||
</div> |
||||
<div className='list-ti'> |
||||
<div className='list-left-txt'>비행 경로 이탈</div> |
||||
<div className='list-right-txt'>22건</div> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
}, [objectId, isClickObject]); |
||||
|
||||
// 비정상상황 기체 개수 계산
|
||||
useEffect(() => { |
||||
if (controlGpArcrftWarnList) { |
||||
let totalWarnCnt = 0; |
||||
|
||||
if (controlGpArcrftWarnList.length > 0) { |
||||
controlGpArcrftWarnList.forEach(warn => { |
||||
totalWarnCnt += warn.warnCount; |
||||
}); |
||||
} |
||||
|
||||
setTotal(total => { |
||||
return { |
||||
totalDroneCnt: controlGpArcrftWarnList.length, |
||||
totalWarnCnt: totalWarnCnt, |
||||
warnList: controlGpArcrftWarnList |
||||
}; |
||||
}); |
||||
} |
||||
}, [controlGpArcrftWarnList]); |
||||
|
||||
return ( |
||||
<div className='left-layer'> |
||||
<div className='layer-content'> |
||||
<div className='layer-ti'> |
||||
<h4>실시간 비정상 알림 정보</h4> |
||||
<button |
||||
className='btn-icon' |
||||
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'>드론 현황</div> |
||||
<div className='list-right-txt'> |
||||
<Badge color='light-primary'> |
||||
{total ? total.totalDroneCnt : 0}대 비행 중 |
||||
</Badge> |
||||
</div> |
||||
<div className='layer-content-list'> |
||||
<dl className='notice-list'> |
||||
<dt> |
||||
<div className='list-ti'> |
||||
<div className='list-left-txt'>PAV-002</div> |
||||
<div className='list-right-txt'>2022. 09. 02 11:23:52</div> |
||||
</div> |
||||
<div className='list-ti'> |
||||
<div className='list-left-txt'>비행 경로 이탈</div> |
||||
<div className='list-right-txt'>10건</div> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
</div> |
||||
</dt> |
||||
<dt> |
||||
<div className='list-ti'> |
||||
<div className='list-left-txt'>비정상 알림 전체</div> |
||||
<div className='list-right-txt'> |
||||
<Badge color='light-primary'> |
||||
{total ? total.totalWarnCnt : 0}건 |
||||
</Badge> |
||||
</div> |
||||
<div className='layer-content-list'> |
||||
<dl className='notice-list'> |
||||
<dt> |
||||
<div className='list-ti'> |
||||
<div className='list-left-txt'>PAV-003</div> |
||||
<div className='list-right-txt'>-</div> |
||||
</div> |
||||
<div className='list-ti'> |
||||
<div className='list-left-txt'>-</div> |
||||
<div className='list-right-txt'>0건</div> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
</div> */} |
||||
</div> |
||||
|
||||
<ControlAlarmDetail
|
||||
historyModal={historyModal} |
||||
setHistoryModal={setHistoryModal} |
||||
controlGpWarnLog={controlGpWarnLog} |
||||
/> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
</div> |
||||
</div> |
||||
<div className='layer-content'> |
||||
<div className='layer-ti'> |
||||
<h4>알림 목록</h4> |
||||
</div> |
||||
); |
||||
{total?.warnList.map((warn, i) => { |
||||
const warnContent = |
||||
warn.warnType === 'PLAN' ? '비행 경로 이탈' : '비정상 상황 발생'; |
||||
|
||||
return ( |
||||
<div |
||||
className='layer-content-list' |
||||
key={i} |
||||
onClick={() => handleWarnDetail(warn.cntrlId)} |
||||
> |
||||
<dl className='notice-list'> |
||||
<dt> |
||||
<div className='list-ti'> |
||||
<div className='list-left-txt'>{warn.idntfNum}</div> |
||||
<div className='list-right-txt'> |
||||
{warn.occurDt ? warn.occurDt : '-'} |
||||
</div> |
||||
</div> |
||||
<div className='list-ti'> |
||||
<div className='list-left-txt'> |
||||
{warnContent ? warnContent : '-'} |
||||
</div> |
||||
<div className='list-right-txt'> |
||||
{warn.warnCount ? warn.warnCount : '-'}건 |
||||
</div> |
||||
</div> |
||||
</dt> |
||||
</dl> |
||||
</div> |
||||
); |
||||
})} |
||||
</div> |
||||
|
||||
<ControlAlarmDetail |
||||
historyModal={historyModal} |
||||
setHistoryModal={setHistoryModal} |
||||
controlGpWarnLog={controlGpWarnLog} |
||||
/> |
||||
</div> |
||||
); |
||||
}; |
||||
|
||||
export default ControlAlarmList; |
||||
|
@ -1,45 +0,0 @@
|
||||
import { Bell, ChevronDown, ChevronUp } from "react-feather"; |
||||
import { ReactComponent as DroneMenuIcon } from '../../../assets/images/drone_menu_icon.svg'; |
||||
|
||||
const ControlAlarmNotice = () => { |
||||
{} |
||||
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; |
Loading…
Reference in new issue