import m from 'http://devtalk.kospo.co.kr:3000/static/bundle/mithril-2.2.2/mithril.js' import {global} from "http://devtalk.kospo.co.kr:3000/static/js/module/variable.js"; import {talkEvent} from "http://devtalk.kospo.co.kr:3000/static/js/module/talkEvent.js"; import {talkMapping, messageMapping} from "http://devtalk.kospo.co.kr:3000/static/js/module/render.js" import {Tab} from "http://devtalk.kospo.co.kr:3000/static/bundle/bootstrap-5.1.3/js/bootstrap.esm.js"; import Common from "http://devtalk.kospo.co.kr:3000/static/js/utils.js"; import {HubEvent} from "http://devtalk.kospo.co.kr:3000/static/js/module/hubEvent.js"; import {showNotification} from "http://devtalk.kospo.co.kr:3000/static/js/notification.js"; import receiver from "http://devtalk.kospo.co.kr:3000/static/js/module/receiver.js"; // api 관리 let isQuestion = true; const talkInit = () => { work().then(() => { manual().then(() => { question() }) docManual() videoManual() }) } // 현재 사용자 정보 const getUser = async () => { global.user = await global.request({ url: `/api/user/info/client`, method: 'get', withCredentials: true }) } // itsm 만족도 조사 저장 const setITSMSatis = (talkId, reqId, rating, content) => { global.request({ url: `/api/ict/satis`, method: 'post', body: {talk_id : talkId, req_id : reqId, h_point: rating, opinion: content}, withCredentials: true }) } // scm 만족도 조사 저장 const setSCMSatis = (talkId, reqId, rating, content) => { global.request({ url: `/api/scm/satis`, method: 'post', body: {talk_id : talkId, req_id : reqId, h_point: rating, opinion: content}, withCredentials: true }) } // 접속 중인 시스템 정보 const work = async () => { global.work = await global.request({ url: `/api/work`, method: 'get', params: {workId: global.currentWorkId}, withCredentials: true }) global.shadowRoot.querySelector('#intro-work').innerText = global.work.workNm; global.shadowRoot.querySelector('#intro-online').classList.add(global.work.onlineYn ? 'online' : 'offline'); global.shadowRoot.querySelector('#intro-user').innerText = global.user.name; receiver.changeLoginInfo(global.work) } // 접속 중인 시스템의 매뉴얼 const manual = () => { // 현재 업무의 메뉴얼 & 비디오 메뉴얼 호출 return new Promise((resolve, reject) => { global.request({ method: 'get', url: `/api/manual/intro`, params: {workId: global.work.workId}, withCredentials: true }).then((images) => { const manualSlide = global.shadowRoot.querySelector('#manual-play'); const vNode = [] if(images.length === 0) { const parent = Common.findParentElement(manualSlide, 'mt-4') parent.remove() isQuestion = false; } else { images.forEach((i, idx) => { if (i.onm.includes("mp4")) { vNode.push( m('div', {class: `carousel-item ${idx === 0 ? 'active' : ''}`}, [ m('video', { controls: false, class: 'd-block w-100 intro-video', muted: true, preload: 'auto', autoplay: false }, [ m('source', { src: `${global.apiUrl}/api/manual/view/video?id=${i.id}&type=S`, type: "video/mp4" }) ]), m('div', {class: 'video-control'}, [ m('div', {class:'video-fullscreen cus-hide', 'data-ori-src': `${global.apiUrl}/api/manual/view/video?id=${i.id}&type=O`}, [ m('i', {class: 'bi-fullscreen bi-color-white'}) ]) ]) ]) ) } else { vNode.push( m('div', {class: `carousel-item ${idx === 0 ? 'active' : ''}`}, [ m('img', { src: `${global.apiUrl}/api/manual/view/image?workId=${global.work.workId}&vnm=${i.vnm}&sabun=${global.user.sabun}`, class: 'd-block w-100', alt: 'img1' }) ]) ) } }) m.render(manualSlide.querySelector('.carousel-inner'), vNode); /* 숏츠 비디오 이벤트 정의 */ global.shadowRoot.querySelectorAll('.video-control').forEach((target) => { target.addEventListener('mouseenter', () => { target.querySelector('.video-fullscreen').classList.remove('cus-hide') target.querySelector('.video-fullscreen').classList.add('cus-show') }) target.addEventListener('mouseleave', () => { target.querySelector('.video-fullscreen').classList.remove('cus-show') target.querySelector('.video-fullscreen').classList.add('cus-hide') }) }) global.shadowRoot.querySelectorAll('.video-fullscreen').forEach((target) => { target.addEventListener('click', () => { const oriSrc = target.dataset.oriSrc console.log(oriSrc) const fullvideo = global.shadowRoot.querySelector('#fullscreen-container'); fullvideo.classList.remove('cus-hide') fullvideo.classList.add('cus-show'); const video = m('video', {preload: 'none', controls: 'controls', id: 'fullvideo', style: 'width:100%; height:100%;'}, [ m('source', {src: oriSrc, type: 'video/mp4'}) ]) m.render(fullvideo, video); const playVideo = global.shadowRoot.querySelector('#fullvideo'); playVideo.requestFullscreen(); playVideo.play(); window.onresize = () => { if(window.matchMedia('(display-mode: fullscreen)').matches || window.document.fullscreenElement) { console.log(true) } else { closeFullscreen(); console.log(false); } } }) }) } resolve(); }) }) } const closeFullscreen = () => { const playVideo = global.shadowRoot.querySelector('#fullvideo'); if(playVideo) { const fullvideo = global.shadowRoot.querySelector('#fullscreen-container'); m.render(fullvideo, []); fullvideo.classList.remove('cus-show') fullvideo.classList.add('cus-hide') } } // 접속 중인 시스템의 자주 하는 질문 const question = () => { const questionCnt = isQuestion ? 5 : 6; /*현재 업무의 자주하는 질문 설정 */ global.request({ method: 'get', url: `/api/question/${global.work.workId}`, withCredentials: true }).then((question) => { const questionContent = global.shadowRoot.querySelector('#question'); const question_page = Math.ceil(question.length / questionCnt) let question_div = null let paging = 0; question.forEach((a, idx) => { if(idx % questionCnt === 0) { paging++; question_div = document.createElement('div') question_div.setAttribute("id", `question-pg-${paging}`) question_div.classList.add('question-pg-container') if(paging !== 1) { question_div.classList.add('cus-hide') } else { question_div.classList.add('cus-show') } } const questionP = document.createElement("p"); questionP.classList.add('cursor-pointer', 'question') const questionText = document.createTextNode(`${a.content}`) questionP.appendChild(questionText) question_div.append(questionP); questionP.addEventListener('click', () => { const talkId = talkEvent.generateUUID(); // 키보드 숨김 해제 global.element.chatEditorArea.classList.remove('cus-hide'); // 채팅 구독 메시지 보내기 localStorage.setItem(global.tabId, talkId) localStorage.setItem('workId', global.work.workId) localStorage.setItem('workNm', global.work.workNm) // 발 생성자 주입 global.chatCreator = global.tabId; talkEvent.join(global.talkParams({ type: 'JOIN', message: a.content, talkId: talkId, workId: global.work.workId, introOwner: 'mine' })) talkEvent.messageShow() }) if(idx % questionCnt === questionCnt-1 || idx === question.length-1) { questionContent.append(question_div) } }) const pagination = document.createElement('div'); pagination.classList.add('fx', 'fx-gap') pagination.setAttribute("id", 'question_pg') for(var i=0; i< question_page; i++) { const pagination_btn = document.createElement('div') if(i === 0) { pagination_btn.classList.add('btn', 'active') pagination_btn.dataset.pg = i } else { pagination_btn.classList.add('btn') pagination_btn.dataset.pg = i } pagination.append(pagination_btn) } questionContent.append(pagination) let current_page = 0 function switchToNext(evt) { const {target} =evt; if(!target.classList.contains('btn')) { return; } const clickedBtn = target; if(clickedBtn.classList.contains('active')) { return; } const activeBtn = pagination.getElementsByClassName('active')[0] activeBtn?.classList.remove("active") clickedBtn.classList.add('active') global.shadowRoot.querySelectorAll(".question-pg-container").forEach((el) => { el.classList.add('cus-hide') el.classList.remove('cus-show') }); const active = global.shadowRoot.querySelector(`#question-pg-${Number(clickedBtn.dataset.pg) + 1}`) active.classList.remove('cus-hide') active.classList.add('cus-show') current_page = Number(clickedBtn.dataset.pg) + 1; } pagination.addEventListener('click', switchToNext) /*자주찾는 질문이 2페이지 이상일때만 실행*/ if(question_page > 1) { setInterval(autoNext, 10000) function autoNext() { let movePage = Number(current_page) + 1 if(question_page < movePage) movePage = 1; global.shadowRoot.querySelectorAll(".question-pg-container").forEach((el) => { el.classList.add('cus-hide') el.classList.remove('cus-show') }); const active = global.shadowRoot.querySelector(`#question-pg-${movePage}`); active.classList.remove('cus-hide') active.classList.add('cus-show') current_page = movePage; } } if(!isQuestion) { const question = global.shadowRoot.querySelector('#question'); const questionPg = global.shadowRoot.querySelector('.question-pg-container'); question.style.minHeight = '286px'; questionPg.style.minHeight = '230px'; } }) } // 접속 중인 시스템의 문서 매뉴얼 const docManual = () => { /*본인 메뉴얼*/ global.request({ method: 'get', url: `/api/manual`, params: {workId: global.work.workId, type: '0000'}, withCredentials: true }).then((manuals) => { const manualVNode = []; manuals.map((ma) => { manualVNode.push( m('div', {class: "d-flex justify-content-start manual-content"}, [ m('div', {class: "p-2 text-ellipsis", style: "width:60%;cursor: help;", title:ma.onm}, `${ma.onm}`), m('div', {class: "p-2", style: "width:20%;"}, `${ma.version}`), m('a', { href: `${global.apiUrl}/api/manual/download/doc?workId=${ma.workId}&vnm=${ma.vnm}`, target: '_download_', rel: 'noopener', style: 'padding-top:6px;' }, [ m('i', { class: "bi bi-download text-black", style: "padding-right:10px; font-size:1.0rem; cursor:pointer;" }) ]) ]) ) }) const manualBody = global.shadowRoot.querySelector('#manual-doc-body'); const content = manualBody.querySelector('.simplebar-content'); if(manualVNode.length > 0) m.render(content, manualVNode) }) } // 접속 중인 시스템의 동영상 매뉴얼 const videoManual = () => { global.request({ method: 'get', url: `/api/manual/video`, params: {workId: global.work.workId}, withCredentials: true }).then((manuals) => { const manualVNode = []; manuals.map((ma) => { manualVNode.push( m('div', {class: "d-flex justify-content-evenly manual-content"}, [ m('div', {class: "p-2 text-ellipsis", style: "width:70%;"}, `${ma.onm}`), // m('div', {class: "p-2", style: "font-size:13px; width:20%;"}, `${ma.version}`), m('button', { class: 'btn btn-sm btn-play manual-play-btn p-0', 'data-id': ma.id, }, '재생') ]) ) }) const manualBody = global.shadowRoot.querySelector('#manual-video-body'); const content = manualBody.querySelector('.simplebar-content'); if(manualVNode.length > 0) m.render(content, manualVNode) // videoManualPlayEvent(); }) console.log('work init end') } // 생성된 톡방 목록 추가 const setChatList = function (chat) { console.log('setChatList before', global.talkData, chat) global.talkData.unshift(chat) console.log('setChatList after', global.talkData) // 채팅 목록 생성 talkMapping(global.talkData); // 채팅 목록 구독 if (Common.isMaster()) { chatConnect([chat]); } // 채팅 부트스트랩 이벤트 수동 연결 chatBootstrapEvent(); talkEvent.badgeChange() } // 현사용자의 톡방 목록 const getTalkList = function (reset) { return new Promise((resolve, reject) => { global.request({ url: `/api/talk`, method: 'get', withCredentials: true }).then((lists) => { if (reset) { global.talkData = lists; getTalkListEvent() resolve(global.talkData.length === 0 ? true : false) } else { lists.forEach(list => { if (!global.talkData.map(talk => talk.talkId).join(',').includes(list.talkId)) { global.talkData.push(list) } }) getTalkListEvent() resolve(global.talkData.length === 0 ? true : false) } }).catch(function (error) { console.log(error) reject() }) }) } // 톡방 이벤트 정의 소켓 연결 및 동적으로 생성된 DOM 이벤트 재설정 const getTalkListEvent = () => { // 채팅 목록 생성 talkMapping(global.talkData); // 마스터만 채팅 목록 구독 if (Common.isMaster()) { chatConnect(global.talkData); } // 채팅 부트스트랩 이벤트 수동 연결 chatBootstrapEvent(); talkEvent.badgeChange() } const getApInfo = () => { return new Promise((resolve, reject) => { global.request({ url: `/api/getApInfo`, method: 'get', withCredentials: true }).then(data => { console.log(data) resolve(data); }).catch(() => { reject(); }) }) } // 소켓 구독 const chatConnect = function (chats) { for (const ch of chats) { if (!ch.closeYn) { if (!Object.keys(global.subscribeList).includes(ch.talkId)) { global.subscribeList[ch.talkId] = talkEvent.subscribe(ch.talkId) } } } } // 톡방 이벤트 정의 const chatBootstrapEvent = () => { /*bootstrap 수동 이벤트 설정*/ global.shadowRoot.querySelectorAll('div[data-bs-toggle="tab"]').forEach((el) => { if (!el.dataset.tabListener) { const tabTrigger = new Tab(el); el.addEventListener('click', function (e) { e.preventDefault(); tabTrigger.show(); }) } el.dataset.tabListener = true; }) } // 톡방 클릭시 해당 메시지 const getMessage = function (messageParams) { global.request({ url: `/api/message/line`, method: 'get', params: messageParams, withCredentials: true }).then((dto) => { const cacheTalk = global.talkData.filter((talk) => talk.talkId === messageParams.talkId)[0]; cacheTalk.messageParams = messageParams; cacheTalk.talkMessages = dto; }); } /* * 비동기 톡방 메시지 호출 * parameter * reset : 초기 설정 일시 true 재연결시 false * */ const getMessageAll = async function (reset) { const dto = await global.request({ url: `/api/message/all`, method: 'get', withCredentials: true }); if (reset) { global.talkData.forEach((talk) => { const cacheTalk = dto.filter((talkData) => talkData.talkId === talk.talkId)[0]; talk.talkMessages = cacheTalk.talkMessages; }) } else { let queue = [] global.talkData.forEach((talk) => { try { const lastMsg = talk.talkMessages.talks[talk.talkMessages.talks.length - 1] const cacheTalk = dto.filter((talkData) => talkData.talkId === talk.talkId)[0]; const newMsg = cacheTalk.talkMessages.talks.filter((ct) => { return Common.dateDifference(new Date(ct.insDate), new Date(lastMsg.insDate)) }) if (newMsg.length > 0) { newMsg.forEach((msg) => { msg.workNm = talk.work.workNm }) talk.lastMessage = newMsg[newMsg.length - 1].message; talk.lastMessageDate = newMsg[newMsg.length - 1].insDate; // 톡방 접속중인 경우 메시지 맵핑 if (localStorage.getItem(global.tabId) === talk.talkId) { messageMapping(talk.talkId, {talks: newMsg}, 'after', false) // 브라우저 상태가 hidden 인 경우 알림에 추가 if (!document.hasFocus()) queue = [...queue, ...newMsg] // 그외 메시지 재정의 } else { talk.talkMessages.talks = [...newMsg, ...talk.talkMessages.talks] talk.unReadCnt = talk.unReadCnt + newMsg.length; queue = [...queue, ...newMsg] } } } catch (e) { console.log(`talk.talkId is null messages`) } }) console.log(queue) // 추가된 큐가 존재 할시 톡방 저체 갱신 // 큐에 정의된 메시지를 알림 if (queue.length > 0) { talkMapping(global.talkData); talkEvent.badgeChange(); queue.forEach((que) => { showNotification(que) }) } } } const getMoreMessageAll = async function () { let insDate = '1999-01-01'; global.talkData.forEach(talk => { if(insDate < talk.lastMessageDate) { insDate = talk.lastMessageDate } }) const dtos = await global.request({ url: `/api/message/more/all`, method: 'get', params: {'insDate': insDate}, withCredentials: true }); let queue = [] dtos.forEach((dto) => { try { const cacheTalk = global.talkData.filter((talk) => talk.talkId === dto.talkId)[0]; const newMsg = dto.talkMessages.talks; console.log(newMsg) if (newMsg.length > 0) { newMsg.forEach((msg) => { msg.workNm = cacheTalk.work.workNm }) cacheTalk.lastMessage = newMsg[newMsg.length - 1].message; cacheTalk.lastMessageDate = newMsg[newMsg.length - 1].insDate; // 톡방 접속중인 경우 메시지 맵핑 if (localStorage.getItem(global.tabId) === cacheTalk.talkId) { messageMapping(cacheTalk.talkId, {talks: newMsg}, 'after', false) // 브라우저 상태가 hidden 인 경우 알림에 추가 if (!document.hasFocus()) queue = [...queue, ...newMsg] // 그외 메시지 재정의 } else { cacheTalk.talkMessages.talks = [...newMsg, ...cacheTalk.talkMessages.talks] cacheTalk.unReadCnt = cacheTalk.unReadCnt + newMsg.length; queue = [...queue, ...newMsg] } } } catch (e) { console.log(`talk.talkId is null messages`) } }) // 추가된 큐가 존재 할시 톡방 저체 갱신 // 큐에 정의된 메시지를 알림 if (queue.length > 0) { talkMapping(global.talkData); talkEvent.badgeChange(); queue.forEach((que) => { showNotification(que) }) } } // 톡방 내용 가져오기 const getMoreMessageLine = (talkId) => { const cacheTalk = global.talkData.filter((talk) => talk.talkId === talkId)[0]; cacheTalk.messageParams['insDate'] = cacheTalk.talkMessages.talks[cacheTalk.talkMessages.talks.length - 1].insDate; return new Promise((resolve, reject) => { global.request({ url: `/api/message/line`, method: 'get', params: cacheTalk.messageParams, withCredentials: true }).then((dto) => { if (dto.talks.length > 0) { messageMapping(talkId, dto, 'before', false); talkEvent.messageScrollOriginalPositionMove(); let result = ''; if (cacheTalk.talkMessages.talks.length >= dto.total) { result = 'last'; } else { result = 'success'; } HubEvent.send(global.talkParams({ type: 'MORE_MESSAGE_LINE', talkId: talkId, tabId: global.tabId, result: result, talkMessages: dto })) resolve(result) } else { resolve('last'); } }).catch(function (error) { reject(error) }) }) } // 톡방내 메시지 검색 const getMessageSearch = (params) => { global.request({ url: `/api/message/search`, method: 'get', params: {talkId: params.talkId, search: params.search}, withCredentials: true }).then((lists) => { params.callback(lists) }) } // 메시지 통합 검색 const getAllContentSearch = (params) => { global.request({ url: `/api/message/search/all`, method: 'get', params: {search: params.search}, withCredentials: true, }).then((lists) => { params.callback(lists) }) } //매뉴얼 조회 const getManual = (params) => { const sendParam = {type: params.type} if(params.search !== '') sendParam['search'] = params.search if(params.workId !== '') sendParam['workId'] = params.workId global.request({ url: `/api/manual`, method: 'get', params: sendParam, withCredentials: true }).then((manuals) => { params.callback(manuals) }) } //매뉴얼 조회 const getVideoManual = (params) => { const sendParam = {type: params.type} if(params.search !== '') sendParam['search'] = params.search if(params.workId !== '') sendParam['workId'] = params.workId global.request({ url: `/api/manual/video`, method: 'get', params: sendParam, withCredentials: true }).then((manuals) => { params.callback(manuals) }) } // 톡방 삭제 (실제 삭제 여부만 갱신) const deleteTalk = (params) => { global.request({ url: `/api/talk/delete/${params.talkId}`, method: 'put', withCredentials: true }).then((data) => { params.callback(data) }) } // 톡방 읽음 표시 const setChatRead = (talkId) => { console.log('read', talkId) return new Promise((resolve, reject) => { global.request({ url: `/api/message/read`, method: 'post', body: {talkId: talkId}, withCredentials: true }).then((result) => { resolve(result); }).catch((err) => { reject(err); }) }) } // 톡방 보관 const setTalkMark = (obj) => { global.request({ url: `/api/talk/mark/${obj.talkId}`, method: 'put', withCredentials: true }).then(() => { obj.callback() }) } export { talkInit, getUser, getApInfo, getTalkList, getTalkListEvent, setChatList, getMessage, getMoreMessageLine, getMessageSearch, getAllContentSearch, getManual, getVideoManual, setChatRead, setTalkMark, setITSMSatis, setSCMSatis, deleteTalk, getMessageAll, getMoreMessageAll }