"use strict";
var datasourcePluginRegistry_1 = require("./datasource/datasourcePluginRegistry");
var _ = require("lodash");
var Plugins = require("./pluginApi/pluginLoader");
var PluginCache = require("./pluginApi/pluginCache");
var scriptLoader_1 = require("./util/scriptLoader");
var URI = require("urijs");
var widgetPluginRegistry_1 = require("./widgets/widgetPluginRegistry");
/**
* The root of the Dashboard business Logic
* Defines the lifecycle of the Dashboard from creation till disposal
*/
var Dashboard = (function () {
function Dashboard(_store) {
var _this = this;
this._store = _store;
this._initialized = false;
this._scriptsLoading = {};
this._datasourcePluginRegistry = new datasourcePluginRegistry_1.default(_store);
this._widgetPluginRegistry = new widgetPluginRegistry_1.default(_store);
_store.subscribe(function () {
// Whenever a datasource is added that is still loading, we create an instance and update the loading state
var state = _store.getState();
if (_this._lastLoadingUrls === state.pluginLoader.loadingUrls) {
return;
}
_this._lastLoadingUrls = state.pluginLoader.loadingUrls;
state.pluginLoader.loadingUrls.forEach(function (urlToLoad) {
Eif (!_this._scriptsLoading[urlToLoad]) {
_this.loadPluginScript(urlToLoad);
}
});
});
}
Dashboard.setInstance = function (dashboard) {
Dashboard._instance = dashboard;
};
/**
* We have some code that depends on this global instance of the Dashboard
* This is bad, but better that static references
* we have at least the chance to influence the instance during tests
*
* @returns {Dashboard}
*/
Dashboard.getInstance = function () {
Iif (!Dashboard._instance) {
throw new Error("No global dashboard created. Call setInstance(dashboard) before!");
}
return Dashboard._instance;
};
Object.defineProperty(Dashboard.prototype, "store", {
get: function () {
return this._store;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Dashboard.prototype, "datasourcePluginRegistry", {
get: function () {
return this._datasourcePluginRegistry;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Dashboard.prototype, "widgetPluginRegistry", {
get: function () {
return this._widgetPluginRegistry;
},
enumerable: true,
configurable: true
});
Dashboard.prototype.init = function () {
var _this = this;
Iif (this._initialized) {
throw new Error("Dashboard was already initialized. Can not call init() twice.");
}
this._initialized = true;
// TODO: Should not be needed but is still needed for unloading plugins and in some widget code
Dashboard.setInstance(this);
var state = this._store.getState();
var plugins = _.valuesIn(state.datasourcePlugins)
.concat(_.valuesIn(state.widgetPlugins));
plugins.forEach(function (plugin) {
_this._store.dispatch(Plugins.reloadExistingPlugin(plugin.url, plugin.id));
});
};
Dashboard.prototype.dispose = function () {
this._datasourcePluginRegistry.dispose();
this._widgetPluginRegistry.dispose();
};
/**
* Load plugin from URL
*/
Dashboard.prototype.loadPluginScript = function (url) {
var _this = this;
var loadScriptsPromise = scriptLoader_1.default.loadScript([url]);
this._scriptsLoading[url] = loadScriptsPromise.then(function () {
Eif (PluginCache.hasPlugin()) {
// TODO: use a reference to the pluginCache and only bind that instance to the window object while the script is loaded
// TODO: The scriploader can ensure that only one script is loaded at a time
var plugin = PluginCache.popLoadedPlugin();
return _this.loadPluginScriptDependencies(plugin, url);
}
else {
return Promise.reject(new Error("Failed to load Plugin. Make sure it called window.iotDashboardApi.register***Plugin from url " + url));
}
}).then(function (plugin) {
Eif (plugin.Datasource) {
_this._datasourcePluginRegistry.register(plugin);
_this._store.dispatch(Plugins.datasourcePluginFinishedLoading(plugin, url));
}
else if (plugin.Widget) {
_this._widgetPluginRegistry.register(plugin);
_this._store.dispatch(Plugins.widgetPluginFinishedLoading(plugin, url));
}
delete _this._scriptsLoading[url];
return Promise.resolve();
}).catch(function (error) {
console.warn("Failed to load script: ", error);
delete _this._scriptsLoading[url];
_this._store.dispatch(Plugins.pluginFailedLoading(url));
});
return this._scriptsLoading[url];
};
Dashboard.prototype.loadPluginScriptDependencies = function (plugin, url) {
// Do not load dependencies of widgets anymore, they are loaded inside the iFrame
Iif (plugin.TYPE_INFO.kind === "widget") {
return Promise.resolve(plugin);
}
var dependencies = plugin.TYPE_INFO.dependencies;
Iif (_.isArray(dependencies) && dependencies.length !== 0) {
var dependencyPaths = dependencies.map(function (dependency) {
return URI(dependency).absoluteTo(url).toString();
});
console.log("Loading Dependencies for Plugin", dependencyPaths);
return scriptLoader_1.default.loadScript(dependencyPaths).then(function () {
return Promise.resolve(plugin);
});
}
else {
return Promise.resolve(plugin);
}
};
return Dashboard;
}());
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = Dashboard;
|