@@ -10,8 +10,43 @@ import { Server } from 'socket.io';
1010import { YSocketIO } from 'y-socket.io/dist/server' ;
1111import * as Y from 'yjs' ;
1212import { NodeService } from '../node/node.service' ;
13+ import { PageService } from '../page/page.service' ;
1314import { NodeCacheService } from '../node-cache/node-cache.service' ;
15+ import { yXmlFragmentToProsemirrorJSON } from 'y-prosemirror' ;
16+ import { EdgeService } from '../edge/edge.service' ;
17+ // yMap에 저장되는 Node 형태
18+ type YMapNode = {
19+ id : string ; // 노드 아이디
20+ type : string ; // 노드의 유형
21+ data : {
22+ title : string ; // 제목
23+ id : number ; // 페이지 아이디
24+ } ;
25+ position : {
26+ x : number ; // X 좌표
27+ y : number ; // Y 좌표
28+ } ;
29+ selected : boolean ;
30+ } ;
1431
32+ // yMap에 저장되는 edge 형태
33+ type YMapEdge = {
34+ id : string ; // Edge 아이디
35+ source : string ; // 출발 노드 아이디
36+ target : string ; // 도착 노드 아이디
37+ sourceHandle : string ;
38+ targetHandle : string ;
39+ } ;
40+
41+ // Y.Doc에는 name 컬럼이 없어서 생성했습니다.
42+ class CustomDoc extends Y . Doc {
43+ name : string ;
44+
45+ constructor ( name : string ) {
46+ super ( ) ;
47+ this . name = name ;
48+ }
49+ }
1550@WebSocketGateway ( 1234 )
1651export class YjsService
1752 implements OnGatewayInit , OnGatewayConnection , OnGatewayDisconnect
@@ -21,6 +56,8 @@ export class YjsService
2156
2257 constructor (
2358 private readonly nodeService : NodeService ,
59+ private readonly pageService : PageService ,
60+ private readonly edgeService : EdgeService ,
2461 private readonly nodeCacheService : NodeCacheService ,
2562 ) { }
2663 @WebSocketServer ( )
@@ -38,22 +75,31 @@ export class YjsService
3875
3976 this . ysocketio . initialize ( ) ;
4077
41- this . ysocketio . on ( 'document-update' , ( doc : Y . Doc ) => {
42- // console.log(doc.get("content").doc.share.get("content"));
43- // console.log(doc.share.get('default'));
44- } ) ;
45-
4678 this . ysocketio . on ( 'document-loaded' , ( doc : Y . Doc ) => {
47- doc . on ( 'update' , ( ) => {
79+ const nodes = doc . getMap ( 'nodes' ) ;
80+ const edges = doc . getMap ( 'edges' ) ;
81+ const editorDoc = doc . getXmlFragment ( 'default' ) ;
82+
83+ // page content의 변경 사항을 감지한다.
84+ editorDoc . observeDeep ( ( ) => {
85+ const document = editorDoc . doc as CustomDoc ;
86+ const pageId = parseInt ( document . name . split ( '-' ) [ 1 ] ) ;
87+ this . pageService . updatePage (
88+ pageId ,
89+ JSON . parse ( JSON . stringify ( yXmlFragmentToProsemirrorJSON ( editorDoc ) ) ) ,
90+ ) ;
91+ } ) ;
92+
93+ // node의 변경 사항을 감지한다.
94+ nodes . observe ( ( ) => {
4895 const nodes = Object . values ( doc . getMap ( 'nodes' ) . toJSON ( ) ) ;
4996
5097 // 모든 노드에 대해 검사한다.
51- nodes . forEach ( ( node ) => {
98+ nodes . forEach ( ( node : YMapNode ) => {
5299 const { title, id } = node . data ;
53100 const { x, y } = node . position ;
54101 // 만약 캐쉬에 노드가 존재하지 않다면 갱신 후 캐쉬에 노드를 넣는다.
55102 if ( ! this . nodeCacheService . has ( id ) ) {
56- console . log ( id ) ;
57103 this . nodeService . updateNode ( id , { title, x, y } ) ;
58104 this . nodeCacheService . set ( id , title ) ;
59105 return ;
@@ -68,6 +114,24 @@ export class YjsService
68114 // 만약 캐쉬에 노드가 존재하고 title이 동일하다면 패스한다.
69115 } ) ;
70116 } ) ;
117+ // edge의 변경 사항을 감지한다.
118+ edges . observe ( ( ) => {
119+ const edges = Object . values ( doc . getMap ( 'edges' ) . toJSON ( ) ) ;
120+ edges . forEach ( async ( edge : YMapEdge ) => {
121+ console . log ( edge ) ;
122+ const findEdge = await this . edgeService . findEdgeByFromNodeAndToNode (
123+ parseInt ( edge . source ) ,
124+ parseInt ( edge . target ) ,
125+ ) ;
126+ // 연결된 노드가 없을 때만 edge 생성
127+ if ( ! findEdge ) {
128+ await this . edgeService . createEdge ( {
129+ fromNode : parseInt ( edge . source ) ,
130+ toNode : parseInt ( edge . target ) ,
131+ } ) ;
132+ }
133+ } ) ;
134+ } ) ;
71135 } ) ;
72136 }
73137
0 commit comments