If you need some specific configurations to be saved for your plugin, that you would need on each request (and maybe even want to allow user to change the configuration value), then you can use shared document to store your configuration.
Since shared configurations are stored in database, they will be shared between both api and frontend sides, as well as between multiple processes on different cpu cores and between multiple server instances.
Setting up configurations
Starting using shared documents is easy, all you need to call is plugins.setConfigs method and pass your plugin namespace and default values for your configurations.
var plugins = require('../plugins/pluginManager.js');
plugins.setConfigs("ourplugin", {
config1: "value1",
config2: false,
config3: 120
});
You should do it as soon as possible (preferably right after you required plugins manager). And you can use it either on api side or on frontend side (configs will be stored in database and shared between processes either way, so it does not matter on which side you set them up).
If you want your configurations to be available in Web UI under Management -> Configurations, your configuration name should match your plugin name. If you want your configurations to be excluded from Web UI, then either provide a name that does not match your plugin or provide third parameter true .
plugins.setConfigs("ourplugin_hidden", {
config1: "value1",
config2: false,
config3: 120
}, true);
You can use multiple namespaces for your plugin, just make sure it does not collide with other plugin namespaces, so at least try to prefix them with your plugin name. Just remember, only your plugin namespace will appear on Configurations UI, all other will be hidden from it and are made for internal use.
Getting configuration values
Since the configuration values might change (either by user in config UI, or simply changes by other server instances), it is NOT recommended to load your configs once and then use them.
It is better to load your configs on per request bases (as they are guarantee not to change during same request, but might change between different requests), or even better simply load them on per need basis, using getConfig method and providing your namespace.
In rare cases when configurations cannot be loaded, getConfig method is guaranteed to at least provide empty object, so you can easily fallback to default values.
var somevalue = plugins.getConfig("ourplugin").config1 || default_value;
Updating configurations
If for some reason you need to update configuration, you can add it to setConfigs method on next process start and it will take new values that don't exist in old configuration.
But what if you don't want to wait till next process start, like your are storing different properties for different apps, and now new app was added and you want to update configs to add new app properties. You can also update configs directly using updateConfigs method, where you need to pass db object, your namespace and new properties to add.
//for example we have an object as
plugins.setConfigs("ourplugin", {
ob1:{
subob1:{
prop1:"value1"
}
}
};
//if we want to add prop2 to subob1, then we update configs like this
plugins.updateConfigs(common.db, "ourplugin", {ob1:{subob1:{prop2:"value2"}}}, function(){
//config updated
console.log("done");
});
After that config will be updated and new values available on next request.
Web UI for configurations
Plugin manager also automatically generates UI (if the configuration is not excluded) to allow global administrator to change your provided configurations. It will check your data type and will provide switches for boolean values, HTML5 number input for numbers and text input for text values.
If you can not see your plugin configuration here, please make sure you set the key name as same as plugin name and enabled the plugin.
Customizing Web UI inputs
But you can also hide specific configuration keys or provide custom input types for your plugin's configuration options.
You can do that by using registerInput function of configurationView, on the browser side, once document is loaded. You need to provide "path" (separated by dots) to your configuration value and either return null to hide the value or return HTML code to replace the standard input with.
So if you set such configuration for example:
plugins.setConfigs("ourplugin", {
subobject:{
subproperty:10
},
config1: "value1",
config2: false,
config3: 120
});
Then to hide subobject's subproperty from input you would need to register such function:
$( document ).ready(function() {
//check if configuration view exists
if(app.configurationsView){
app.configurationsView.registerInput("ourplugin.subobject.subproperty", function(value){
//no html for this input, will hide it
return null;
});
}
});
But to override default text input for config1, you would need to firstly provide HTML code for your custom input (of course you can also style it as you want)
$( document ).ready(function() {
//check if configuration view exists
if(app.configurationsView){
app.configurationsView.registerInput("ourplugin.config1", function(value){
//return HTML code to textarea
return "<textarea id='ourplugin.config1' class='mytextarestyle'>"+value+"</textarea>";
});
}
});
As well as then handle it's value changes and set them to configurations view's updateConfig method
app.addPageScript("/manage/configurations", function(){
if(app.configurationsView){
$("#ourplugin.config1").keyup(function () {
//value might have changed
var id = $(this).attr("id");
var value = $(this).val();
//let's notify configuration view about possible changes
app.configurationsView.updateConfig(id, value);
});
}
});
Customizing Web UI labels
Similar way as inputs, you can also provide custom HTML for labels, including translating them in current language and providing help tooltips, etc.
For provided example:
plugins.setConfigs("ourplugin", {
subobject:{
subproperty:10
},
config1: "value1",
config2: false,
config3: 120
});
By default we will look for localization keys as: Your category name: ourplugin.plugin-title or ourplugin.title Your property label name for config1: ourplugin.config1 or configs.ourplugin-config1 Your property explanation for config1: configs.help.ourplugin-config1
Just put them in your localization file for configuration to pick them up automatically in UI.
Or you can override/provide property label name programmatically. To overwrite default label name, simply use registerLabel method of configurationView and pass label id and html code to replace it with.
$( document ).ready(function() {
//check if configuration view exists
if(app.configurationsView){
// provide html label directly
app.configurationsView.registerLabel("ourplugin.subobject.subproperty",
"Subproperty");
// or provide localized string to use value from
app.configurationsView.registerLabel("ourplugin.subobject.subproperty",
"ourplugin.help.subproperty");
}
});
Plugin specific configuration page
If you want to provide edit settings button on your plugin's view and direct user to your plugin specific configuration page (with options only for your specific plugin's namespace), then you can point that button to "#/manage/configurations/namespace" (of course, replacing namespace with your configs namespace).
And user will be redirected to the page with configs only from that namespace, and would be allowed to change them and also provided a back button to return back to your plugin's view.
Notice
When your plugin has some configuration in UI, please avoid using plugin name contains "."(like "*countly.aws.kinesis"). Which may cause not show the configuration form in the UI.