mirror of
https://github.com/openstf/stf
synced 2025-10-04 10:19:30 +02:00
Save user settings to the database and embed them to the template for fast access.
This commit is contained in:
parent
332c7b6106
commit
e13fc6701f
11 changed files with 152 additions and 141 deletions
|
@ -13,7 +13,6 @@
|
||||||
"oboe": "~1.15.1",
|
"oboe": "~1.15.1",
|
||||||
"fa-borderlayout": "~0.3.1-beta2",
|
"fa-borderlayout": "~0.3.1-beta2",
|
||||||
"Snap.svg": "~0.3.0",
|
"Snap.svg": "~0.3.0",
|
||||||
"angular-localForage": "~0.2.6",
|
|
||||||
"ng-table": "git://github.com/esvit/ng-table.git#bd9ec42172389257fcd312330013302b2696ac2a",
|
"ng-table": "git://github.com/esvit/ng-table.git#bd9ec42172389257fcd312330013302b2696ac2a",
|
||||||
"jquery.terminal": "~0.8.7",
|
"jquery.terminal": "~0.8.7",
|
||||||
"stf-site": "~0.4.1",
|
"stf-site": "~0.4.1",
|
||||||
|
|
|
@ -25,6 +25,7 @@ dbapi.saveUserAfterLogin = function(user) {
|
||||||
, lastLoggedInAt: r.now()
|
, lastLoggedInAt: r.now()
|
||||||
, createdAt: r.now()
|
, createdAt: r.now()
|
||||||
, forwards: []
|
, forwards: []
|
||||||
|
, settings: {}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
return stats
|
return stats
|
||||||
|
@ -35,6 +36,18 @@ dbapi.loadUser = function(email) {
|
||||||
return db.run(r.table('users').get(email))
|
return db.run(r.table('users').get(email))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dbapi.updateUserSettings = function(email, changes) {
|
||||||
|
return db.run(r.table('users').get(email).update({
|
||||||
|
settings: changes
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
dbapi.resetUserSettings = function(email) {
|
||||||
|
return db.run(r.table('users').get(email).update({
|
||||||
|
settings: r.literal({})
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
dbapi.addUserForward = function(email, forward) {
|
dbapi.addUserForward = function(email, forward) {
|
||||||
var devicePort = forward.devicePort
|
var devicePort = forward.devicePort
|
||||||
return db.run(r.table('users').get(email).update({
|
return db.run(r.table('users').get(email).update({
|
||||||
|
|
|
@ -256,6 +256,13 @@ module.exports = function(options) {
|
||||||
|
|
||||||
new Promise(function(resolve) {
|
new Promise(function(resolve) {
|
||||||
socket.on('disconnect', resolve)
|
socket.on('disconnect', resolve)
|
||||||
|
// Settings
|
||||||
|
.on('user.settings.update', function(data) {
|
||||||
|
dbapi.updateUserSettings(user.email, data)
|
||||||
|
})
|
||||||
|
.on('user.settings.reset', function() {
|
||||||
|
dbapi.resetUserSettings(user.email)
|
||||||
|
})
|
||||||
// Touch events
|
// Touch events
|
||||||
.on('input.touchDown', createTouchHandler(wire.TouchDownMessage))
|
.on('input.touchDown', createTouchHandler(wire.TouchDownMessage))
|
||||||
.on('input.touchMove', createTouchHandler(wire.TouchMoveMessage))
|
.on('input.touchMove', createTouchHandler(wire.TouchMoveMessage))
|
||||||
|
|
|
@ -1,17 +1,2 @@
|
||||||
require('localforage')
|
module.exports = angular.module('stf/settings', [])
|
||||||
require('angular-localForage')
|
|
||||||
|
|
||||||
module.exports = angular.module('stf/settings', [
|
|
||||||
'LocalForageModule'
|
|
||||||
])
|
|
||||||
.config(['$localForageProvider', function ($localForageProvider) {
|
|
||||||
$localForageProvider.config({
|
|
||||||
driver: 'localStorageWrapper',
|
|
||||||
name: 'stf-v0',
|
|
||||||
version: 1.0,
|
|
||||||
storeName: 'settings',
|
|
||||||
description: 'STF Local Settings'
|
|
||||||
})
|
|
||||||
|
|
||||||
}])
|
|
||||||
.factory('SettingsService', require('./settings-service'))
|
.factory('SettingsService', require('./settings-service'))
|
||||||
|
|
|
@ -1,61 +1,103 @@
|
||||||
var Promise = require('bluebird')
|
var _ = require('lodash')
|
||||||
|
|
||||||
module.exports = function SettingsServiceFactory($localForage) {
|
module.exports = function SettingsServiceFactory(
|
||||||
|
$rootScope
|
||||||
|
, UserService
|
||||||
|
, socket
|
||||||
|
) {
|
||||||
var SettingsService = {}
|
var SettingsService = {}
|
||||||
|
|
||||||
var loadedInMemory = false
|
var settings = UserService.currentUser.settings || {}
|
||||||
|
, syncListeners = []
|
||||||
|
|
||||||
var memoryData = Object.create(null)
|
function createListener(object, options, monitor) {
|
||||||
|
var source = options.source || options.target
|
||||||
|
return function() {
|
||||||
|
var value = object[options.target] = (source in settings)
|
||||||
|
? settings[source]
|
||||||
|
: options.defaultValue
|
||||||
|
|
||||||
function setItemMemory(key, value) {
|
if (monitor) {
|
||||||
memoryData[key] = value
|
monitor(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getItemMemory(key) {
|
function applyDelta(delta) {
|
||||||
return memoryData[key]
|
$rootScope.safeApply(function() {
|
||||||
}
|
_.merge(settings, delta, function(a, b) {
|
||||||
|
// New Arrays overwrite old Arrays
|
||||||
|
return _.isArray(b) ? b : undefined
|
||||||
|
})
|
||||||
|
|
||||||
SettingsService.setItem = function (key, value) {
|
for (var i = 0, l = syncListeners.length; i < l; ++i) {
|
||||||
setItemMemory(key, value)
|
syncListeners[i]()
|
||||||
return $localForage.setItem(key, value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadAllItems() {
|
|
||||||
if (loadedInMemory) {
|
|
||||||
return Promise.resolve()
|
|
||||||
}
|
|
||||||
|
|
||||||
return $localForage.getKeys().then(function (keys) {
|
|
||||||
return Promise.all(keys.map(function (key) {
|
|
||||||
return $localForage.getItem(key).then(setItemMemory.bind(null, key))
|
|
||||||
}))
|
|
||||||
}).then(function () {
|
|
||||||
loadedInMemory = true
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsService.getItem = function (key) {
|
SettingsService.update = function(delta) {
|
||||||
return loadAllItems().then(function () {
|
socket.emit('user.settings.update', delta)
|
||||||
return getItemMemory(key)
|
applyDelta(delta)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsService.bind = function () {
|
SettingsService.set = function(key, value) {
|
||||||
|
var delta = Object.create(null)
|
||||||
|
delta[key] = value
|
||||||
|
SettingsService.update(delta)
|
||||||
return $localForage.bind.apply($localForage, arguments)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsService.driver = function () {
|
SettingsService.reset = function() {
|
||||||
return $localForage.driver.apply($localForage, arguments)
|
socket.emit('user.settings.reset')
|
||||||
+ ' with memory cache'
|
settings = {}
|
||||||
|
applyDelta(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsService.clear = function () {
|
SettingsService.bind = function(scope, options) {
|
||||||
memoryData = Object.create(null)
|
var source = options.source || options.target
|
||||||
return $localForage.clear.apply($localForage, arguments)
|
|
||||||
|
scope.$watch(
|
||||||
|
options.target
|
||||||
|
, function(newValue, oldValue) {
|
||||||
|
// Skip initial value.
|
||||||
|
if (newValue !== oldValue) {
|
||||||
|
var delta = Object.create(null)
|
||||||
|
delta[source] = newValue
|
||||||
|
SettingsService.update(delta)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
, true
|
||||||
|
)
|
||||||
|
|
||||||
|
scope.$watch(
|
||||||
|
function() {
|
||||||
|
return settings[source]
|
||||||
|
}
|
||||||
|
, function(newValue, oldValue) {
|
||||||
|
// Skip initial value. The new value might not be different if
|
||||||
|
// settings were reset, for example. In that case we call back
|
||||||
|
// to the default value.
|
||||||
|
if (newValue !== oldValue) {
|
||||||
|
scope[options.target] = newValue || options.defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
, true
|
||||||
|
)
|
||||||
|
|
||||||
|
scope[options.target] = settings[source] || options.defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsService.sync = function(object, options, monitor) {
|
||||||
|
var listener = createListener(object, options, monitor)
|
||||||
|
listener() // Initialize
|
||||||
|
return syncListeners.push(listener) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsService.unsync = function(id) {
|
||||||
|
syncListeners.splice(id, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.on('user.settings.update', applyDelta)
|
||||||
|
|
||||||
return SettingsService
|
return SettingsService
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
module.exports = function LayoutCtrl(LanguageService) {
|
module.exports = function LayoutCtrl(LanguageService) {
|
||||||
LanguageService.init()
|
LanguageService.updateLanguage()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
module.exports = function MenuCtrl($scope, $rootScope, SettingsService, $location, ExternalUrlModalService) {
|
module.exports = function MenuCtrl(
|
||||||
$rootScope.platform = 'native'
|
$scope
|
||||||
|
, $rootScope
|
||||||
|
, SettingsService
|
||||||
|
, $location
|
||||||
|
, ExternalUrlModalService
|
||||||
|
) {
|
||||||
SettingsService.bind($rootScope, {
|
SettingsService.bind($rootScope, {
|
||||||
key: 'platform',
|
target: 'platform'
|
||||||
storeName: 'Platform'
|
, defaultValue: 'native'
|
||||||
})
|
})
|
||||||
|
|
||||||
$scope.$on('$routeChangeSuccess', function () {
|
$scope.$on('$routeChangeSuccess', function () {
|
||||||
|
|
|
@ -1,20 +1,8 @@
|
||||||
module.exports = function ($scope, LanguageService, SettingsService) {
|
module.exports = function ($scope, LanguageService, SettingsService) {
|
||||||
// SettingsService.sync($scope, 'Language', {
|
SettingsService.bind($scope, {
|
||||||
// language: LanguageService.detectedLanguage
|
target: 'language'
|
||||||
// })
|
, source: LanguageService.settingKey
|
||||||
// SettingsService.bind($scope, {
|
, defaultValue: LanguageService.detectedLanguage
|
||||||
// key: 'language',
|
|
||||||
// defaultValue: LanguageService.selectedLanguage
|
|
||||||
// })
|
|
||||||
|
|
||||||
LanguageService.getSelectedLanguage().then(function (data) {
|
|
||||||
$scope.language = data
|
|
||||||
})
|
|
||||||
|
|
||||||
$scope.$watch('language', function (newValue, oldValue) {
|
|
||||||
if (newValue !== oldValue) {
|
|
||||||
LanguageService.setSelectedLanguage(newValue)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
$scope.supportedLanguages = LanguageService.supportedLanguages
|
$scope.supportedLanguages = LanguageService.supportedLanguages
|
||||||
|
|
|
@ -1,67 +1,45 @@
|
||||||
var _ = require('lodash')
|
|
||||||
var supportedLanguages = require('./../../../common/lang/langs.json')
|
var supportedLanguages = require('./../../../common/lang/langs.json')
|
||||||
|
|
||||||
module.exports = function (SettingsService, $q, gettextCatalog) {
|
module.exports = function LanguageServiceFactory(
|
||||||
|
SettingsService
|
||||||
|
, gettextCatalog
|
||||||
|
) {
|
||||||
var LanguageService = {}
|
var LanguageService = {}
|
||||||
|
|
||||||
|
function detectLanguage() {
|
||||||
|
return (navigator.language || navigator.userLanguage || 'en-US')
|
||||||
|
.substring(0, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSupported(lang) {
|
||||||
|
return !!supportedLanguages[lang]
|
||||||
|
}
|
||||||
|
|
||||||
|
function onlySupported(lang, defaultValue) {
|
||||||
|
return isSupported(lang) ? lang : defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
LanguageService.settingKey = 'selectedLanguage'
|
||||||
LanguageService.supportedLanguages = supportedLanguages
|
LanguageService.supportedLanguages = supportedLanguages
|
||||||
|
LanguageService.defaultLanguage = 'en'
|
||||||
|
LanguageService.detectedLanguage =
|
||||||
|
onlySupported(detectLanguage(), LanguageService.defaultLanguage)
|
||||||
|
|
||||||
var browserLocale = navigator.language || navigator.userLanguage || 'en-US'
|
SettingsService.sync(
|
||||||
var browserLanguage = browserLocale.substring(0, 2)
|
LanguageService
|
||||||
var isLanguageMatched = _.some(supportedLanguages, function (value, key) {
|
, {
|
||||||
return key === browserLanguage
|
target: LanguageService.settingKey
|
||||||
})
|
, source: LanguageService.settingKey
|
||||||
var detectedLanguage = isLanguageMatched ? browserLanguage : 'en'
|
, defaultValue: LanguageService.detectedLanguage
|
||||||
|
|
||||||
var defaultLanguage = 'ja'
|
|
||||||
LanguageService.detectedLanguage = defaultLanguage
|
|
||||||
LanguageService.selectedLanguage = null
|
|
||||||
|
|
||||||
// TODO: Can't this be refactored to something like this?
|
|
||||||
// SettingsService.sync(LanguageService.selectedLanguage, 'Language', {
|
|
||||||
// selected: LanguageService.detectedLanguage
|
|
||||||
// })
|
|
||||||
|
|
||||||
LanguageService.getSelectedLanguage = function () {
|
|
||||||
var deferred = $q.defer()
|
|
||||||
if (LanguageService.selectedLanguage) {
|
|
||||||
deferred.resolve(LanguageService.selectedLanguage)
|
|
||||||
} else {
|
|
||||||
SettingsService.getItem('Language.selected').then(function (data) {
|
|
||||||
if (data) {
|
|
||||||
deferred.resolve(data)
|
|
||||||
} else {
|
|
||||||
LanguageService.setSelectedLanguage(LanguageService.detectedLanguage)
|
|
||||||
.then(function () {
|
|
||||||
deferred.resolve(LanguageService.detectedLanguage)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
, updateLanguage
|
||||||
}
|
)
|
||||||
return deferred.promise
|
|
||||||
|
function updateLanguage() {
|
||||||
|
gettextCatalog.currentLanguage = LanguageService.selectedLanguage
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this is to prevent initial text flashing from ja
|
LanguageService.updateLanguage = updateLanguage
|
||||||
gettextCatalog.currentLanguage = LanguageService.detectedLanguage
|
|
||||||
|
|
||||||
// Initialize gettextCatalog
|
|
||||||
|
|
||||||
LanguageService.init = function () {
|
|
||||||
LanguageService.getSelectedLanguage().then(function (data) {
|
|
||||||
LanguageService.setSelectedLanguage(data)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LanguageService.setSelectedLanguage = function (lang) {
|
|
||||||
var deferred = $q.defer()
|
|
||||||
LanguageService.selectedLanguage = lang
|
|
||||||
gettextCatalog.currentLanguage = lang
|
|
||||||
SettingsService.setItem('Language.selected', lang).then(function () {
|
|
||||||
deferred.resolve(lang)
|
|
||||||
})
|
|
||||||
return deferred.promise
|
|
||||||
}
|
|
||||||
|
|
||||||
return LanguageService
|
return LanguageService
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
module.exports = function ($scope, SettingsService) {
|
module.exports = function ($scope, SettingsService) {
|
||||||
|
|
||||||
$scope.resetSettings = function () {
|
$scope.resetSettings = function () {
|
||||||
SettingsService.clear()
|
SettingsService.reset()
|
||||||
console.log('Settings cleared')
|
console.log('Settings cleared')
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.savedTo = SettingsService.driver()
|
|
||||||
|
|
||||||
// $scope.resetSettings = function () {
|
// $scope.resetSettings = function () {
|
||||||
// var title = 'Reset Settings';
|
// var title = 'Reset Settings';
|
||||||
// var msg = 'Are you sure you want to revert all settings to ' +
|
// var msg = 'Are you sure you want to revert all settings to ' +
|
||||||
|
|
|
@ -6,6 +6,3 @@
|
||||||
button(ng-click='resetSettings()').btn.btn-danger
|
button(ng-click='resetSettings()').btn.btn-danger
|
||||||
i.fa.fa-trash-o
|
i.fa.fa-trash-o
|
||||||
span(translate) Reset Settings
|
span(translate) Reset Settings
|
||||||
|
|
||||||
p
|
|
||||||
span.text-muted(translate) Saved to: {{savedTo}}
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue