Commit bdd674e048f8917357c9360017872a4d20836af0
refactor to work with browserify as a static page
Michael Williams committed on 12/9/2016, 12:28:25 AMParent: 4c04551a3e25f880780438f3d6ba6a54f100d610
Files changed
graph.js | changed |
index.js | changed |
package.json | changed |
renderer.js | changed |
data.js | added |
output.js | deleted |
output/config.js | added |
output/index.html | added |
output/index.js | added |
graph.js | ||
---|---|---|
@@ -1,45 +1,35 @@ | ||
1 | 1 … | const waterfall = require('run-waterfall') |
2 | - | |
3 | 2 … | const { keys } = Object |
4 | 3 … | |
4 … | +const fetchData = require('./data') | |
5 … | + | |
5 | 6 … | module.exports = Graph |
6 | 7 … | |
7 | -function Graph (sbot, cb) { | |
8 | - waterfall([ | |
9 | - (cb) => sbot.friends.all(cb), | |
10 | - (friends, cb) => { | |
11 | - const filteredFriends = friends // activeFriends(friends) | |
12 | - | |
13 | - cb(null, { | |
14 | - nodes: buildNodes(filteredFriends), | |
15 | - links: buildLinks(filteredFriends) | |
16 | - }) | |
17 | - } | |
18 | - ], cb) | |
8 … | +function Graph (friends, cb) { | |
9 … | + return { | |
10 … | + nodes: buildNodes(friends), | |
11 … | + links: buildLinks(friends) | |
12 … | + } | |
19 | 13 … | } |
20 | 14 … | |
21 | 15 … | function buildNodes (friends) { |
22 | - return keys(friends).map(id => { | |
16 … | + return friends.map(friend => { | |
23 | 17 … | return { |
24 | - id, | |
25 | - data: { | |
26 | - friends: keys(friends[id]) | |
27 | - } | |
18 … | + id: friend.id, | |
19 … | + data: friend | |
28 | 20 … | } |
29 | 21 … | }) |
30 | 22 … | } |
31 | 23 … | |
32 | 24 … | function buildLinks (friends) { |
33 | - return keys(friends).reduce((sofar, friend) => { | |
34 | - const friendOfFriends = keys(friends[friend]) | |
35 | - .filter(id => friends[friend][id] === true) | |
36 | - | |
25 … | + return friends.reduce((sofar, friend) => { | |
26 … | + const friendOfFriends = friend.friends | |
37 | 27 … | const edges = friendOfFriends.map(friendOfFriend => { |
38 | 28 … | return { |
39 | - fromId: friend, | |
29 … | + fromId: friend.id, | |
40 | 30 … | toId: friendOfFriend, |
41 | - data: { | |
31 … | + friends: { | |
42 | 32 … | hidden: true |
43 | 33 … | } |
44 | 34 … | } |
45 | 35 … | }) |
@@ -49,19 +39,4 @@ | ||
49 | 39 … | ...edges |
50 | 40 … | ] |
51 | 41 … | }, []) |
52 | 42 … | } |
53 | - | |
54 | -/* | |
55 | -function activeFriends (friends) { | |
56 | - return keys(friends) | |
57 | - .reduce( | |
58 | - (sofar, current) => { | |
59 | - if (keys(friends[current]).length < 4) return sofar | |
60 | - | |
61 | - sofar[current] = friends[current] | |
62 | - return sofar | |
63 | - }, | |
64 | - {} | |
65 | - ) | |
66 | -} | |
67 | -*/ |
index.js | ||
---|---|---|
@@ -1,34 +1,12 @@ | ||
1 | 1 … | const fromJson = require('ngraph.fromjson') |
2 | 2 … | const Renderer = require('./renderer') |
3 | 3 … | const Graph = require('./graph') |
4 | 4 … | |
5 | -const config = { | |
6 | - physics: { | |
7 | - springLength: 80, | |
8 | - springCoeff: 0.0001, | |
9 | - gravity: -1.4, | |
10 | - theta: 0.4, | |
11 | - dragCoeff: 0.04 | |
12 | - }, | |
13 | - link: (link) => { | |
14 | - // if (link.data.hidden) return | |
15 | - // makes linkUI element not exist ? => display.getLink doesn't work | |
16 | - | |
17 | - return { | |
18 | - fromColor: 0x000066, | |
19 | - toColor: 0x000066 | |
20 | - } | |
21 | - } | |
5 … | +module.exports = function (data, config, cb) { | |
6 … | + const graphData = Graph(data) | |
7 … | + const str = JSON.stringify(graphData) | |
8 … | + var graph = fromJson(str) | |
9 … | + var display = Renderer(graph, config) | |
10 … | + return display | |
22 | 11 … | } |
23 | 12 … | |
24 | -module.exports = function (sbot, cb) { | |
25 | - Graph(sbot, (err, data) => { | |
26 | - if (err) return cb(err) | |
27 | - const str = JSON.stringify(data) | |
28 | - var graph = fromJson(str) | |
29 | - var display = Renderer(graph, config, sbot) | |
30 | - | |
31 | - cb(null, display) | |
32 | - }) | |
33 | -} | |
34 | - |
package.json | ||
---|---|---|
@@ -4,10 +4,26 @@ | ||
4 | 4 … | "description": "visualize the ssb network graph", |
5 | 5 … | "main": "index.js", |
6 | 6 … | "scripts": { |
7 | 7 … | "test": "standard", |
8 | - "start": "electro output.js" | |
8 … | + "start": "budo output:bundle.js -d output --live -- -d", | |
9 … | + "bundle": "browserify output -g envify -g uglifyify", | |
10 … | + "build": "npm run --silent bundle -- -o output/bundle.js", | |
11 … | + "disc": "npm run --silent bundle -- --full-paths | discify --open", | |
12 … | + "push": "gh-pages -d output", | |
13 … | + "deploy": "npm-run-all -s build push" | |
9 | 14 … | }, |
15 … | + "browserify": { | |
16 … | + "transform": [ | |
17 … | + [ | |
18 … | + "configurify", | |
19 … | + { | |
20 … | + "pattern": "**/data.js" | |
21 … | + } | |
22 … | + ], | |
23 … | + "es2040" | |
24 … | + ] | |
25 … | + }, | |
10 | 26 … | "repository": { |
11 | 27 … | "type": "git", |
12 | 28 … | "url": " ssb://%hNm67sfnZFtWkD/+1qxH3UfzhXykfpKtOL1C/XbLANA=.sha256" |
13 | 29 … | }, |
@@ -18,23 +34,26 @@ | ||
18 | 34 … | "url": "https://git.scuttlebot.io/%25hNm67sfnZFtWkD%2F%2B1qxH3UfzhXykfpKtOL1C%2FXbLANA%3D.sha256/issues" |
19 | 35 … | }, |
20 | 36 … | "homepage": "https://git.scuttlebot.io/%25hNm67sfnZFtWkD%2F%2B1qxH3UfzhXykfpKtOL1C%2FXbLANA%3D.sha256#readme", |
21 | 37 … | "devDependencies": { |
38 … | + "browserify": "^13.1.1", | |
39 … | + "budo": "^9.3.0", | |
40 … | + "configurify": "^1.0.0", | |
41 … | + "disc": "^1.3.2", | |
42 … | + "es2040": "^1.2.4", | |
43 … | + "npm-run-all": "^3.1.2", | |
22 | 44 … | "standard": "^8.6.0", |
23 | - "tape": "^4.5.1" | |
45 … | + "tape": "^4.5.1", | |
46 … | + "uglifyify": "^3.0.4", | |
47 … | + "watchify": "^3.7.0" | |
24 | 48 … | }, |
25 | 49 … | "dependencies": { |
26 | - "electro": "^2.0.2", | |
27 | - "electron": "^1.4.4", | |
28 | - "hyperscript": "^2.0.2", | |
29 | 50 … | "insert-css": "^1.0.0", |
30 | - "inu": "^3.1.3", | |
31 | 51 … | "ngraph.fromjson": "^0.1.8", |
32 | 52 … | "ngraph.pixel": "^2.2.0", |
33 | - "pull-stream": "^3.4.5", | |
53 … | + "run-parallel": "^1.1.6", | |
34 | 54 … | "run-waterfall": "^1.1.3", |
35 | 55 … | "ssb-avatar": "^0.2.0", |
36 | 56 … | "ssb-client": "^4.3.0", |
37 | - "stream-to-pull-stream": "^1.7.2", | |
38 | 57 … | "yo-yo": "^1.3.1" |
39 | 58 … | } |
40 | 59 … | } |
renderer.js | ||
---|---|---|
@@ -3,9 +3,9 @@ | ||
3 | 3 … | const html = require('yo-yo') |
4 | 4 … | |
5 | 5 … | module.exports = createRenderer |
6 | 6 … | |
7 | -function createRenderer (graph, config, sbot) { | |
7 … | +function createRenderer (graph, config) { | |
8 | 8 … | var avatarEl = html`<div class="avatar" />` |
9 | 9 … | document.body.appendChild(avatarEl) |
10 | 10 … | |
11 | 11 … | var display = Renderer(graph, config) |
@@ -16,24 +16,20 @@ | ||
16 | 16 … | |
17 | 17 … | function handleNodeHover (node) { |
18 | 18 … | if (node === undefined) return |
19 | 19 … | |
20 | - avatar(sbot, node.id, node.id, (err, { name, image }) => { | |
21 | - // handle this error! | |
22 | - if (err) throw err | |
20 … | + const { name, image } = node.data.about | |
21 … | + const imgSrc = image ? `http://localhost:7777/${image}` : '' | |
23 | 22 … | |
24 | - const imgSrc = image ? `http://localhost:7777/${image}` : '' | |
23 … | + const newAvatarEl = html` | |
24 … | + <div class="avatar"> | |
25 … | + <img class="image" src=${imgSrc} /> | |
26 … | + <div class="name">${name}</div> | |
27 … | + </div> | |
28 … | + ` | |
25 | 29 … | |
26 | - const newAvatarEl = html` | |
27 | - <div class="avatar"> | |
28 | - <img class="image" src=${imgSrc} /> | |
29 | - <div class="name">${name}</div> | |
30 | - </div> | |
31 | - ` | |
30 … | + html.update(avatarEl, newAvatarEl) | |
32 | 31 … | |
33 | - html.update(avatarEl, newAvatarEl) | |
34 | - }) | |
35 | - | |
36 | 32 … | display.forEachLink(linkUI => { |
37 | 33 … | const { from, to } = linkUI |
38 | 34 … | const friends = node.data.friends |
39 | 35 … |
data.js | |||
---|---|---|---|
@@ -1,0 +1,90 @@ | |||
1 … | +const { keys } = Object | ||
2 … | +const { join } = require('path') | ||
3 … | +const Sbot = require('ssb-client') | ||
4 … | +const avatar = require('ssb-avatar') | ||
5 … | +const waterfall = require('run-waterfall') | ||
6 … | +const parallel = require('run-parallel') | ||
7 … | +// const pull = require('pull-stream') | ||
8 … | +// const writeFile = require('pull-write-file') | ||
9 … | + | ||
10 … | +module.exports = fetchData | ||
11 … | + | ||
12 … | +function fetchData (cb) { | ||
13 … | + waterfall([ | ||
14 … | + Sbot, | ||
15 … | + (sbot, cb) => { | ||
16 … | + // fetch friend graph | ||
17 … | + sbot.friends.all((err, friends) => { | ||
18 … | + cb(err, sbot, friends) | ||
19 … | + }) | ||
20 … | + }, | ||
21 … | + (sbot, friends, cb) => { | ||
22 … | + // fetch profiles (name and avatar) | ||
23 … | + return parallel( | ||
24 … | + keys(friends).map(id => { | ||
25 … | + const friendOfFriends = keys(friends[id]) | ||
26 … | + .filter(foafId => friends[id][foafId] === true) | ||
27 … | + return (cb) => { | ||
28 … | + avatar(sbot, id, id, (err, { name, image }) => { | ||
29 … | + if (err) cb(err) | ||
30 … | + else cb(null, { | ||
31 … | + id, | ||
32 … | + friends: friendOfFriends, | ||
33 … | + about: { | ||
34 … | + name, | ||
35 … | + image | ||
36 … | + } | ||
37 … | + }) | ||
38 … | + }) | ||
39 … | + } | ||
40 … | + }) | ||
41 … | + , (err, friends) => { | ||
42 … | + cb(err, sbot, friends) | ||
43 … | + }) | ||
44 … | + }, | ||
45 … | + /* | ||
46 … | + (sbot, friends, cb) => { | ||
47 … | + // fetch images | ||
48 … | + return parallel( | ||
49 … | + friends.map(friend => { | ||
50 … | + const imageBlobId = friend.about.image | ||
51 … | + if (imageBlobId) { | ||
52 … | + const imageId = pathFriendlyId(imageBlobId) | ||
53 … | + const imagePath = join(__dirname, 'output', 'images', imageId) | ||
54 … | + const imageUrl = `/images/${imageId}` | ||
55 … | + return (cb) => { | ||
56 … | + pull( | ||
57 … | + sbot.blobs.get(imageBlobId), | ||
58 … | + writeFile(imagePath, function (err) { | ||
59 … | + if (err) cb(err) | ||
60 … | + else cb(null, { | ||
61 … | + id: friend.id, | ||
62 … | + friends: friend.friends, | ||
63 … | + about: { | ||
64 … | + name: friend.about.name, | ||
65 … | + image: imageUrl | ||
66 … | + } | ||
67 … | + }) | ||
68 … | + }) | ||
69 … | + ) | ||
70 … | + } | ||
71 … | + } else return (cb) => cb(null, friend) | ||
72 … | + }) | ||
73 … | + ) | ||
74 … | + }, | ||
75 … | + */ | ||
76 … | + (sbot, friends, cb) => { | ||
77 … | + sbot.close(err => { | ||
78 … | + cb(err, friends) | ||
79 … | + }) | ||
80 … | + } | ||
81 … | + ], cb) | ||
82 … | +} | ||
83 … | + | ||
84 … | +/* | ||
85 … | +function pathFriendlyId (str) { | ||
86 … | + return str | ||
87 … | + .replace(/\+/g, '-') | ||
88 … | + .replace(/\//g, '_') | ||
89 … | +} | ||
90 … | +*/ |
output.js | ||
---|---|---|
@@ -1,31 +1,0 @@ | ||
1 | -const insertCss = require('insert-css') | |
2 | -const Sbot = require('ssb-client') | |
3 | -const waterfall = require('run-waterfall') | |
4 | - | |
5 | -const Viz = require('./') | |
6 | - | |
7 | -insertCss(` | |
8 | - html, body { | |
9 | - width: 100%; | |
10 | - height: 100%; | |
11 | - position: absolute; | |
12 | - overflow: hidden; | |
13 | - padding: 0; | |
14 | - margin: 0; | |
15 | - } | |
16 | - | |
17 | - .avatar { | |
18 | - position: fixed; | |
19 | - left: 10px; | |
20 | - bottom: 10px; | |
21 | - color: #fff; | |
22 | - } | |
23 | - | |
24 | - .avatar .image { | |
25 | - max-height: 160px; | |
26 | - } | |
27 | -`) | |
28 | - | |
29 | -waterfall([Sbot, Viz], (err) => { | |
30 | - if (err) throw err | |
31 | -}) |
output/config.js | ||
---|---|---|
@@ -1,0 +1,21 @@ | ||
1 … | +const config = { | |
2 … | + physics: { | |
3 … | + springLength: 80, | |
4 … | + springCoeff: 0.0001, | |
5 … | + gravity: -1.4, | |
6 … | + theta: 0.4, | |
7 … | + dragCoeff: 0.04 | |
8 … | + }, | |
9 … | + link: (link) => { | |
10 … | + // if (link.data.hidden) return | |
11 … | + // makes linkUI element not exist ? => display.getLink doesn't work | |
12 … | + | |
13 … | + return { | |
14 … | + fromColor: 0x000066, | |
15 … | + toColor: 0x000066 | |
16 … | + } | |
17 … | + }, | |
18 … | + container: document.body.querySelector('main') | |
19 … | +} | |
20 … | + | |
21 … | +module.exports = config |
output/index.html | ||
---|---|---|
@@ -1,0 +1,13 @@ | ||
1 … | + | |
2 … | +<html lang="en"> | |
3 … | + <head> | |
4 … | + <meta charset="utf-8" /> | |
5 … | + <title>ssb-graphviz</title> | |
6 … | + <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
7 … | + </head> | |
8 … | + <body> | |
9 … | + <main> | |
10 … | + </main> | |
11 … | + <script src="bundle.js"></script> | |
12 … | + </body> | |
13 … | +</html> |
output/index.js | ||
---|---|---|
@@ -1,0 +1,32 @@ | ||
1 … | +const insertCss = require('insert-css') | |
2 … | + | |
3 … | +const config = require('./config') | |
4 … | +const Data = require('../data') | |
5 … | +const Viz = require('../') | |
6 … | + | |
7 … | +insertCss(` | |
8 … | + html, body, main { | |
9 … | + width: 100%; | |
10 … | + height: 100%; | |
11 … | + position: absolute; | |
12 … | + overflow: hidden; | |
13 … | + padding: 0; | |
14 … | + margin: 0; | |
15 … | + } | |
16 … | + | |
17 … | + .avatar { | |
18 … | + position: fixed; | |
19 … | + left: 10px; | |
20 … | + bottom: 10px; | |
21 … | + color: #fff; | |
22 … | + } | |
23 … | + | |
24 … | + .avatar .image { | |
25 … | + max-height: 160px; | |
26 … | + } | |
27 … | +`) | |
28 … | + | |
29 … | +Data((err, data) => { | |
30 … | + if (err) throw err | |
31 … | + Viz(data, config) | |
32 … | +}) |
Built with git-ssb-web