webgui: moved events controller to events service

This commit is contained in:
Sergey Mishin 2015-06-14 17:17:48 +03:00
parent 6a6593c656
commit 2449f1e1b6
5 changed files with 127 additions and 95 deletions

View File

@ -23,8 +23,6 @@
</head>
<body>
<div ng-controller="EventController"></div>
<!-- Top bar -->
<nav class="navbar navbar-top navbar-default" role="navigation">
@ -1118,7 +1116,7 @@
<!-- gui application code -->
<script src="scripts/syncthing/core/module.js"></script>
<script src="scripts/syncthing/core/controllers/eventController.js"></script>
<script src="scripts/syncthing/core/services/events.js"></script>
<script src="scripts/syncthing/core/controllers/syncthingController.js"></script>
<script src="scripts/syncthing/core/directives/identiconDirective.js"></script>
<script src="scripts/syncthing/core/directives/languageSelectDirective.js"></script>

View File

@ -1,55 +0,0 @@
var debugEvents = false;
angular.module('syncthing.core')
.controller('EventController', function ($scope, $http) {
'use strict';
$scope.lastEvent = null;
var lastID = 0;
var successFn = function (data) {
// When Syncthing restarts while the long polling connection is in
// progress the browser on some platforms returns a 200 (since the
// headers has been flushed with the return code 200), with no data.
// This basically means that the connection has been reset, and the call
// was not actually successful.
if (!data) {
errorFn(data);
return;
}
$scope.$emit('UIOnline');
if (lastID > 0) {
data.forEach(function (event) {
if (debugEvents) {
console.log("event", event.id, event.type, event.data);
}
$scope.$emit(event.type, event);
});
}
$scope.lastEvent = data[data.length - 1];
lastID = $scope.lastEvent.id;
setTimeout(function () {
$http.get(urlbase + '/events?since=' + lastID)
.success(successFn)
.error(errorFn);
}, 500);
};
var errorFn = function (data) {
$scope.$emit('UIOffline');
setTimeout(function () {
$http.get(urlbase + '/events?limit=1')
.success(successFn)
.error(errorFn);
}, 1000);
};
$http.get(urlbase + '/events?limit=1')
.success(successFn)
.error(errorFn);
});

View File

@ -2,7 +2,7 @@ angular.module('syncthing.core')
.config(function($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
})
.controller('SyncthingController', function ($scope, $http, $location, LocaleService) {
.controller('SyncthingController', function ($scope, $http, $location, LocaleService, Events) {
'use strict';
// private/helper definitions
@ -15,6 +15,7 @@ angular.module('syncthing.core')
function initController() {
LocaleService.autoConfigLocale();
setInterval($scope.refresh, 10000);
Events.start();
}
@ -66,7 +67,7 @@ angular.module('syncthing.core')
'touch': 'asterisk'
};
$scope.$on('UIOnline', function (event, arg) {
$scope.$on(Events.ONLINE, function () {
if (online && !restarting) {
return;
}
@ -100,7 +101,7 @@ angular.module('syncthing.core')
$('#shutdown').modal('hide');
});
$scope.$on('UIOffline', function (event, arg) {
$scope.$on(Events.OFFLINE, function () {
if (navigatingAway || !online) {
return;
}
@ -125,7 +126,7 @@ angular.module('syncthing.core')
if (!restarting) {
if (arg.status === 0) {
// A network error, not an HTTP error
$scope.$emit('UIOffline');
$scope.$emit(Events.OFFLINE);
} else if (arg.status >= 400 && arg.status <= 599) {
// A genuine HTTP error
$('#networkError').modal('hide');
@ -136,7 +137,7 @@ angular.module('syncthing.core')
}
});
$scope.$on('StateChanged', function (event, arg) {
$scope.$on(Events.STATE_CHANGED, function (event, arg) {
var data = arg.data;
if ($scope.model[data.folder]) {
$scope.model[data.folder].state = data.to;
@ -144,21 +145,24 @@ angular.module('syncthing.core')
}
});
$scope.$on('LocalIndexUpdated', function (event, arg) {
var data = arg.data;
$scope.$on(Events.LOCAL_INDEX_UPDATED, function (event, arg) {
refreshFolderStats();
});
$scope.$on('RemoteIndexUpdated', function (event, arg) {
/* currently not using
$scope.$on('Events.REMOTE_INDEX_UPDATED', function (event, arg) {
// Nothing
});
$scope.$on('DeviceDisconnected', function (event, arg) {
*/
$scope.$on(Events.DEVICE_DISCONNECTED, function (event, arg) {
delete $scope.connections[arg.data.id];
refreshDeviceStats();
});
$scope.$on('DeviceConnected', function (event, arg) {
$scope.$on(Events.DEVICE_CONNECTED, function (event, arg) {
if (!$scope.connections[arg.data.id]) {
$scope.connections[arg.data.id] = {
inbps: 0,
@ -173,7 +177,7 @@ angular.module('syncthing.core')
}
});
$scope.$on('ConfigLoaded', function (event) {
$scope.$on('ConfigLoaded', function () {
if ($scope.config.options.urAccepted === 0) {
// If usage reporting has been neither accepted nor declined,
// we want to ask the user to make a choice. But we don't want
@ -193,15 +197,15 @@ angular.module('syncthing.core')
}
});
$scope.$on('DeviceRejected', function (event, arg) {
$scope.$on(Events.DEVICE_REJECTED, function (event, arg) {
$scope.deviceRejections[arg.data.device] = arg;
});
$scope.$on('FolderRejected', function (event, arg) {
$scope.$on(Events.FOLDER_REJECTED, function (event, arg) {
$scope.folderRejections[arg.data.folder + "-" + arg.data.device] = arg;
});
$scope.$on('ConfigSaved', function (event, arg) {
$scope.$on(Events.CONFIG_SAVED, function (event, arg) {
updateLocalConfig(arg.data);
$http.get(urlbase + '/system/config/insync').success(function (data) {
@ -209,7 +213,7 @@ angular.module('syncthing.core')
}).error($scope.emitHTTPError);
});
$scope.$on('DownloadProgress', function (event, arg) {
$scope.$on(Events.DOWNLOAD_PROGRESS, function (event, arg) {
var stats = arg.data;
var progress = {};
for (var folder in stats) {
@ -254,12 +258,12 @@ angular.module('syncthing.core')
console.log("DownloadProgress", $scope.progress);
});
$scope.$on('FolderSummary', function (event, arg) {
$scope.$on(Events.FOLDER_SUMMARY, function (event, arg) {
var data = arg.data;
$scope.model[data.folder] = data.summary;
});
$scope.$on('FolderCompletion', function (event, arg) {
$scope.$on(Events.FOLDER_COMPLETION, function (event, arg) {
var data = arg.data;
if (!$scope.completion[data.device]) {
$scope.completion[data.device] = {};
@ -444,7 +448,7 @@ angular.module('syncthing.core')
} else {
return 'sync';
}
};
}
function parseNeeded(data) {
var merged = [];
@ -475,7 +479,7 @@ angular.module('syncthing.core')
$scope.neededChangePageSize = function (perpage) {
$scope.neededPageSize = perpage;
refreshNeed($scope.neededFolder);
}
};
var refreshDeviceStats = debounce(function () {
$http.get(urlbase + "/stats/device").success(function (data) {
@ -973,7 +977,7 @@ angular.module('syncthing.core')
$scope.$watch('currentFolder.path', function (newvalue) {
if (newvalue && newvalue.trim().charAt(0) == '~') {
$scope.currentFolder.path = $scope.system.tilde + newvalue.trim().substring(1)
$scope.currentFolder.path = $scope.system.tilde + newvalue.trim().substring(1);
}
$http.get(urlbase + '/system/browse', {
params: { current: newvalue }
@ -1052,19 +1056,19 @@ angular.module('syncthing.core')
$scope.dismissFolderRejection(folder, device);
$scope.currentFolder = {
id: folder,
selectedDevices: {}
selectedDevices: {},
rescanIntervalS: 60,
fileVersioningSelector: "none",
trashcanClean: 0,
simpleKeep: 5,
staggeredMaxAge: 365,
staggeredCleanInterval: 3600,
staggeredVersionsPath: "",
externalCommand: "",
autoNormalize: true
};
$scope.currentFolder.selectedDevices[device] = true;
$scope.currentFolder.rescanIntervalS = 60;
$scope.currentFolder.fileVersioningSelector = "none";
$scope.currentFolder.trashcanClean = 0;
$scope.currentFolder.simpleKeep = 5;
$scope.currentFolder.staggeredMaxAge = 365;
$scope.currentFolder.staggeredCleanInterval = 3600;
$scope.currentFolder.staggeredVersionsPath = "";
$scope.currentFolder.externalCommand = "";
$scope.currentFolder.autoNormalize = true;
$scope.editingExisting = false;
$scope.folderEditor.$setPristine();
$('#editFolder').modal();
@ -1159,12 +1163,12 @@ angular.module('syncthing.core')
});
names.sort();
return names.join(", ");
}
};
$scope.deviceFolders = function (deviceCfg) {
var folders = [];
for (var folderID in $scope.folders) {
var devices = $scope.folders[folderID].devices
var devices = $scope.folders[folderID].devices;
for (var i = 0; i < devices.length; i++) {
if (devices[i].deviceID == deviceCfg.deviceID) {
folders.push(folderID);

View File

@ -0,0 +1,85 @@
var debugEvents = !true;
angular.module('syncthing.core')
.service('Events', ['$http', '$rootScope', '$timeout', function ($http, $rootScope, $timeout) {
'use strict';
var lastID = 0;
var self = this;
function successFn (data) {
// When Syncthing restarts while the long polling connection is in
// progress the browser on some platforms returns a 200 (since the
// headers has been flushed with the return code 200), with no data.
// This basically means that the connection has been reset, and the call
// was not actually successful.
if (!data) {
errorFn(data);
return;
}
$rootScope.$broadcast(self.ONLINE);
if (lastID > 0) { // not emit events from first response
data.forEach(function (event) {
if (debugEvents) {
console.log("event", event.id, event.type, event.data);
}
$rootScope.$broadcast(event.type, event);
});
}
var lastEvent = data.pop();
if (lastEvent) {
lastID = lastEvent.id;
}
$timeout(function () {
$http.get(urlbase + '/events?since=' + lastID)
.success(successFn)
.error(errorFn);
}, 500, false);
}
function errorFn (dummy) {
$rootScope.$broadcast(self.OFFLINE);
$timeout(function () {
$http.get(urlbase + '/events?limit=1')
.success(successFn)
.error(errorFn);
}, 1000, false);
}
angular.extend(self, {
// emitted by this
ONLINE: 'UIOnline',
OFFLINE: 'UIOffline',
// emitted by syncthing process
CONFIG_SAVED: 'ConfigSaved', // Emitted after the config has been saved by the user or by Syncthing itself
DEVICE_CONNECTED: 'DeviceConnected', // Generated each time a connection to a device has been established
DEVICE_DISCONNECTED: 'DeviceDisconnected', // Generated each time a connection to a device has been terminated
DEVICE_DISCOVERED: 'DeviceDiscovered', // Emitted when a new device is discovered using local discovery
DEVICE_REJECTED: 'DeviceRejected', // Emitted when there is a connection from a device we are not configured to talk to
DOWNLOAD_PROGRESS: 'DownloadProgress', // Emitted during file downloads for each folder for each file
FOLDER_COMPLETION: 'FolderCompletion', //Emitted when the local or remote contents for a folder changes
FOLDER_REJECTED: 'FolderRejected', // Emitted when a device sends index information for a folder we do not have, or have but do not share with the device in question
FOLDER_SUMMARY: 'FolderSummary', // Emitted when folder contents have changed locally
ITEM_FINISHED: 'ItemFinished', // Generated when Syncthing ends synchronizing a file to a newer version
ITEM_STARTED: 'ItemStarted', // Generated when Syncthing begins synchronizing a file to a newer version
LOCAL_INDEX_UPDATED: 'LocalIndexUpdated', // Generated when the local index information has changed, due to synchronizing one or more items from the cluster or discovering local changes during a scan
PING: 'Ping', // Generated automatically every 60 seconds
REMOTE_INDEX_UPDATED: 'RemoteIndexUpdated', // Generated each time new index information is received from a device
STARTING: 'Starting', // Emitted exactly once, when Syncthing starts, before parsing configuration etc
STARTUP_COMPLETED: 'StartupCompleted', // Emitted exactly once, when initialization is complete and Syncthing is ready to start exchanging data with other devices
STATE_CHANGED: 'StateChanged', // Emitted when a folder changes state
start: function() {
$http.get(urlbase + '/events?limit=1')
.success(successFn)
.error(errorFn);
}
});
}]);

File diff suppressed because one or more lines are too long