@@ -10,12 +10,18 @@ import { implementWaffleService } from './services/WaffleService';
1010
1111import type { MongoClient } from 'mongodb' ;
1212import { z } from 'zod' ;
13+ import {
14+ type WaffleGraphDashboardService ,
15+ implementWaffleGraphDashboardService ,
16+ } from './services/WaffleGraphDashboardService' ;
1317
1418export const handle = async (
1519 dependencies : {
1620 slackClient : Pick < WebClient [ 'chat' ] , 'postMessage' | 'getPermalink' > ;
1721 mongoClient : Pick < MongoClient , 'db' > ;
18- wadotClient : { listUsers : ( ) => Promise < { github_id : string ; slack_id : string } [ ] > } ;
22+ wadotClient : {
23+ listUsers : ( ) => Promise < { github_id : string ; slack_id : string ; first_name : string } [ ] > ;
24+ } ;
1925 } ,
2026 env : {
2127 slackBotToken : string ;
@@ -50,6 +56,10 @@ export const handle = async (
5056 } ,
5157 } ,
5258 } ) ;
59+ const waffleGraphDashboardService = implementWaffleGraphDashboardService ( {
60+ waffleRepository : implementMongoAtlasWaffleRepository ( dependencies ) ,
61+ memberRepository : implementMemberWaffleDotComRepository ( dependencies ) ,
62+ } ) ;
5363 const deployWebhookController = implementGitHubDeployWebhookController ( {
5464 deploymentService : implementDeploymentService ( {
5565 messengerPresenter : implementSlackPresenter ( {
@@ -66,6 +76,14 @@ export const handle = async (
6676 if ( request . method === 'GET' && url . pathname === '/health-check' )
6777 return new Response ( 'ok' , { status : 200 } ) ;
6878
79+ if ( request . method === 'GET' && url . pathname === '/dashboard' ) {
80+ const data = await waffleGraphDashboardService . getGraphData ( ) ;
81+ return new Response ( html ( data ) , {
82+ status : 200 ,
83+ headers : { 'content-type' : 'text/html;charset=utf-8' } ,
84+ } ) ;
85+ }
86+
6987 if ( request . method === 'POST' && url . pathname === '/slack/action-endpoint' ) {
7088 const body = ( await request . json ( ) ) as {
7189 token : unknown ;
@@ -135,3 +153,32 @@ export const handle = async (
135153 return new Response ( null , { status : 500 } ) ;
136154 }
137155} ;
156+
157+ const html = ( data : Awaited < ReturnType < WaffleGraphDashboardService [ 'getGraphData' ] > > ) => {
158+ return `
159+ <!DOCTYPE html>
160+ <html lang="ko">
161+ <head>
162+ <title>Waffle Dashboard</title>
163+ <script src="//cdn.jsdelivr.net/npm/3d-force-graph"></script>
164+ </head>
165+ <body style="margin: 0">
166+ <div id="graph"></div>
167+
168+ <script>
169+ const gData = {
170+ nodes: ${ JSON . stringify ( data . vertexes ) } ,
171+ links: ${ JSON . stringify ( data . edges . map ( ( e ) => ( { source : e . from , target : e . to , count : e . count } ) ) ) }
172+ };
173+
174+ const Graph = ForceGraph3D()
175+ (document.getElementById('graph'))
176+ .nodeVal(node => node.count / 10) // use val for node size
177+ .nodeLabel(node => node.title)
178+ .linkWidth(link => link.count * 0.03) // use weight for link thickness
179+ .graphData(gData);
180+ </script>
181+ </body>
182+ </html>
183+ ` ;
184+ } ;
0 commit comments