2014-01-21 12:45:27 +04:00
|
|
|
|
2014-02-05 12:40:30 +04:00
|
|
|
var _ = require('lodash'),
|
2014-08-17 10:17:23 +04:00
|
|
|
Promise = require('bluebird'),
|
2014-05-09 14:11:29 +04:00
|
|
|
errors = require('../errors'),
|
2014-01-21 12:45:27 +04:00
|
|
|
api = require('../api'),
|
|
|
|
loader = require('./loader'),
|
2015-11-12 15:29:45 +03:00
|
|
|
i18n = require('../i18n'),
|
2016-04-11 16:58:41 +03:00
|
|
|
config = require('../config'),
|
2014-01-21 12:45:27 +04:00
|
|
|
// Holds the available apps
|
|
|
|
availableApps = {};
|
|
|
|
|
|
|
|
function getInstalledApps() {
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
return api.settings.read({context: {internal: true}, key: 'installedApps'}).then(function (response) {
|
2014-04-28 03:28:50 +04:00
|
|
|
var installed = response.settings[0];
|
|
|
|
|
2014-01-21 12:45:27 +04:00
|
|
|
installed.value = installed.value || '[]';
|
|
|
|
|
|
|
|
try {
|
|
|
|
installed = JSON.parse(installed.value);
|
|
|
|
} catch (e) {
|
2014-08-17 10:17:23 +04:00
|
|
|
return Promise.reject(e);
|
2014-01-21 12:45:27 +04:00
|
|
|
}
|
|
|
|
|
2016-09-13 18:41:14 +03:00
|
|
|
return installed.concat(config.get('internalApps'));
|
2014-01-21 12:45:27 +04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function saveInstalledApps(installedApps) {
|
|
|
|
return getInstalledApps().then(function (currentInstalledApps) {
|
2016-09-13 18:41:14 +03:00
|
|
|
var updatedAppsInstalled = _.difference(_.uniq(installedApps.concat(currentInstalledApps)), config.get('internalApps'));
|
2014-01-21 12:45:27 +04:00
|
|
|
|
2014-05-24 10:21:17 +04:00
|
|
|
return api.settings.edit({settings: [{key: 'installedApps', value: updatedAppsInstalled}]}, {context: {internal: true}});
|
2014-01-21 12:45:27 +04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
init: function () {
|
|
|
|
var appsToLoad;
|
|
|
|
|
|
|
|
try {
|
|
|
|
// We have to parse the value because it's a string
|
Refactor API arguments
closes #2610, refs #2697
- cleanup API index.js, and add docs
- all API methods take consistent arguments: object & options
- browse, read, destroy take options, edit and add take object and options
- the context is passed as part of options, meaning no more .call
everywhere
- destroy expects an object, rather than an id all the way down to the model layer
- route params such as :id, :slug, and :key are passed as an option & used
to perform reads, updates and deletes where possible - settings / themes
may need work here still
- HTTP posts api can find a post by slug
- Add API utils for checkData
2014-05-08 16:41:19 +04:00
|
|
|
api.settings.read({context: {internal: true}, key: 'activeApps'}).then(function (response) {
|
2014-04-28 03:28:50 +04:00
|
|
|
var aApps = response.settings[0];
|
|
|
|
|
2014-01-21 12:45:27 +04:00
|
|
|
appsToLoad = JSON.parse(aApps.value) || [];
|
2016-04-11 16:58:41 +03:00
|
|
|
|
2016-09-13 18:41:14 +03:00
|
|
|
appsToLoad = appsToLoad.concat(config.get('internalApps'));
|
2014-01-21 12:45:27 +04:00
|
|
|
});
|
|
|
|
} catch (e) {
|
|
|
|
errors.logError(
|
2015-11-12 15:29:45 +03:00
|
|
|
i18n.t('errors.apps.failedToParseActiveAppsSettings.error', {message: e.message}),
|
|
|
|
i18n.t('errors.apps.failedToParseActiveAppsSettings.context'),
|
|
|
|
i18n.t('errors.apps.failedToParseActiveAppsSettings.help')
|
2014-01-21 12:45:27 +04:00
|
|
|
);
|
2014-08-17 10:17:23 +04:00
|
|
|
|
|
|
|
return Promise.resolve();
|
2014-01-21 12:45:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Grab all installed apps, install any not already installed that are in appsToLoad.
|
|
|
|
return getInstalledApps().then(function (installedApps) {
|
|
|
|
var loadedApps = {},
|
|
|
|
recordLoadedApp = function (name, loadedApp) {
|
|
|
|
// After loading the app, add it to our hash of loaded apps
|
|
|
|
loadedApps[name] = loadedApp;
|
|
|
|
|
2014-08-17 10:17:23 +04:00
|
|
|
return Promise.resolve(loadedApp);
|
2014-01-21 12:45:27 +04:00
|
|
|
},
|
|
|
|
loadPromises = _.map(appsToLoad, function (app) {
|
|
|
|
// If already installed, just activate the app
|
2016-06-11 21:23:27 +03:00
|
|
|
if (_.includes(installedApps, app)) {
|
2014-01-21 12:45:27 +04:00
|
|
|
return loader.activateAppByName(app).then(function (loadedApp) {
|
|
|
|
return recordLoadedApp(app, loadedApp);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Install, then activate the app
|
|
|
|
return loader.installAppByName(app).then(function () {
|
|
|
|
return loader.activateAppByName(app);
|
|
|
|
}).then(function (loadedApp) {
|
|
|
|
return recordLoadedApp(app, loadedApp);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2014-08-17 10:17:23 +04:00
|
|
|
return Promise.all(loadPromises).then(function () {
|
2014-01-21 12:45:27 +04:00
|
|
|
// Save our installed apps to settings
|
|
|
|
return saveInstalledApps(_.keys(loadedApps));
|
|
|
|
}).then(function () {
|
|
|
|
// Extend the loadedApps onto the available apps
|
|
|
|
_.extend(availableApps, loadedApps);
|
2014-08-17 10:17:23 +04:00
|
|
|
}).catch(function (err) {
|
2014-01-21 12:45:27 +04:00
|
|
|
errors.logError(
|
|
|
|
err.message || err,
|
2015-11-12 15:29:45 +03:00
|
|
|
i18n.t('errors.apps.appWillNotBeLoaded.error'),
|
|
|
|
i18n.t('errors.apps.appWillNotBeLoaded.help')
|
2014-01-21 12:45:27 +04:00
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
},
|
|
|
|
availableApps: availableApps
|
2014-08-17 10:17:23 +04:00
|
|
|
};
|