2014-02-05 12:40:30 +04:00
|
|
|
var _ = require('lodash'),
|
2013-12-06 12:51:35 +04:00
|
|
|
dataProvider = require('../models'),
|
|
|
|
when = require('when'),
|
|
|
|
errors = require('../errorHandling'),
|
|
|
|
config = require('../config'),
|
|
|
|
settings,
|
|
|
|
settingsObject,
|
|
|
|
settingsCollection,
|
|
|
|
settingsFilter,
|
|
|
|
updateSettingsCache,
|
|
|
|
readSettingsResult,
|
2014-02-23 16:32:35 +04:00
|
|
|
filterPaths,
|
2013-12-06 12:51:35 +04:00
|
|
|
// Holds cached settings
|
|
|
|
settingsCache = {};
|
|
|
|
|
|
|
|
// ### Helpers
|
|
|
|
// Turn a settings collection into a single object/hashmap
|
|
|
|
settingsObject = function (settings) {
|
|
|
|
if (_.isObject(settings)) {
|
|
|
|
return _.reduce(settings, function (res, item, key) {
|
|
|
|
if (_.isArray(item)) {
|
|
|
|
res[key] = item;
|
|
|
|
} else {
|
|
|
|
res[key] = item.value;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}, {});
|
|
|
|
}
|
|
|
|
return (settings.toJSON ? settings.toJSON() : settings).reduce(function (res, item) {
|
|
|
|
if (item.toJSON) { item = item.toJSON(); }
|
|
|
|
if (item.key) { res[item.key] = item.value; }
|
|
|
|
return res;
|
|
|
|
}, {});
|
|
|
|
};
|
|
|
|
// Turn an object into a collection
|
|
|
|
settingsCollection = function (settings) {
|
|
|
|
return _.map(settings, function (value, key) {
|
|
|
|
return { key: key, value: value };
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// Filters an object based on a given filter object
|
|
|
|
settingsFilter = function (settings, filter) {
|
|
|
|
return _.object(_.filter(_.pairs(settings), function (setting) {
|
|
|
|
if (filter) {
|
|
|
|
return _.some(filter.split(','), function (f) {
|
|
|
|
return setting[1].type === f;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}));
|
|
|
|
};
|
|
|
|
|
|
|
|
// Maintain the internal cache of the settings object
|
|
|
|
updateSettingsCache = function (settings) {
|
|
|
|
settings = settings || {};
|
|
|
|
|
|
|
|
if (!_.isEmpty(settings)) {
|
|
|
|
_.map(settings, function (setting, key) {
|
|
|
|
settingsCache[key].value = setting.value;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
return when(dataProvider.Settings.findAll()).then(function (result) {
|
|
|
|
return when(readSettingsResult(result)).then(function (s) {
|
|
|
|
settingsCache = s;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
readSettingsResult = function (result) {
|
|
|
|
var settings = {};
|
|
|
|
return when(_.map(result.models, function (member) {
|
|
|
|
if (!settings.hasOwnProperty(member.attributes.key)) {
|
|
|
|
var val = {};
|
|
|
|
val.value = member.attributes.value;
|
|
|
|
val.type = member.attributes.type;
|
|
|
|
settings[member.attributes.key] = val;
|
|
|
|
}
|
|
|
|
})).then(function () {
|
2014-01-05 10:40:53 +04:00
|
|
|
return when(config().paths.availableThemes).then(function (themes) {
|
2014-02-23 16:32:35 +04:00
|
|
|
var res = filterPaths(themes, settings.activeTheme.value);
|
|
|
|
settings.availableThemes = {
|
|
|
|
value: res,
|
|
|
|
type: 'theme'
|
|
|
|
};
|
2013-12-06 12:51:35 +04:00
|
|
|
return settings;
|
|
|
|
});
|
2014-02-23 16:32:35 +04:00
|
|
|
}).then(function () {
|
|
|
|
return when(config().paths.availableApps).then(function (apps) {
|
|
|
|
var res = filterPaths(apps, JSON.parse(settings.activeApps.value));
|
|
|
|
settings.availableApps = {
|
|
|
|
value: res,
|
|
|
|
type: 'app'
|
|
|
|
};
|
|
|
|
return settings;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Normalizes paths read by require-tree so that the apps and themes modules can use them.
|
|
|
|
* Creates an empty array (res), and populates it with useful info about the read packages
|
|
|
|
* like name, whether they're active (comparison with the second argument), and if they
|
|
|
|
* have a package.json, that, otherwise false
|
|
|
|
* @param object paths as returned by require-tree()
|
|
|
|
* @param array/string active as read from the settings object
|
|
|
|
* @return array of objects with useful info about
|
|
|
|
* apps / themes
|
|
|
|
*/
|
|
|
|
filterPaths = function (paths, active) {
|
|
|
|
var pathKeys = Object.keys(paths),
|
|
|
|
res = [],
|
|
|
|
item;
|
|
|
|
|
|
|
|
// turn active into an array (so themes and apps can be checked the same)
|
|
|
|
if (!Array.isArray(active)) {
|
|
|
|
active = [active];
|
|
|
|
}
|
|
|
|
|
|
|
|
_.each(pathKeys, function (key) {
|
|
|
|
//do not include hidden files or _messages
|
|
|
|
if (key.indexOf('.') !== 0
|
|
|
|
&& key !== '_messages'
|
|
|
|
&& key !== 'README.md'
|
|
|
|
) {
|
|
|
|
item = {
|
|
|
|
name: key
|
|
|
|
};
|
|
|
|
if (paths[key].hasOwnProperty('package.json')) {
|
|
|
|
item.package = paths[key]['package.json'];
|
|
|
|
} else {
|
|
|
|
item.package = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_.indexOf(active, key) !== -1) {
|
|
|
|
item.active = true;
|
|
|
|
}
|
|
|
|
res.push(item);
|
|
|
|
}
|
2013-12-06 12:51:35 +04:00
|
|
|
});
|
2014-02-23 16:32:35 +04:00
|
|
|
return res;
|
2013-12-06 12:51:35 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
settings = {
|
|
|
|
// #### Browse
|
|
|
|
|
|
|
|
// **takes:** options object
|
|
|
|
browse: function browse(options) {
|
|
|
|
// **returns:** a promise for a settings json object
|
|
|
|
if (settingsCache) {
|
|
|
|
return when(settingsCache).then(function (settings) {
|
|
|
|
//TODO: omit where type==core
|
|
|
|
return settingsObject(settingsFilter(settings, options.type));
|
|
|
|
}, errors.logAndThrowError);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
// #### Read
|
|
|
|
|
|
|
|
// **takes:** either a json object containing a key, or a single key string
|
|
|
|
read: function read(options) {
|
|
|
|
if (_.isString(options)) {
|
|
|
|
options = { key: options };
|
|
|
|
}
|
|
|
|
|
|
|
|
if (settingsCache) {
|
|
|
|
return when(settingsCache[options.key]).then(function (setting) {
|
|
|
|
if (!setting) {
|
2014-02-26 21:51:01 +04:00
|
|
|
return when.reject({code: 404, message: 'Unable to find setting: ' + options.key});
|
2013-12-06 12:51:35 +04:00
|
|
|
}
|
|
|
|
var res = {};
|
|
|
|
res.key = options.key;
|
|
|
|
res.value = setting.value;
|
|
|
|
return res;
|
|
|
|
}, errors.logAndThrowError);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
// #### Edit
|
|
|
|
|
|
|
|
// **takes:** either a json object representing a collection of settings, or a key and value pair
|
|
|
|
edit: function edit(key, value) {
|
2014-04-03 17:03:09 +04:00
|
|
|
var self = this,
|
|
|
|
type;
|
|
|
|
|
2013-12-06 12:51:35 +04:00
|
|
|
// Check for passing a collection of settings first
|
|
|
|
if (_.isObject(key)) {
|
|
|
|
//clean data
|
2014-04-03 17:03:09 +04:00
|
|
|
type = key.type;
|
2013-12-06 12:51:35 +04:00
|
|
|
delete key.type;
|
|
|
|
delete key.availableThemes;
|
2014-02-23 16:32:35 +04:00
|
|
|
delete key.availableApps;
|
2013-12-06 12:51:35 +04:00
|
|
|
|
|
|
|
key = settingsCollection(key);
|
2014-04-03 17:03:09 +04:00
|
|
|
return dataProvider.Settings.edit(key, {user: self.user}).then(function (result) {
|
2013-12-06 12:51:35 +04:00
|
|
|
result.models = result;
|
|
|
|
return when(readSettingsResult(result)).then(function (settings) {
|
|
|
|
updateSettingsCache(settings);
|
2013-12-10 08:41:58 +04:00
|
|
|
}).then(function () {
|
2013-12-26 16:15:10 +04:00
|
|
|
return config.theme.update(settings, config().url).then(function () {
|
2013-12-10 08:41:58 +04:00
|
|
|
return settingsObject(settingsFilter(settingsCache, type));
|
|
|
|
});
|
2013-12-06 12:51:35 +04:00
|
|
|
});
|
|
|
|
}).otherwise(function (error) {
|
|
|
|
return dataProvider.Settings.read(key.key).then(function (result) {
|
|
|
|
if (!result) {
|
2014-02-26 21:51:01 +04:00
|
|
|
return when.reject({code: 404, message: 'Unable to find setting: ' + key});
|
2013-12-06 12:51:35 +04:00
|
|
|
}
|
|
|
|
return when.reject({message: error.message});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return dataProvider.Settings.read(key).then(function (setting) {
|
|
|
|
if (!setting) {
|
2014-02-26 21:51:01 +04:00
|
|
|
return when.reject({code: 404, message: 'Unable to find setting: ' + key});
|
2013-12-06 12:51:35 +04:00
|
|
|
}
|
|
|
|
if (!_.isString(value)) {
|
|
|
|
value = JSON.stringify(value);
|
|
|
|
}
|
|
|
|
setting.set('value', value);
|
2014-04-03 17:03:09 +04:00
|
|
|
return dataProvider.Settings.edit(setting, {user: self.user}).then(function (result) {
|
2013-12-06 12:51:35 +04:00
|
|
|
settingsCache[_.first(result).attributes.key].value = _.first(result).attributes.value;
|
2013-12-10 08:41:58 +04:00
|
|
|
}).then(function () {
|
2013-12-26 16:15:10 +04:00
|
|
|
return config.theme.update(settings, config().url).then(function () {
|
2013-12-10 08:41:58 +04:00
|
|
|
return settingsObject(settingsCache);
|
|
|
|
});
|
|
|
|
}).otherwise(errors.logAndThrowError);
|
2013-12-06 12:51:35 +04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = settings;
|
|
|
|
module.exports.updateSettingsCache = updateSettingsCache;
|