mirror of
https://github.com/balena-io/etcher.git
synced 2025-08-13 05:09:24 +00:00
refactor: store settings in redux store
The state data structure now contains a property called `settings`, which is a map containing all setting values. The list of supported settings can be calculated by retrieving the keys from the `settings` object, which means that if we support a setting, we must include a default. Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
This commit is contained in:
@@ -21,41 +21,11 @@
|
||||
*/
|
||||
|
||||
const angular = require('angular');
|
||||
const _ = require('lodash');
|
||||
require('ngstorage');
|
||||
const Store = require('./store');
|
||||
const MODULE_NAME = 'Etcher.Models.Settings';
|
||||
const SettingsModel = angular.module(MODULE_NAME, [
|
||||
'ngStorage'
|
||||
]);
|
||||
const SettingsModel = angular.module(MODULE_NAME, []);
|
||||
|
||||
SettingsModel.service('SettingsModel', function($localStorage) {
|
||||
|
||||
/**
|
||||
* @summary Default settings
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
const DEFAULT_SETTINGS = {
|
||||
errorReporting: true,
|
||||
unmountOnSuccess: true,
|
||||
validateWriteOnSuccess: true,
|
||||
sleepUpdateCheck: false,
|
||||
lastUpdateNotify: null
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Settings data
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
const data = $localStorage.$default(DEFAULT_SETTINGS);
|
||||
|
||||
/**
|
||||
* @summary Supported settings keys
|
||||
* @type {String[]}
|
||||
* @private
|
||||
*/
|
||||
this.SUPPORTED_KEYS = _.keys(DEFAULT_SETTINGS);
|
||||
SettingsModel.service('SettingsModel', function() {
|
||||
|
||||
/**
|
||||
* @summary Set a setting value
|
||||
@@ -69,23 +39,13 @@ SettingsModel.service('SettingsModel', function($localStorage) {
|
||||
* SettingsModel.set('unmountOnSuccess', true);
|
||||
*/
|
||||
this.set = (key, value) => {
|
||||
if (!key) {
|
||||
throw new Error('Missing setting key');
|
||||
}
|
||||
|
||||
if (!_.isString(key)) {
|
||||
throw new Error(`Invalid setting key: ${key}`);
|
||||
}
|
||||
|
||||
if (!_.includes(this.SUPPORTED_KEYS, key)) {
|
||||
throw new Error(`Unsupported setting: ${key}`);
|
||||
}
|
||||
|
||||
if (_.isObject(value)) {
|
||||
throw new Error(`Invalid setting value: ${value}`);
|
||||
}
|
||||
|
||||
data[key] = value;
|
||||
Store.dispatch({
|
||||
type: Store.Actions.SET_SETTING,
|
||||
data: {
|
||||
key,
|
||||
value
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -100,15 +60,7 @@ SettingsModel.service('SettingsModel', function($localStorage) {
|
||||
* const value = SettingsModel.get('unmountOnSuccess');
|
||||
*/
|
||||
this.get = (key) => {
|
||||
if (!key) {
|
||||
throw new Error('Missing setting key');
|
||||
}
|
||||
|
||||
if (!_.isString(key)) {
|
||||
throw new Error(`Invalid setting key: ${key}`);
|
||||
}
|
||||
|
||||
return data[key];
|
||||
return this.getAll()[key];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -123,7 +75,7 @@ SettingsModel.service('SettingsModel', function($localStorage) {
|
||||
* console.log(allSettings.unmountOnSuccess);
|
||||
*/
|
||||
this.getAll = () => {
|
||||
return data;
|
||||
return Store.getState().get('settings').toJS();
|
||||
};
|
||||
|
||||
});
|
||||
|
@@ -34,6 +34,13 @@ const DEFAULT_STATE = Immutable.fromJS({
|
||||
flashState: {
|
||||
percentage: 0,
|
||||
speed: 0
|
||||
},
|
||||
settings: {
|
||||
errorReporting: true,
|
||||
unmountOnSuccess: true,
|
||||
validateWriteOnSuccess: true,
|
||||
sleepUpdateCheck: false,
|
||||
lastUpdateNotify: null
|
||||
}
|
||||
});
|
||||
|
||||
@@ -51,7 +58,8 @@ const ACTIONS = _.fromPairs(_.map([
|
||||
'SELECT_DRIVE',
|
||||
'SELECT_IMAGE',
|
||||
'REMOVE_DRIVE',
|
||||
'REMOVE_IMAGE'
|
||||
'REMOVE_IMAGE',
|
||||
'SET_SETTING'
|
||||
], (message) => {
|
||||
return [ message, message ];
|
||||
}));
|
||||
@@ -263,6 +271,29 @@ const storeReducer = (state, action) => {
|
||||
return state.deleteIn([ 'selection', 'image' ]);
|
||||
}
|
||||
|
||||
case ACTIONS.SET_SETTING: {
|
||||
const key = action.data.key;
|
||||
const value = action.data.value;
|
||||
|
||||
if (!key) {
|
||||
throw new Error('Missing setting key');
|
||||
}
|
||||
|
||||
if (!_.isString(key)) {
|
||||
throw new Error(`Invalid setting key: ${key}`);
|
||||
}
|
||||
|
||||
if (!DEFAULT_STATE.get('settings').has(key)) {
|
||||
throw new Error(`Unsupported setting: ${key}`);
|
||||
}
|
||||
|
||||
if (_.isObject(value)) {
|
||||
throw new Error(`Invalid setting value: ${value}`);
|
||||
}
|
||||
|
||||
return state.setIn([ 'settings', key ], value);
|
||||
}
|
||||
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
@@ -271,5 +302,6 @@ const storeReducer = (state, action) => {
|
||||
};
|
||||
|
||||
module.exports = _.merge(redux.createStore(storeReducer), {
|
||||
Actions: ACTIONS
|
||||
Actions: ACTIONS,
|
||||
Defaults: DEFAULT_STATE
|
||||
});
|
||||
|
@@ -72,7 +72,6 @@
|
||||
"immutable": "^3.8.1",
|
||||
"is-elevated": "^1.0.0",
|
||||
"lodash": "^4.5.1",
|
||||
"ngstorage": "^0.3.10",
|
||||
"redux": "^3.5.2",
|
||||
"resin-cli-errors": "^1.2.0",
|
||||
"resin-cli-form": "^1.4.1",
|
||||
|
@@ -4,6 +4,7 @@ const m = require('mochainon');
|
||||
const _ = require('lodash');
|
||||
const angular = require('angular');
|
||||
require('angular-mocks');
|
||||
const Store = require('../../../lib/gui/models/store');
|
||||
|
||||
describe('Browser: SettingsModel', function() {
|
||||
|
||||
@@ -13,6 +14,7 @@ describe('Browser: SettingsModel', function() {
|
||||
|
||||
describe('SettingsModel', function() {
|
||||
|
||||
const SUPPORTED_KEYS = _.keys(Store.Defaults.get('settings').toJS());
|
||||
let SettingsModel;
|
||||
|
||||
beforeEach(angular.mock.inject(function(_SettingsModel_) {
|
||||
@@ -24,13 +26,13 @@ describe('Browser: SettingsModel', function() {
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
_.each(SettingsModel.SUPPORTED_KEYS, (supportedKey) => {
|
||||
_.each(SUPPORTED_KEYS, (supportedKey) => {
|
||||
SettingsModel.set(supportedKey, this.settings[supportedKey]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to set and read values', function() {
|
||||
const keyUnderTest = _.first(SettingsModel.SUPPORTED_KEYS);
|
||||
const keyUnderTest = _.first(SUPPORTED_KEYS);
|
||||
const originalValue = SettingsModel.get(keyUnderTest);
|
||||
|
||||
SettingsModel.set(keyUnderTest, !originalValue);
|
||||
@@ -39,22 +41,6 @@ describe('Browser: SettingsModel', function() {
|
||||
m.chai.expect(SettingsModel.get(keyUnderTest)).to.equal(originalValue);
|
||||
});
|
||||
|
||||
describe('.get()', function() {
|
||||
|
||||
it('should throw if no key', function() {
|
||||
m.chai.expect(function() {
|
||||
SettingsModel.get(null);
|
||||
}).to.throw('Missing setting key');
|
||||
});
|
||||
|
||||
it('should throw if key is not a string', function() {
|
||||
m.chai.expect(function() {
|
||||
SettingsModel.get(1234);
|
||||
}).to.throw('Invalid setting key: 1234');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('.set()', function() {
|
||||
|
||||
it('should throw if the key is not supported', function() {
|
||||
@@ -76,7 +62,7 @@ describe('Browser: SettingsModel', function() {
|
||||
});
|
||||
|
||||
it('should throw if setting an object', function() {
|
||||
const keyUnderTest = _.first(SettingsModel.SUPPORTED_KEYS);
|
||||
const keyUnderTest = _.first(SUPPORTED_KEYS);
|
||||
m.chai.expect(function() {
|
||||
SettingsModel.set(keyUnderTest, {
|
||||
x: 1
|
||||
@@ -85,14 +71,14 @@ describe('Browser: SettingsModel', function() {
|
||||
});
|
||||
|
||||
it('should throw if setting an array', function() {
|
||||
const keyUnderTest = _.first(SettingsModel.SUPPORTED_KEYS);
|
||||
const keyUnderTest = _.first(SUPPORTED_KEYS);
|
||||
m.chai.expect(function() {
|
||||
SettingsModel.set(keyUnderTest, [ 1, 2, 3 ]);
|
||||
}).to.throw('Invalid setting value: 1,2,3');
|
||||
});
|
||||
|
||||
it('should set the key to undefined if no value', function() {
|
||||
const keyUnderTest = _.first(SettingsModel.SUPPORTED_KEYS);
|
||||
const keyUnderTest = _.first(SUPPORTED_KEYS);
|
||||
SettingsModel.set(keyUnderTest);
|
||||
m.chai.expect(SettingsModel.get(keyUnderTest)).to.be.undefined;
|
||||
});
|
||||
@@ -104,7 +90,7 @@ describe('Browser: SettingsModel', function() {
|
||||
it('should be able to read all values', function() {
|
||||
const allValues = SettingsModel.getAll();
|
||||
|
||||
_.each(SettingsModel.SUPPORTED_KEYS, function(supportedKey) {
|
||||
_.each(SUPPORTED_KEYS, function(supportedKey) {
|
||||
m.chai.expect(allValues[supportedKey]).to.equal(SettingsModel.get(supportedKey));
|
||||
});
|
||||
});
|
||||
|
Reference in New Issue
Block a user