Route caching bug fix, simplify routing (#763)
* move window.apiPrefix into Angular service
* avoid routing by accept headers, integrate api service
* Revert "Fixed over-matching of index route."
This reverts commit 62e1225dd3.
* better name for index template file
This commit is contained in:
parent
cc7c6f81d4
commit
340decd978
23
Gruntfile.js
23
Gruntfile.js
@ -1,5 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// var config = require('insight-config.json');
|
||||||
|
|
||||||
module.exports = function(grunt) {
|
module.exports = function(grunt) {
|
||||||
|
|
||||||
//Load NPM tasks
|
//Load NPM tasks
|
||||||
@ -10,10 +12,27 @@ module.exports = function(grunt) {
|
|||||||
grunt.loadNpmTasks('grunt-markdown');
|
grunt.loadNpmTasks('grunt-markdown');
|
||||||
grunt.loadNpmTasks('grunt-macreload');
|
grunt.loadNpmTasks('grunt-macreload');
|
||||||
grunt.loadNpmTasks('grunt-angular-gettext');
|
grunt.loadNpmTasks('grunt-angular-gettext');
|
||||||
|
grunt.loadNpmTasks('grunt-replace');
|
||||||
|
|
||||||
// Project Configuration
|
// Project Configuration
|
||||||
grunt.initConfig({
|
grunt.initConfig({
|
||||||
pkg: grunt.file.readJSON('package.json'),
|
pkg: grunt.file.readJSON('package.json'),
|
||||||
|
replace: {
|
||||||
|
dist: {
|
||||||
|
options: {
|
||||||
|
patterns: [
|
||||||
|
{
|
||||||
|
match: 'INSIGHT_API_PREFIX',
|
||||||
|
replacement: '<%= pkg.insightConfig.apiPrefix %>'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
usePrefix: false
|
||||||
|
},
|
||||||
|
files: [
|
||||||
|
{src: ['public/src/templates/api.js'], dest: 'public/src/js/services/api.js'}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
concat: {
|
concat: {
|
||||||
options: {
|
options: {
|
||||||
process: function(src, filepath) {
|
process: function(src, filepath) {
|
||||||
@ -117,13 +136,13 @@ module.exports = function(grunt) {
|
|||||||
grunt.option('force', true);
|
grunt.option('force', true);
|
||||||
|
|
||||||
//Default task(s).
|
//Default task(s).
|
||||||
grunt.registerTask('default', ['watch']);
|
grunt.registerTask('default', ['replace', 'watch']);
|
||||||
|
|
||||||
//Update .pot file
|
//Update .pot file
|
||||||
grunt.registerTask('translate', ['nggettext_extract']);
|
grunt.registerTask('translate', ['nggettext_extract']);
|
||||||
|
|
||||||
//Compile task (concat + minify)
|
//Compile task (concat + minify)
|
||||||
grunt.registerTask('compile', ['nggettext_compile', 'concat', 'uglify', 'cssmin']);
|
grunt.registerTask('compile', ['replace', 'nggettext_compile', 'concat', 'uglify', 'cssmin']);
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
34
README.md
34
README.md
@ -23,24 +23,42 @@ Open a web browser to `http://localhost:3001/insight/`
|
|||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
To run Insight UI locally in development mode:
|
To build Insight UI locally:
|
||||||
|
|
||||||
Install bower dependencies:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
$ bower install
|
$ npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
To compile and minify the web application's assets:
|
A watch task is also available:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ grunt compile
|
$ npm run watch
|
||||||
```
|
```
|
||||||
|
|
||||||
There is a convenient Gruntfile.js for automation during editing the code
|
## Changing routePrefix and apiPrefix
|
||||||
|
|
||||||
|
By default, the `insightConfig` in `package.json` is:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"insightConfig": {
|
||||||
|
"apiPrefix": "insight-api",
|
||||||
|
"routePrefix": "insight"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To change these routes, first make your changes to `package.json`, for example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"insightConfig": {
|
||||||
|
"apiPrefix": "api",
|
||||||
|
"routePrefix": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then rebuild the `insight-ui` service:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ grunt
|
$ npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
## Multilanguage support
|
## Multilanguage support
|
||||||
|
|||||||
@ -3,19 +3,15 @@
|
|||||||
var BaseService = require('./service');
|
var BaseService = require('./service');
|
||||||
var inherits = require('util').inherits;
|
var inherits = require('util').inherits;
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
var pkg = require('../package');
|
||||||
|
|
||||||
var InsightUI = function(options) {
|
var InsightUI = function(options) {
|
||||||
BaseService.call(this, options);
|
BaseService.call(this, options);
|
||||||
if (typeof options.apiPrefix !== 'undefined') {
|
// we don't use the options object for routePrefix and apiPrefix, since the
|
||||||
this.apiPrefix = options.apiPrefix;
|
// client must be rebuilt with the proper options. A future version of
|
||||||
} else {
|
// Bitcore should allow for a service "build" step to make this better.
|
||||||
this.apiPrefix = 'insight-api';
|
this.apiPrefix = pkg.insightConfig.apiPrefix;
|
||||||
}
|
this.routePrefix = pkg.insightConfig.routePrefix;
|
||||||
if (typeof options.routePrefix !== 'undefined') {
|
|
||||||
this.routePrefix = options.routePrefix;
|
|
||||||
} else {
|
|
||||||
this.routePrefix = 'insight';
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
InsightUI.dependencies = ['insight-api'];
|
InsightUI.dependencies = ['insight-api'];
|
||||||
@ -23,20 +19,8 @@ InsightUI.dependencies = ['insight-api'];
|
|||||||
inherits(InsightUI, BaseService);
|
inherits(InsightUI, BaseService);
|
||||||
|
|
||||||
InsightUI.prototype.start = function(callback) {
|
InsightUI.prototype.start = function(callback) {
|
||||||
|
this.indexFile = this.filterIndexHTML(fs.readFileSync(__dirname + '/../public/index-template.html', {encoding: 'utf8'}));
|
||||||
var self = this;
|
setImmediate(callback);
|
||||||
|
|
||||||
var indexFile = __dirname + '/../public/index.html';
|
|
||||||
|
|
||||||
fs.readFile(indexFile, { encoding: 'utf8' }, function(err, data) {
|
|
||||||
|
|
||||||
if(err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.indexFile = self.filterIndexHTML(data);
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
InsightUI.prototype.getRoutePrefix = function() {
|
InsightUI.prototype.getRoutePrefix = function() {
|
||||||
@ -45,26 +29,19 @@ InsightUI.prototype.getRoutePrefix = function() {
|
|||||||
|
|
||||||
InsightUI.prototype.setupRoutes = function(app, express) {
|
InsightUI.prototype.setupRoutes = function(app, express) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
app.use(express.static(__dirname + '/../public'));
|
||||||
app.use('/', function(req, res, next){
|
// if not in found, fall back to indexFile (404 is handled client-side)
|
||||||
|
app.use(function(req, res, next) {
|
||||||
if (req.url === '/') {
|
res.setHeader('Content-Type', 'text/html');
|
||||||
res.send(self.indexFile);
|
res.send(self.indexFile);
|
||||||
} else {
|
|
||||||
express.static(__dirname + '/../public')(req, res, next);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
InsightUI.prototype.filterIndexHTML = function(data) {
|
InsightUI.prototype.filterIndexHTML = function(data) {
|
||||||
var transformed = data
|
var transformed = data;
|
||||||
.replace(/apiPrefix = '\/api'/, "apiPrefix = '/" + this.apiPrefix + "'");
|
if (this.routePrefix !== '') {
|
||||||
|
transformed = transformed.replace('<base href="/"', '<base href="/' + this.routePrefix + '/"');
|
||||||
if (this.routePrefix) {
|
|
||||||
transformed = transformed.replace(/<base href=\"\/\"/, '<base href="/' + this.routePrefix + '/"');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return transformed;
|
return transformed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
18
package.json
18
package.json
@ -39,19 +39,27 @@
|
|||||||
"front-end"
|
"front-end"
|
||||||
],
|
],
|
||||||
"bitcoreNode": "bitcore-node",
|
"bitcoreNode": "bitcore-node",
|
||||||
"dependencies": {
|
"insightConfig": {
|
||||||
|
"apiPrefix": "insight-api",
|
||||||
|
"routePrefix": "insight"
|
||||||
},
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "bower install && grunt compile",
|
||||||
|
"watch": "grunt"
|
||||||
|
},
|
||||||
|
"dependencies": {},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"bower": "~1.2.8",
|
"bower": "~1.8.0",
|
||||||
"grunt": "~0.4.2",
|
"grunt": "~0.4.2",
|
||||||
|
"grunt-angular-gettext": "^0.2.15",
|
||||||
"grunt-cli": "~0.1.11",
|
"grunt-cli": "~0.1.11",
|
||||||
"grunt-contrib-jshint": "~0.8.0",
|
|
||||||
"grunt-contrib-concat": "~0.3.0",
|
"grunt-contrib-concat": "~0.3.0",
|
||||||
|
"grunt-contrib-jshint": "~0.8.0",
|
||||||
"grunt-contrib-uglify": "~0.3.2",
|
"grunt-contrib-uglify": "~0.3.2",
|
||||||
"grunt-contrib-watch": "*",
|
"grunt-contrib-watch": "*",
|
||||||
"grunt-macreload": "*",
|
|
||||||
"grunt-css": "~0.5.4",
|
"grunt-css": "~0.5.4",
|
||||||
|
"grunt-macreload": "*",
|
||||||
"grunt-markdown": "~0.5.0",
|
"grunt-markdown": "~0.5.0",
|
||||||
"grunt-angular-gettext": "^0.2.15"
|
"grunt-replace": "^1.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
<meta name="fragment" content="!">
|
<meta name="fragment" content="!">
|
||||||
<title data-ng-bind="$root.title + $root.titleDetail + ' | Insight'">Insight</title>
|
<title data-ng-bind="$root.title + $root.titleDetail + ' | Insight'">Insight</title>
|
||||||
<meta name="keywords" content="bitcoins, transactions, blocks, address, block chain, best block, mining difficulty, hash serialized">
|
<meta name="keywords" content="bitcoins, transactions, blocks, address, block chain, best block, mining difficulty, hash serialized">
|
||||||
<meta name="description" content="Bitcoin Insight. View detailed information on all bitcoin transactions and block. {{ $root.title + $root.titleDetail }}">
|
<meta name="description" content="Bitcoin Insight. View detailed information on all bitcoin transactions and blocks.">
|
||||||
<link rel="shortcut icon" href="img/icons/favicon.ico" type="image/x-icon">
|
<link rel="shortcut icon" href="img/icons/favicon.ico" type="image/x-icon">
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,400italic">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700,400italic">
|
||||||
<link rel="stylesheet" href="css/main.min.css">
|
<link rel="stylesheet" href="css/main.min.css">
|
||||||
@ -66,7 +66,6 @@
|
|||||||
<a class="insight m10v pull-right" target="_blank" href="http://insight.is">insight <small>API v{{version}}</small></a>
|
<a class="insight m10v pull-right" target="_blank" href="http://insight.is">insight <small>API v{{version}}</small></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script language="javascript">window.apiPrefix = '/api';</script>
|
|
||||||
<script src="/socket.io/socket.io.js"></script>
|
<script src="/socket.io/socket.io.js"></script>
|
||||||
<script src="js/vendors.min.js"></script>
|
<script src="js/vendors.min.js"></script>
|
||||||
<script src="js/angularjs-all.min.js"></script>
|
<script src="js/angularjs-all.min.js"></script>
|
||||||
22
public/js/angularjs-all.min.js
vendored
22
public/js/angularjs-all.min.js
vendored
File diff suppressed because one or more lines are too long
6
public/js/main.min.js
vendored
6
public/js/main.min.js
vendored
File diff suppressed because one or more lines are too long
5
public/js/vendors.min.js
vendored
5
public/js/vendors.min.js
vendored
File diff suppressed because one or more lines are too long
@ -15,6 +15,7 @@ angular.module('insight',[
|
|||||||
'angularMoment',
|
'angularMoment',
|
||||||
'insight.system',
|
'insight.system',
|
||||||
'insight.socket',
|
'insight.socket',
|
||||||
|
'insight.api',
|
||||||
'insight.blocks',
|
'insight.blocks',
|
||||||
'insight.transactions',
|
'insight.transactions',
|
||||||
'insight.address',
|
'insight.address',
|
||||||
@ -27,6 +28,7 @@ angular.module('insight',[
|
|||||||
|
|
||||||
angular.module('insight.system', []);
|
angular.module('insight.system', []);
|
||||||
angular.module('insight.socket', []);
|
angular.module('insight.socket', []);
|
||||||
|
angular.module('insight.api', []);
|
||||||
angular.module('insight.blocks', []);
|
angular.module('insight.blocks', []);
|
||||||
angular.module('insight.transactions', []);
|
angular.module('insight.transactions', []);
|
||||||
angular.module('insight.address', []);
|
angular.module('insight.address', []);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('insight.messages').controller('VerifyMessageController',
|
angular.module('insight.messages').controller('VerifyMessageController',
|
||||||
function($scope, $http) {
|
function($scope, $http, Api) {
|
||||||
$scope.message = {
|
$scope.message = {
|
||||||
address: '',
|
address: '',
|
||||||
signature: '',
|
signature: '',
|
||||||
@ -22,7 +22,7 @@ angular.module('insight.messages').controller('VerifyMessageController',
|
|||||||
$scope.verify = function() {
|
$scope.verify = function() {
|
||||||
$scope.verification.status = 'loading';
|
$scope.verification.status = 'loading';
|
||||||
$scope.verification.address = $scope.message.address;
|
$scope.verification.address = $scope.message.address;
|
||||||
$http.post(window.apiPrefix + '/messages/verify', $scope.message)
|
$http.post(Api.apiPrefix + '/messages/verify', $scope.message)
|
||||||
.success(function(data, status, headers, config) {
|
.success(function(data, status, headers, config) {
|
||||||
if(typeof(data.result) != 'boolean') {
|
if(typeof(data.result) != 'boolean') {
|
||||||
// API returned 200 but result was not true or false
|
// API returned 200 but result was not true or false
|
||||||
|
|||||||
@ -175,7 +175,7 @@ function($scope, $rootScope, $routeParams, $location, Global, Transaction, Trans
|
|||||||
});
|
});
|
||||||
|
|
||||||
angular.module('insight.transactions').controller('SendRawTransactionController',
|
angular.module('insight.transactions').controller('SendRawTransactionController',
|
||||||
function($scope, $http) {
|
function($scope, $http, Api) {
|
||||||
$scope.transaction = '';
|
$scope.transaction = '';
|
||||||
$scope.status = 'ready'; // ready|loading|sent|error
|
$scope.status = 'ready'; // ready|loading|sent|error
|
||||||
$scope.txid = '';
|
$scope.txid = '';
|
||||||
@ -189,7 +189,7 @@ angular.module('insight.transactions').controller('SendRawTransactionController'
|
|||||||
rawtx: $scope.transaction
|
rawtx: $scope.transaction
|
||||||
};
|
};
|
||||||
$scope.status = 'loading';
|
$scope.status = 'loading';
|
||||||
$http.post(window.apiPrefix + '/tx/send', postData)
|
$http.post(Api.apiPrefix + '/tx/send', postData)
|
||||||
.success(function(data, status, headers, config) {
|
.success(function(data, status, headers, config) {
|
||||||
if(typeof(data.txid) != 'string') {
|
if(typeof(data.txid) != 'string') {
|
||||||
// API returned 200 but the format is not known
|
// API returned 200 but the format is not known
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('insight.address').factory('Address',
|
angular.module('insight.address').factory('Address',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/addr/:addrStr/?noTxList=1', {
|
return $resource(Api.apiPrefix + '/addr/:addrStr/?noTxList=1', {
|
||||||
addrStr: '@addStr'
|
addrStr: '@addStr'
|
||||||
}, {
|
}, {
|
||||||
get: {
|
get: {
|
||||||
|
|||||||
9
public/src/js/services/api.js
Normal file
9
public/src/js/services/api.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('insight.api')
|
||||||
|
.factory('Api',
|
||||||
|
function() {
|
||||||
|
return {
|
||||||
|
apiPrefix: '/insight-api'
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
angular.module('insight.blocks')
|
angular.module('insight.blocks')
|
||||||
.factory('Block',
|
.factory('Block',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/block/:blockHash', {
|
return $resource(Api.apiPrefix + '/block/:blockHash', {
|
||||||
blockHash: '@blockHash'
|
blockHash: '@blockHash'
|
||||||
}, {
|
}, {
|
||||||
get: {
|
get: {
|
||||||
@ -22,10 +22,10 @@ angular.module('insight.blocks')
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.factory('Blocks',
|
.factory('Blocks',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/blocks');
|
return $resource(Api.apiPrefix + '/blocks');
|
||||||
})
|
})
|
||||||
.factory('BlockByHeight',
|
.factory('BlockByHeight',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/block-index/:blockHeight');
|
return $resource(Api.apiPrefix + '/block-index/:blockHeight');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular.module('insight.currency').factory('Currency',
|
angular.module('insight.currency').factory('Currency',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/currency');
|
return $resource(Api.apiPrefix + '/currency');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,6 +7,6 @@ angular.module('insight.system')
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
.factory('Version',
|
.factory('Version',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/version');
|
return $resource(Api.apiPrefix + '/version');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
angular.module('insight.status')
|
angular.module('insight.status')
|
||||||
.factory('Status',
|
.factory('Status',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/status', {
|
return $resource(Api.apiPrefix + '/status', {
|
||||||
q: '@q'
|
q: '@q'
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.factory('Sync',
|
.factory('Sync',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/sync');
|
return $resource(Api.apiPrefix + '/sync');
|
||||||
})
|
})
|
||||||
.factory('PeerSync',
|
.factory('PeerSync',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/peer');
|
return $resource(Api.apiPrefix + '/peer');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
angular.module('insight.transactions')
|
angular.module('insight.transactions')
|
||||||
.factory('Transaction',
|
.factory('Transaction',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/tx/:txId', {
|
return $resource(Api.apiPrefix + '/tx/:txId', {
|
||||||
txId: '@txId'
|
txId: '@txId'
|
||||||
}, {
|
}, {
|
||||||
get: {
|
get: {
|
||||||
@ -22,18 +22,18 @@ angular.module('insight.transactions')
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.factory('TransactionsByBlock',
|
.factory('TransactionsByBlock',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/txs', {
|
return $resource(Api.apiPrefix + '/txs', {
|
||||||
block: '@block'
|
block: '@block'
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.factory('TransactionsByAddress',
|
.factory('TransactionsByAddress',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/txs', {
|
return $resource(Api.apiPrefix + '/txs', {
|
||||||
address: '@address'
|
address: '@address'
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.factory('Transactions',
|
.factory('Transactions',
|
||||||
function($resource) {
|
function($resource, Api) {
|
||||||
return $resource(window.apiPrefix + '/txs');
|
return $resource(Api.apiPrefix + '/txs');
|
||||||
});
|
});
|
||||||
|
|||||||
9
public/src/templates/api.js
Normal file
9
public/src/templates/api.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular.module('insight.api')
|
||||||
|
.factory('Api',
|
||||||
|
function() {
|
||||||
|
return {
|
||||||
|
apiPrefix: '/INSIGHT_API_PREFIX'
|
||||||
|
}
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user