Introduce uiSettings DB

This commit is contained in:
John Furrow
2016-01-30 20:21:42 -08:00
parent 750850584f
commit 86e8becde3
24 changed files with 353 additions and 117 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,6 @@
.DS_Store
node_modules
npm-debug.log
server/db/uiSettings.db
server/db/users.js
server/db/history

View File

@@ -5,6 +5,12 @@ import ActionTypes from '../constants/ActionTypes';
const TorrentActions = {
addTorrents: function(urls, destination) {
axios.post('/ui/torrent-location', {
destination
})
.catch(function (error) {
console.log(error);
});
return axios.post('/client/add', {
urls,
destination
@@ -30,6 +36,25 @@ const TorrentActions = {
});
},
fetchLatestTorrentLocation: function () {
return axios.get('/ui/torrent-location')
.then((json = {}) => {
return json.data;
})
.then((data) => {
AppDispatcher.dispatchServerAction({
type: ActionTypes.UI_LATEST_TORRENT_LOCATION_REQUEST_SUCCESS,
data
});
})
.catch((error) => {
AppDispatcher.dispatchServerAction({
type: ActionTypes.UI_LATEST_TORRENT_LOCATION_REQUEST_ERROR,
error
});
});
},
fetchTorrents: function () {
return axios.get('/client/list')
.then((json = {}) => {

View File

@@ -1,3 +1,5 @@
import axios from 'axios';
import AppDispatcher from '../dispatcher/AppDispatcher';
import ActionTypes from '../constants/ActionTypes';
@@ -16,6 +18,25 @@ const UIActions = {
});
},
fetchSortProps: function() {
return axios.get('/ui/sort-props')
.then((json = {}) => {
return json.data;
})
.then((data) => {
AppDispatcher.dispatchServerAction({
type: ActionTypes.UI_SORT_PROPS_REQUEST_SUCCESS,
data
});
})
.catch((error) => {
AppDispatcher.dispatchServerAction({
type: ActionTypes.UI_SORT_PROPS_REQUEST_ERROR,
error
});
});
},
handleDetailsClick: function(data) {
AppDispatcher.dispatchUIAction({
type: ActionTypes.UI_CLICK_TORRENT_DETAILS,
@@ -45,6 +66,12 @@ const UIActions = {
},
setTorrentsSort: function(data) {
axios
.post('/ui/sort-props', data)
.catch(function (error) {
console.log(error);
});
AppDispatcher.dispatchUIAction({
type: ActionTypes.UI_SET_TORRENT_SORT,
data

View File

@@ -7,8 +7,13 @@ import Modals from './components/modals/Modals';
import Sidebar from './components/panels/Sidebar';
import TorrentListView from './components/panels/TorrentListView';
import TorrentDetailsView from './components/panels/TorrentDetailsView';
import TorrentActions from './actions/TorrentActions';
class FloodApp extends React.Component {
componentDidMount() {
TorrentActions.fetchLatestTorrentLocation();
}
render() {
return (
<Application>

View File

@@ -2,8 +2,10 @@ import _ from 'lodash';
import classnames from 'classnames';
import React from 'react';
import EventTypes from '../../constants/EventTypes';
import TextboxRepeater from '../forms/TextboxRepeater';
import TorrentActions from '../../actions/TorrentActions';
import UIStore from '../../stores/UIStore';
const METHODS_TO_BIND = [
'getContent',
@@ -11,7 +13,8 @@ const METHODS_TO_BIND = [
'handleUrlAdd',
'handleUrlChange',
'handleUrlRemove',
'handleAddTorrents'
'handleAddTorrents',
'onLatestTorrentLocationChange'
];
export default class AddTorrents extends React.Component {
@@ -29,6 +32,23 @@ export default class AddTorrents extends React.Component {
});
}
componentWillMount() {
this.setState({destination: UIStore.getLatestTorrentLocation()});
}
componentDidMount() {
UIStore.listen(EventTypes.UI_LATEST_TORRENT_LOCATION_CHANGE, this.onLatestTorrentLocationChange);
}
componentWillUnmount() {
UIStore.unlisten(EventTypes.UI_LATEST_TORRENT_LOCATION_CHANGE, this.onLatestTorrentLocationChange);
UIStore.fetchLatestTorrentLocation();
}
onLatestTorrentLocationChange() {
this.setState({destination: UIStore.getLatestTorrentLocation()});
}
getContent() {
return (
<div className="modal__content" onClick={this.handleMenuWrapperClick}>

View File

@@ -1,12 +1,12 @@
import React from 'react';
import ClientActions from '../../actions/ClientActions';
import ClientDataStore from '../../stores/ClientDataStore';
import Dropdown from '../forms/Dropdown';
import EventTypes from '../../constants/EventTypes';
import format from '../../util/formatData';
import Limits from '../icons/Limits';
import SidebarItem from '../sidebar/SidebarItem';
import TransferDataStore from '../../stores/TransferDataStore';
const METHODS_TO_BIND = ['onTransferDataRequestSuccess'];
const SPEEDS = [1024, 10240, 102400, 512000, 1048576, 2097152, 5242880, 10485760, 0];
@@ -25,15 +25,15 @@ class Sidebar extends React.Component {
}
componentDidMount() {
ClientDataStore.listen(
TransferDataStore.listen(
EventTypes.CLIENT_TRANSFER_DATA_REQUEST_SUCCESS,
this.onTransferDataRequestSuccess
);
ClientDataStore.fetchTransferData();
TransferDataStore.fetchTransferData();
}
componentWillUnmount() {
ClientDataStore.unlisten(
TransferDataStore.unlisten(
EventTypes.CLIENT_TRANSFER_DATA_REQUEST_SUCCESS,
this.onTransferDataRequestSuccess
);
@@ -41,7 +41,7 @@ class Sidebar extends React.Component {
onTransferDataRequestSuccess() {
this.setState({
throttle: ClientDataStore.getThrottles({latest: true})
throttle: TransferDataStore.getThrottles({latest: true})
});
}

View File

@@ -1,16 +1,18 @@
import React from 'react';
import ReactDOM from 'react-dom';
import ClientDataStore from '../../stores/ClientDataStore';
import Download from '../icons/Download';
import EventTypes from '../../constants/EventTypes';
import format from '../../util/formatData';
import LineChart from '../ui/LineChart';
import LoadingIndicator from '../ui/LoadingIndicator';
import TransferDataStore from '../../stores/TransferDataStore';
import Upload from '../icons/Upload';
const METHODS_TO_BIND = [
'onTransferDataRequestError',
'onTransferDataRequestSuccess'
'onTransferDataRequestSuccess',
'onTransferHistoryRequestSuccess'
];
class ClientStats extends React.Component {
@@ -19,6 +21,7 @@ class ClientStats extends React.Component {
this.state = {
sidebarWidth: 0,
transferHistoryRequestSuccess: false,
transferDataRequestError: false,
transferDataRequestSuccess: false
};
@@ -32,20 +35,25 @@ class ClientStats extends React.Component {
this.setState({
sidebarWidth: ReactDOM.findDOMNode(this).offsetWidth
});
ClientDataStore.listen(
EventTypes.CLIENT_TRANSFER_DATA_REQUEST_SUCCESS,
this.onTransferDataRequestSuccess
);
ClientDataStore.fetchTransferData();
TransferDataStore.listen(EventTypes.CLIENT_TRANSFER_DATA_REQUEST_SUCCESS,
this.onTransferDataRequestSuccess);
TransferDataStore.listen(EventTypes.CLIENT_TRANSFER_HISTORY_REQUEST_SUCCESS,
this.onTransferHistoryRequestSuccess);
TransferDataStore.fetchTransferData();
}
componentWillUnmount() {
ClientDataStore.unlisten(
TransferDataStore.unlisten(
EventTypes.CLIENT_TRANSFER_DATA_REQUEST_SUCCESS,
this.onTransferDataRequestSuccess
);
}
isLoading() {
return !this.state.transferHistoryRequestSuccess ||
!this.state.transferDataRequestSuccess;
}
onTransferDataRequestError() {
this.setState({
transferDataRequestError: true,
@@ -60,17 +68,25 @@ class ClientStats extends React.Component {
});
}
onTransferHistoryRequestSuccess() {
if (!this.state.transferHistoryRequestSuccess) {
this.setState({
transferHistoryRequestSuccess: true
});
}
}
render() {
if (this.state.transferDataRequestError) {
return <div>Error</div>;
} else if (!this.state.transferDataRequestSuccess) {
return <div>Loading</div>;
} else if (this.isLoading()) {
return <LoadingIndicator />;
}
let throttles = ClientDataStore.getThrottles();
let transferRate = ClientDataStore.getTransferRate();
let transferRates = ClientDataStore.getTransferRates();
let transferTotals = ClientDataStore.getTransferTotals();
let throttles = TransferDataStore.getThrottles();
let transferRate = TransferDataStore.getTransferRate();
let transferRates = TransferDataStore.getTransferRates();
let transferTotals = TransferDataStore.getTransferTotals();
let downloadRate = format.data(transferRate.download, '/s');
let downloadTotal = format.data(transferTotals.download);

View File

@@ -34,6 +34,7 @@ export default class ActionBar extends React.Component {
}
componentDidMount() {
TorrentFilterStore.fetchSortProps();
TorrentFilterStore.listen(EventTypes.UI_TORRENTS_SORT_CHANGE, this.onSortChange);
}

View File

@@ -41,16 +41,18 @@ export default class LineChart extends React.Component {
})
]);
let lineFunc = d3
.svg
.line()
.x(function(dataPoint, index) {
return xRange(index);
})
.y(function(dataPoint) {
return yRange(dataPoint);
})
.interpolate('basis');
let lineFunc = function (interpolation) {
return d3
.svg
.line()
.x(function(dataPoint, index) {
return xRange(index);
})
.y(function(dataPoint) {
return yRange(dataPoint);
})
.interpolate(interpolation);
}
let areaFunc = d3
.svg
@@ -64,8 +66,8 @@ export default class LineChart extends React.Component {
})
.interpolate('basis');
let transferDataLinePoints = lineFunc(transferData);
let transferLimitLinePoints = lineFunc(transferLimit);
let transferDataLinePoints = lineFunc('basis')(transferData);
let transferLimitLinePoints = lineFunc('step-after')(transferLimit);
let transferDataAreaPoints = areaFunc(transferData);
graph

View File

@@ -18,9 +18,13 @@ const ActionTypes = {
UI_CLICK_TORRENT: 'UI_CLICK_TORRENT',
UI_CLICK_TORRENT_DETAILS: 'UI_CLICK_TORRENT_DETAILS',
UI_DISPLAY_MODAL: 'UI_DISPLAY_MODAL',
UI_LATEST_TORRENT_LOCATION_REQUEST_ERROR: 'UI_LATEST_TORRENT_LOCATION_REQUEST_ERROR',
UI_LATEST_TORRENT_LOCATION_REQUEST_SUCCESS: 'UI_LATEST_TORRENT_LOCATION_REQUEST_SUCCESS',
UI_SET_TORRENT_SEARCH_FILTER: 'UI_SET_TORRENT_SEARCH_FILTER',
UI_SET_TORRENT_SORT: 'UI_SET_TORRENT_SORT',
UI_SET_TORRENT_STATUS_FILTER: 'UI_SET_TORRENT_STATUS_FILTER'
UI_SET_TORRENT_STATUS_FILTER: 'UI_SET_TORRENT_STATUS_FILTER',
UI_SORT_PROPS_REQUEST_SUCCESS: 'UI_SORT_PROPS_REQUEST_SUCCESS',
UI_SORT_PROPS_REQUEST_ERROR: 'UI_SORT_PROPS_REQUEST_ERROR'
};
export default ActionTypes;

View File

@@ -8,6 +8,7 @@ const EventTypes = {
CLIENT_TRANSFER_DATA_REQUEST_ERROR: 'CLIENT_TRANSFER_DATA_REQUEST_ERROR',
CLIENT_TRANSFER_HISTORY_REQUEST_SUCCESS: 'CLIENT_TRANSFER_HISTORY_REQUEST_SUCCESS',
UI_MODAL_CHANGE: 'UI_MODAL_CHANGE',
UI_LATEST_TORRENT_LOCATION_CHANGE: 'UI_LATEST_TORRENT_LOCATION_CHANGE',
UI_TORRENT_DETAILS_HASH_CHANGE: 'UI_TORRENT_DETAILS_HASH_CHANGE',
UI_TORRENT_DETAILS_OPEN_CHANGE: 'UI_TORRENT_DETAILS_OPEN_CHANGE',
UI_TORRENT_SELECTION_CHANGE: 'UI_TORRENT_SELECTION_CHANGE',

View File

@@ -1,8 +1,9 @@
import ActionTypes from '../constants/ActionTypes';
import AppDispatcher from '../dispatcher/AppDispatcher';
import BaseStore from './BaseStore';
import TorrentActions from '../actions/TorrentActions';
import EventTypes from '../constants/EventTypes';
import TorrentActions from '../actions/TorrentActions';
import UIActions from '../actions/UIActions';
class TorrentFilterStoreClass extends BaseStore {
constructor() {
@@ -18,26 +19,34 @@ class TorrentFilterStoreClass extends BaseStore {
};
}
getStatusFilter() {
return this.statusFilter;
}
setStatusFilter(filter) {
this.statusFilter = filter;
this.emit(EventTypes.UI_TORRENTS_FILTER_STATUS_CHANGE);
fetchSortProps() {
UIActions.fetchSortProps();
}
getSearchFilter() {
return this.searchFilter;
}
getStatusFilter() {
return this.statusFilter;
}
getTorrentsSort() {
return this.sortTorrentsBy;
}
handleSortPropsRequestSuccess(sortBy) {
this.setTorrentsSort(sortBy);
}
setSearchFilter(filter) {
this.searchFilter = filter;
this.emit(EventTypes.UI_TORRENTS_FILTER_SEARCH_CHANGE);
}
getTorrentsSort() {
return this.sortTorrentsBy;
setStatusFilter(filter) {
this.statusFilter = filter;
this.emit(EventTypes.UI_TORRENTS_FILTER_STATUS_CHANGE);
}
setTorrentsSort(sortBy) {
@@ -61,6 +70,9 @@ AppDispatcher.register((payload) => {
case ActionTypes.UI_SET_TORRENT_SORT:
TorrentFilterStore.setTorrentsSort(action.data);
break;
case ActionTypes.UI_SORT_PROPS_REQUEST_SUCCESS:
TorrentFilterStore.handleSortPropsRequestSuccess(action.data);
break;
}
});

View File

@@ -5,7 +5,7 @@ import ClientActions from '../actions/ClientActions';
import config from '../../../../config';
import EventTypes from '../constants/EventTypes';
class ClientDataStoreClass extends BaseStore {
class TransferDataStoreClass extends BaseStore {
constructor() {
super();
@@ -126,43 +126,33 @@ class ClientDataStoreClass extends BaseStore {
config.pollInterval
);
}
startPollingTorrents() {
clearInterval(this.pollTransferDataID);
this.pollTransferDataID = null;
}
stopPollingTorrentDetails() {
clearInterval(this.pollTorrentDetailsIntervalID);
this.isPollingTorrents = false;
}
}
const ClientDataStore = new ClientDataStoreClass();
const TransferDataStore = new TransferDataStoreClass();
AppDispatcher.register((payload) => {
const {action, source} = payload;
switch (action.type) {
case ActionTypes.CLIENT_FETCH_TRANSFER_DATA_SUCCESS:
ClientDataStore.handleTransferDataSuccess(action.data.transferData);
TransferDataStore.handleTransferDataSuccess(action.data.transferData);
break;
case ActionTypes.CLIENT_FETCH_TRANSFER_DATA_ERROR:
ClientDataStore.handleTransferDataError(action.data.error);
TransferDataStore.handleTransferDataError(action.data.error);
break;
case ActionTypes.CLIENT_SET_THROTTLE_SUCCESS:
ClientDataStore.handleSetThrottleSuccess(action.data.transferData);
TransferDataStore.handleSetThrottleSuccess(action.data.transferData);
break;
case ActionTypes.CLIENT_SET_THROTTLE_ERROR:
ClientDataStore.handleSetThrottleError(action.data.error);
TransferDataStore.handleSetThrottleError(action.data.error);
break;
case ActionTypes.CLIENT_FETCH_TRANSFER_HISTORY_ERROR:
ClientDataStore.handleTransferHistoryError(action.error);
TransferDataStore.handleTransferHistoryError(action.error);
break;
case ActionTypes.CLIENT_FETCH_TRANSFER_HISTORY_SUCCESS:
ClientDataStore.handleTransferHistorySuccess(action.data);
TransferDataStore.handleTransferHistorySuccess(action.data);
break;
}
});
export default ClientDataStore;
export default TransferDataStore;

View File

@@ -10,6 +10,7 @@ class UIStoreClass extends BaseStore {
super();
this.activeModal = null;
this.latestTorrentLocation = null;
this.torrentDetailsHash = null;
this.torrentDetailsOpen = false;
}
@@ -21,19 +22,31 @@ class UIStoreClass extends BaseStore {
}
}
fetchLatestTorrentLocation() {
TorrentActions.fetchLatestTorrentLocation();
}
getActiveModal() {
return this.activeModal;
}
setActiveModal(modal) {
this.activeModal = modal;
this.emit(EventTypes.UI_MODAL_CHANGE);
getLatestTorrentLocation() {
return this.latestTorrentLocation;
}
getTorrentDetailsHash() {
return this.torrentDetailsHash;
}
handleLatestTorrentLocationRequestSuccess(location) {
this.latestTorrentLocation = location;
this.emit(EventTypes.UI_LATEST_TORRENT_LOCATION_CHANGE);
}
handleLatestTorrentLocationRequestError(error) {
console.log(error);
}
handleTorrentClick(hash) {
this.torrentDetailsHash = hash;
this.emit(EventTypes.UI_TORRENT_DETAILS_HASH_CHANGE);
@@ -47,6 +60,11 @@ class UIStoreClass extends BaseStore {
isTorrentDetailsOpen() {
return this.torrentDetailsOpen;
}
setActiveModal(modal) {
this.activeModal = modal;
this.emit(EventTypes.UI_MODAL_CHANGE);
}
}
const UIStore = new UIStoreClass();
@@ -64,6 +82,12 @@ AppDispatcher.register((payload) => {
case ActionTypes.UI_DISPLAY_MODAL:
UIStore.setActiveModal(action.data);
break;
case ActionTypes.UI_LATEST_TORRENT_LOCATION_REQUEST_SUCCESS:
UIStore.handleLatestTorrentLocationRequestSuccess(action.data.path);
break;
case ActionTypes.UI_LATEST_TORRENT_LOCATION_REQUEST_ERROR:
UIStore.handleLatestTorrentLocationRequestError(action.error);
break;
}
});

View File

@@ -1,6 +1,8 @@
const config = {
databasePath: './server/db/',
maxHistoryStates: 30,
pollInterval: 5000
pollInterval: 5000,
uiDatabaseCleanInterval: 1000 * 60 * 60 // 1 hour
};
module.exports = config;

View File

@@ -5,7 +5,8 @@ var favicon = require('serve-favicon');
var logger = require('morgan');
var path = require('path');
var client = require('./routes/client');
var clientRoutes = require('./routes/client');
var uiRoutes = require('./routes/ui');
var routes = require('./routes/index');
var app = express();
@@ -33,7 +34,8 @@ app.use(function(req, res, next) {
});
app.use('/', routes);
app.use('/client', client);
app.use('/client', clientRoutes);
app.use('/ui', uiRoutes);
// catch 404 and forward to error handler
app.use(function(req, res, next) {

File diff suppressed because one or more lines are too long

View File

@@ -2,9 +2,9 @@
let Datastore = require('nedb');
let config = require('../../config');
let stringUtil = require('./util/stringUtil');
const FILE_PATH = './server/db/history/';
const MAX_CLEANUP_INTERVAL = 1000 * 60 * 60; // 1 hour
const MAX_NEXT_ERA_UPDATE_INTERVAL = 1000 * 60 * 60 * 12; // 12 hours
const CUMULATIVE_DATA_BUFFER = 1000 * 2;
@@ -92,7 +92,8 @@ class HistoryEra {
getData(opts, callback) {
let minTimestamp = Date.now() - this.opts.maxTime;
this.db.find({ts: {$gte: minTimestamp}}).sort({ts: 1})
this.db.find({ts: {$gte: minTimestamp}})
.sort({ts: 1})
.exec(function (err, docs) {
callback(err, docs);
}
@@ -104,7 +105,7 @@ class HistoryEra {
REQUIRED_FIELDS.forEach(function (field) {
if (opts[field] == null) {
console.warn(`historyEra requires ${field}`);
console.warn(`HistoryEra requires ${field}`);
requirementsMet = false;
}
});
@@ -115,7 +116,7 @@ class HistoryEra {
loadDatabase(dbName) {
let db = new Datastore({
autoload: true,
filename: `${FILE_PATH}${dbName}.db`
filename: `${config.databasePath}history/${dbName}.db`
});
this.ready = true;

View File

@@ -1,5 +1,4 @@
'use strict';
var Datastore = require('nedb');
var client = require('./client');
var config = require('../../config');

View File

@@ -4,11 +4,9 @@ var Deserializer = require('./util/deserializer');
var Serializer = require('./util/serializer');
var rtorrent = {
initialized: false,
get: function(api, array) {
var stream = net.connect({
port: 5000,
host: 'localhost'
@@ -62,7 +60,6 @@ var rtorrent = {
return deferred.promise;
}
}
module.exports = rtorrent;

View File

@@ -0,0 +1,70 @@
'use strict';
let Datastore = require('nedb');
let config = require('../../config');
let uiDB = new Datastore({
autoload: true,
filename: `${config.databasePath}uiSettings.db`
});
uiDB.persistence.setAutocompactionInterval(config.uiDatabaseCleanInterval);
let uiSettings = {
getLatestTorrentLocation: function(callback) {
uiDB.find({type: 'location'}, function(error, docs) {
if (error) {
callback(error);
return;
}
if (docs.length) {
callback(error, docs[0]);
}
});
},
getSortProps: function(callback) {
uiDB.find({type: 'sort'}, function(error, docs) {
if (error) {
callback(error);
return;
}
if (docs.length) {
callback(error, docs[0]);
}
});
},
setLatestTorrentLocation: function(data, callback) {
let newLocationData = Object.assign({}, {type: 'location'}, {path: data.destination});
uiDB.update({type: 'location'}, newLocationData, {upsert: true}, function (error, docs) {
if (error) {
callback(error);
return;
}
if (docs.length) {
callback(error, docs);
}
});
},
setSortProps: function(sortProps, callback) {
let newSortPropData = Object.assign({}, {type: 'sort'}, sortProps);
uiDB.update({type: 'sort'}, newSortPropData, {upsert: true}, function (error, docs) {
if (error) {
callback(error);
return;
}
if (docs.length) {
callback(error, docs);
}
});
}
}
module.exports = uiSettings;

View File

@@ -1,52 +1,46 @@
var express = require('express');
var router = express.Router();
var xmlrpc = require('xmlrpc');
'use strict';
var client = require('../models/client');
var history = require('../models/history');
let express = require('express');
let router = express.Router();
let xmlrpc = require('xmlrpc');
var handleClientResponse = function (res) {
return function (error, response) {
if (error) {
console.log(error);
}
res.json(response);
}
}
let ajaxUtil = require('../util/ajaxUtil');
let client = require('../models/client');
let history = require('../models/history');
router.post('/add', function(req, res, next) {
client.add(req.body, handleClientResponse(res));
client.add(req.body, ajaxUtil.getResponseFn(res));
});
router.get('/history', function(req, res, next) {
history.get(req.query, handleClientResponse(res));
history.get(req.query, ajaxUtil.getResponseFn(res));
});
router.get('/list', function(req, res, next) {
client.getTorrentList(handleClientResponse(res));
client.getTorrentList(ajaxUtil.getResponseFn(res));
});
router.put('/settings/speed-limits', function(req, res, next) {
client.setSpeedLimits(req.body, handleClientResponse(res));
client.setSpeedLimits(req.body, ajaxUtil.getResponseFn(res));
});
router.post('/start', function(req, res, next) {
var hashes = req.body.hashes;
client.startTorrent(hashes, handleClientResponse(res));
client.startTorrent(hashes, ajaxUtil.getResponseFn(res));
});
router.get('/stats', function(req, res, next) {
client.getTransferStats(handleClientResponse(res));
client.getTransferStats(ajaxUtil.getResponseFn(res));
});
router.post('/stop', function(req, res, next) {
var hashes = req.body.hashes;
client.stopTorrent(hashes, handleClientResponse(res));
client.stopTorrent(hashes, ajaxUtil.getResponseFn(res));
});
router.post('/torrent-details', function(req, res, next) {
var hash = req.body.hash;
client.getTorrentDetails(hash, handleClientResponse(res));
client.getTorrentDetails(hash, ajaxUtil.getResponseFn(res));
});
router.get('/methods.json', function(req, res, next) {
@@ -60,7 +54,7 @@ router.get('/methods.json', function(req, res, next) {
method = 'system.methodSignature';
}
client.listMethods(method, args, handleClientResponse(res));
client.listMethods(method, args, ajaxUtil.getResponseFn(res));
});
module.exports = router;

28
server/routes/ui.js Normal file
View File

@@ -0,0 +1,28 @@
'use strict';
let express = require('express');
let router = express.Router();
let xmlrpc = require('xmlrpc');
let ajaxUtil = require('../util/ajaxUtil');
let client = require('../models/client');
let history = require('../models/history');
let uiSettings = require('../models/uiSettings');
router.post('/sort-props', function(req, res, next) {
uiSettings.setSortProps(req.body, ajaxUtil.getResponseFn(res));
});
router.get('/sort-props', function(req, res, next) {
uiSettings.getSortProps(ajaxUtil.getResponseFn(res));
});
router.get('/torrent-location', function(req, res, next) {
uiSettings.getLatestTorrentLocation(ajaxUtil.getResponseFn(res));
});
router.post('/torrent-location', function(req, res, next) {
uiSettings.setLatestTorrentLocation(req.body, ajaxUtil.getResponseFn(res));
});
module.exports = router;

14
server/util/ajaxUtil.js Normal file
View File

@@ -0,0 +1,14 @@
'use strict';
let ajaxUtil = {
getResponseFn: function (res) {
return function (error, response) {
if (error) {
console.log('error in getResponseFn', error);
}
res.json(response);
}
}
};
module.exports = ajaxUtil;