mirror of
https://github.com/balena-io/etcher.git
synced 2025-11-10 10:58:32 +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 angular = require('angular');
|
||||||
const _ = require('lodash');
|
const Store = require('./store');
|
||||||
require('ngstorage');
|
|
||||||
const MODULE_NAME = 'Etcher.Models.Settings';
|
const MODULE_NAME = 'Etcher.Models.Settings';
|
||||||
const SettingsModel = angular.module(MODULE_NAME, [
|
const SettingsModel = angular.module(MODULE_NAME, []);
|
||||||
'ngStorage'
|
|
||||||
]);
|
|
||||||
|
|
||||||
SettingsModel.service('SettingsModel', function($localStorage) {
|
SettingsModel.service('SettingsModel', function() {
|
||||||
|
|
||||||
/**
|
|
||||||
* @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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Set a setting value
|
* @summary Set a setting value
|
||||||
@@ -69,23 +39,13 @@ SettingsModel.service('SettingsModel', function($localStorage) {
|
|||||||
* SettingsModel.set('unmountOnSuccess', true);
|
* SettingsModel.set('unmountOnSuccess', true);
|
||||||
*/
|
*/
|
||||||
this.set = (key, value) => {
|
this.set = (key, value) => {
|
||||||
if (!key) {
|
Store.dispatch({
|
||||||
throw new Error('Missing setting key');
|
type: Store.Actions.SET_SETTING,
|
||||||
}
|
data: {
|
||||||
|
key,
|
||||||
if (!_.isString(key)) {
|
value
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,15 +60,7 @@ SettingsModel.service('SettingsModel', function($localStorage) {
|
|||||||
* const value = SettingsModel.get('unmountOnSuccess');
|
* const value = SettingsModel.get('unmountOnSuccess');
|
||||||
*/
|
*/
|
||||||
this.get = (key) => {
|
this.get = (key) => {
|
||||||
if (!key) {
|
return this.getAll()[key];
|
||||||
throw new Error('Missing setting key');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_.isString(key)) {
|
|
||||||
throw new Error(`Invalid setting key: ${key}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data[key];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,7 +75,7 @@ SettingsModel.service('SettingsModel', function($localStorage) {
|
|||||||
* console.log(allSettings.unmountOnSuccess);
|
* console.log(allSettings.unmountOnSuccess);
|
||||||
*/
|
*/
|
||||||
this.getAll = () => {
|
this.getAll = () => {
|
||||||
return data;
|
return Store.getState().get('settings').toJS();
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -34,6 +34,13 @@ const DEFAULT_STATE = Immutable.fromJS({
|
|||||||
flashState: {
|
flashState: {
|
||||||
percentage: 0,
|
percentage: 0,
|
||||||
speed: 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_DRIVE',
|
||||||
'SELECT_IMAGE',
|
'SELECT_IMAGE',
|
||||||
'REMOVE_DRIVE',
|
'REMOVE_DRIVE',
|
||||||
'REMOVE_IMAGE'
|
'REMOVE_IMAGE',
|
||||||
|
'SET_SETTING'
|
||||||
], (message) => {
|
], (message) => {
|
||||||
return [ message, message ];
|
return [ message, message ];
|
||||||
}));
|
}));
|
||||||
@@ -263,6 +271,29 @@ const storeReducer = (state, action) => {
|
|||||||
return state.deleteIn([ 'selection', 'image' ]);
|
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: {
|
default: {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@@ -271,5 +302,6 @@ const storeReducer = (state, action) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
module.exports = _.merge(redux.createStore(storeReducer), {
|
module.exports = _.merge(redux.createStore(storeReducer), {
|
||||||
Actions: ACTIONS
|
Actions: ACTIONS,
|
||||||
|
Defaults: DEFAULT_STATE
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -72,7 +72,6 @@
|
|||||||
"immutable": "^3.8.1",
|
"immutable": "^3.8.1",
|
||||||
"is-elevated": "^1.0.0",
|
"is-elevated": "^1.0.0",
|
||||||
"lodash": "^4.5.1",
|
"lodash": "^4.5.1",
|
||||||
"ngstorage": "^0.3.10",
|
|
||||||
"redux": "^3.5.2",
|
"redux": "^3.5.2",
|
||||||
"resin-cli-errors": "^1.2.0",
|
"resin-cli-errors": "^1.2.0",
|
||||||
"resin-cli-form": "^1.4.1",
|
"resin-cli-form": "^1.4.1",
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const m = require('mochainon');
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const angular = require('angular');
|
const angular = require('angular');
|
||||||
require('angular-mocks');
|
require('angular-mocks');
|
||||||
|
const Store = require('../../../lib/gui/models/store');
|
||||||
|
|
||||||
describe('Browser: SettingsModel', function() {
|
describe('Browser: SettingsModel', function() {
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ describe('Browser: SettingsModel', function() {
|
|||||||
|
|
||||||
describe('SettingsModel', function() {
|
describe('SettingsModel', function() {
|
||||||
|
|
||||||
|
const SUPPORTED_KEYS = _.keys(Store.Defaults.get('settings').toJS());
|
||||||
let SettingsModel;
|
let SettingsModel;
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(function(_SettingsModel_) {
|
beforeEach(angular.mock.inject(function(_SettingsModel_) {
|
||||||
@@ -24,13 +26,13 @@ describe('Browser: SettingsModel', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
_.each(SettingsModel.SUPPORTED_KEYS, (supportedKey) => {
|
_.each(SUPPORTED_KEYS, (supportedKey) => {
|
||||||
SettingsModel.set(supportedKey, this.settings[supportedKey]);
|
SettingsModel.set(supportedKey, this.settings[supportedKey]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to set and read values', function() {
|
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);
|
const originalValue = SettingsModel.get(keyUnderTest);
|
||||||
|
|
||||||
SettingsModel.set(keyUnderTest, !originalValue);
|
SettingsModel.set(keyUnderTest, !originalValue);
|
||||||
@@ -39,22 +41,6 @@ describe('Browser: SettingsModel', function() {
|
|||||||
m.chai.expect(SettingsModel.get(keyUnderTest)).to.equal(originalValue);
|
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() {
|
describe('.set()', function() {
|
||||||
|
|
||||||
it('should throw if the key is not supported', 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() {
|
it('should throw if setting an object', function() {
|
||||||
const keyUnderTest = _.first(SettingsModel.SUPPORTED_KEYS);
|
const keyUnderTest = _.first(SUPPORTED_KEYS);
|
||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SettingsModel.set(keyUnderTest, {
|
SettingsModel.set(keyUnderTest, {
|
||||||
x: 1
|
x: 1
|
||||||
@@ -85,14 +71,14 @@ describe('Browser: SettingsModel', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if setting an array', function() {
|
it('should throw if setting an array', function() {
|
||||||
const keyUnderTest = _.first(SettingsModel.SUPPORTED_KEYS);
|
const keyUnderTest = _.first(SUPPORTED_KEYS);
|
||||||
m.chai.expect(function() {
|
m.chai.expect(function() {
|
||||||
SettingsModel.set(keyUnderTest, [ 1, 2, 3 ]);
|
SettingsModel.set(keyUnderTest, [ 1, 2, 3 ]);
|
||||||
}).to.throw('Invalid setting value: 1,2,3');
|
}).to.throw('Invalid setting value: 1,2,3');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set the key to undefined if no value', function() {
|
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);
|
SettingsModel.set(keyUnderTest);
|
||||||
m.chai.expect(SettingsModel.get(keyUnderTest)).to.be.undefined;
|
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() {
|
it('should be able to read all values', function() {
|
||||||
const allValues = SettingsModel.getAll();
|
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));
|
m.chai.expect(allValues[supportedKey]).to.equal(SettingsModel.get(supportedKey));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user