Skip to content
This repository was archived by the owner on Sep 12, 2019. It is now read-only.

Commit d3f973b

Browse files
authored
Merge pull request #74 from stellar/bridge-admin-gui
Admin GUI
2 parents f77234d + 932eabc commit d3f973b

37 files changed

+1825
-72
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@
55
/bin
66
/dist
77
/config.toml
8+
/gui/.tmp
9+
/gui/yarn.lock
10+
/gui/node_modules
11+
/gui/dist

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@ gb build
3131

3232
After a successful build, you should find `bin/bridge` in the project directory.
3333

34+
### GUI
35+
36+
To build user interface for the bridge server go to `gui` folder and run:
37+
38+
```
39+
gulp build
40+
```
41+
42+
For development run:
43+
44+
```
45+
gulp develop
46+
```
47+
3448
## Running tests
3549

3650
```

gui/gulpfile.babel.js

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
'use strict';
2+
3+
var _ = require('lodash');
4+
var bs = require('browser-sync').create();
5+
var gulp = require('gulp');
6+
var path = require('path');
7+
var webpack = require("webpack");
8+
9+
gulp.task('default', ['develop']);
10+
11+
var webpackOptions = {
12+
entry: {
13+
app: "./src/app.js",
14+
vendor: ["react", "react-dom", "muicss", "stellar-sdk", "axios", "d3", "fbemitter"]
15+
},
16+
devtool: "source-map",
17+
resolve: {
18+
root: [
19+
path.resolve('src'),
20+
path.resolve('common')
21+
],
22+
modulesDirectories: ["node_modules"]
23+
},
24+
module: {
25+
loaders: [
26+
{test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', query: {presets: ['es2015', 'react']}},
27+
{test: /\.json$/, loader: 'json'},
28+
{test: /\.html$/, loader: 'file?name=[name].html'},
29+
]
30+
},
31+
plugins: [
32+
new webpack.IgnorePlugin(/ed25519/)
33+
]
34+
};
35+
36+
gulp.task('develop', function(done) {
37+
var options = merge(webpackOptions, {
38+
output: {
39+
filename: "[name].js",
40+
path: './.tmp/admin'
41+
},
42+
plugins: [
43+
new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.js")
44+
]
45+
});
46+
47+
var watchOptions = {
48+
aggregateTimeout: 300
49+
};
50+
51+
var bsInitialized = false;
52+
53+
var compiler = webpack(options);
54+
compiler.purgeInputFileSystem();
55+
compiler.watch(watchOptions, function(error, stats) {
56+
if (!bsInitialized) {
57+
gulp.watch(".tmp/**/*").on("change", bs.reload);
58+
bs.init({
59+
port: 3000,
60+
online: false,
61+
notify: false,
62+
server: "./.tmp",
63+
startPath: '/admin/index.html',
64+
socket: {
65+
// Golang httputil.ReverseProxy removes trailing slash from request before passing
66+
// it to destination folder. This made the socket.io used by browser-sync fail.
67+
// Make sure socket.io client connects to the destination server (not use proxy).
68+
domain: 'localhost:3000'
69+
}
70+
});
71+
bsInitialized = true;
72+
}
73+
console.log(stats.toString({
74+
hash: false,
75+
version: false,
76+
timings: true,
77+
chunks: false,
78+
colors: true
79+
}));
80+
});
81+
});
82+
83+
gulp.task('build', function(done) {
84+
var options = merge(webpackOptions, {
85+
bail: true,
86+
output: {
87+
// TODO chunkhash
88+
filename: "[name].js",//"[name]-[chunkhash].js",
89+
path: './dist'
90+
},
91+
plugins: [
92+
new webpack.optimize.CommonsChunkPlugin("vendor", "vendor.js"),
93+
new webpack.optimize.DedupePlugin(),
94+
new webpack.optimize.OccurenceOrderPlugin(),
95+
new webpack.DefinePlugin({
96+
'process.env': {
97+
NODE_ENV: JSON.stringify('production'),
98+
}
99+
}),
100+
new webpack.optimize.UglifyJsPlugin()
101+
]
102+
});
103+
104+
var compiler = webpack(options);
105+
compiler.purgeInputFileSystem();
106+
compiler.run(done);
107+
});
108+
109+
110+
function merge(object1, object2) {
111+
return _.mergeWith(object1, object2, function(a, b) {
112+
if (_.isArray(a)) {
113+
return a.concat(b);
114+
}
115+
});
116+
}

gui/package.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "bridge-server-admin",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "index.js",
6+
"author": "Stellar.org",
7+
"dependencies": {
8+
"axios": "^0.15.3",
9+
"babel-core": "^6.23.0",
10+
"babel-loader": "^6.3.2",
11+
"babel-preset-es2015": "^6.22.0",
12+
"babel-preset-react": "^6.23.0",
13+
"babel-register": "^6.24.0",
14+
"bignumber.js": "^3.0.1",
15+
"browser-sync": "^2.18.2",
16+
"fbemitter": "^2.1.1",
17+
"file-loader": "^0.9.0",
18+
"gulp": "^3.9.1",
19+
"lodash": "^4.17.2",
20+
"moment": "^2.17.1",
21+
"muicss": "^0.9.24",
22+
"react": "^15.4.1",
23+
"react-d3-components": "^0.6.5",
24+
"react-dom": "^15.4.1",
25+
"react-router-dom": "^4.2.2",
26+
"stellar-sdk": "^0.6.2",
27+
"webpack": "^1.13.3"
28+
}
29+
}

gui/src/app.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
import App from './components/App.js';
4+
5+
require('./index.html');
6+
7+
ReactDOM.render(
8+
<App></App>,
9+
document.getElementById('app')
10+
);

gui/src/components/App.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react';
2+
import {HashRouter as Router, Route, Link} from 'react-router-dom';
3+
import AppBar from './AppBar';
4+
import Navigation from './Navigation';
5+
import ReceivedTransactions from './ReceivedTransactions';
6+
import ReceivedTransactionDetails from './ReceivedTransactionDetails';
7+
import SentTransactions from './SentTransactions';
8+
9+
export default class App extends React.Component {
10+
render() {
11+
return (
12+
<Router>
13+
<div>
14+
<AppBar />
15+
<main>
16+
<Route component={Navigation} />
17+
18+
<Route exact path="/(sent)?" component={SentTransactions} />
19+
<Route exact path="/received" component={ReceivedTransactions} />
20+
<Route path="/received/:id" component={ReceivedTransactionDetails} />
21+
</main>
22+
</div>
23+
</Router>
24+
);
25+
}
26+
}

gui/src/components/AppBar.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from 'react';
2+
3+
export default class AppBar extends React.Component {
4+
render() {
5+
return <div>
6+
<div className="mui-appbar">
7+
<div className="inner">
8+
<div className="mui--text-headline">Bridge Server</div>
9+
</div>
10+
</div>
11+
</div>
12+
}
13+
}

gui/src/components/Navigation.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import React from 'react';
2+
import Tabs from 'muicss/lib/react/tabs';
3+
import Tab from 'muicss/lib/react/tab';
4+
5+
export default class Navigation extends React.Component {
6+
constructor({history, location}) {
7+
super();
8+
this.state = {};
9+
this.history = history;
10+
this.state.selected = this.getActive(location.pathname);
11+
}
12+
13+
componentWillReceiveProps(nextProps) {
14+
const locationChanged = nextProps.location !== this.props.location;
15+
16+
if (locationChanged) {
17+
let selected = this.getActive(nextProps.location.pathname);
18+
this.setState({selected});
19+
}
20+
}
21+
22+
onChange(i, id) {
23+
this.history.push("/"+id);
24+
}
25+
26+
getActive(pathname) {
27+
let state = {};
28+
if (pathname.indexOf('/sent') == 0) {
29+
return 0;
30+
} else if (pathname.indexOf('/received') == 0) {
31+
return 1;
32+
} else {
33+
return 0;
34+
}
35+
}
36+
37+
render() {
38+
return <Tabs onChange={this.onChange.bind(this)} defaultSelectedIndex={this.state.selected}>
39+
<Tab value="sent" label="Sent Transactions"></Tab>
40+
<Tab value="received" label="Received Transactions"></Tab>
41+
</Tabs>
42+
}
43+
}

0 commit comments

Comments
 (0)