eLabConnect
Use eLabconnect with your add-on
Use eLabConnect with your add-on
Lab instruments and devices are used on a daily basis in almost every workflow in the lab. These devices allow scientists to analyse, store, handle samples, and collect data during the experimentation process.
As a result, it is crucial to fully track any event that occurs during an experiment and be aware of those events when the need arises. Read more
Prerequisites
In order to support eLabConnect in your add-on the following line has to be added to your add-on code context.hasFileMonitoringSupport = true;
. The implementation can be found in the example code below.
Local development
During normal production conditions, plugins that want to use eLABConnect need to own a unique pluginID. This plugin ID is automatically issued upon installation into production. This poses a challenge during development, as no pluginID has been issued yet and the script is being side-loaded.
To solve this issue, the sandbox environment has the eLabSync
plugin installed. This plugin should be made available to your account. If this is not the case, please ask your contact within eLabNext to enable. You can review installed plugins by going to the eLabNext Marketplace. This plugin has the pluginID 320
and can be re-used in your own plugin during development.
This is simply done by making sure to use pluginID 320
during the fetching of files from the API. The sample plugin contained in the example below includes boiler-plate code to demonstrate how that is done.
Steps to demonstrate the upload and fetching of files using eLABConnect
- Install eLABConnect at the workstation that uploads your files Download
- Login to the sandbox environment
- Go to eLabNext Marketplace
- Follow the prompts in eLABConnect to choose the folder to monitor for automatic uploads
- Place a plain text file with at least 20 lines of text in the folder (ending with .txt). eLABConnect will start
uploading - Side-load the example code below and run your code to fetch the files. For sandbox.elabjournal.com, use
320
as
the forcePluginID parameter, which is the ID of the eLABConnect Placeholder for development plugin. This allows
you to use the side-loading of your plugin that doesn’t have a pluginID on itself - Monitor the Console Logger of your browser. You should see an XML requests with a response from the API that
includes the fields - The example code below should alert the contents of the last text file uploaded
Remember to remove the ‘forcePluginID’ from your plugin before releasing into production to make sure it works as
intended
Example code
/*
@rootVar: FileParseExample
@name: File Parse Example
@version: 1.0.0
@description: Plugin that works together with eLABConnect
@author: Awesome Developer
*/
var FileParseExample = {};
(function (namespace) {
namespace.hasFileMonitoringSupport = true;
namespace.configurationSchema = function () {
return {
"max_file_age": {
"title": "Maximum File Age (hours)",
"type": "integer",
"default": 168
}
};
},
context.init = function (config) {
document.addEventListener('DOMContentLoaded', () => {
context.myExampleAddon = new context.myExampleAddon(config);
});
};
namespace.myExampleAddon = new Class({
Implements: [Options, Events],
options:{
content: 'data that will be logged to the console',
forcePluginID: 'Override pluginID for testing/sandbox purposes to make eLABConnect work without an installed instance of this plugin'
},
initialize: function (config) {
var defaultConfig = {
content: 'content',
forcePluginID: null,
max_file_age: 1000
};
config = $.extend(true, defaultConfig, config);
this.setOptions(config);
this.render();
},
render: function (config) {
const self = this;
const content= this.options.content;
self.getFiles(function (sampleFiles) {
// Load the first file (if any) and output to console
if (sampleFiles.length > 0) {
const pluginFileID = sampleFiles[0].sdkPluginFileID;
self.loadDataFromFile(pluginFileID, function (content) {
console.log(content);
Dialog.show({
width: '450',
title: 'Plugin loaded',
content: ('<div style="background-color:#fff;padding:5px;margin-top:10px;"> File contents:<br/> ' + content + '</div>'),
btnOkLabel: 'Close',
btnCancel: false
});
});
} else {
Dialog.alert('No files found yet', 'No uploaded files found yet');
}
});
},
destroy: function(){
Dialog.close();
},
returnValidData: function (sampleFiles, maxFileAge) {
if(!sampleFiles.length) return [];
return sampleFiles.filter(s => new Date(s.lastModified) > maxFileAge);
},
getFiles: function (callback) {
const _self = this;
const sdkPluginID = _self.options.forcePluginID !== null ? _self.options.forcePluginID : _self.options.pluginID;
const maxFileAge = _self.options.max_file_age;
const thisFileAge = new Date(new Date() - maxFileAge * 1000 * 3600);
fetch(`/api/v1/plugins/${sdkPluginID}/files?$sort=lastModified%20desc&$expand=meta`)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
const sampleFiles = [];
if (typeof data.data !== 'undefined' && data.data.length > 0) {
data.data.forEach(o => {
sampleFiles.push(o);
});
}
if (location.hostname.split('.')[0] !== 'sandbox') {
sampleFiles = _self.returnValidData(sampleFiles, thisFileAge);
}
callback(sampleFiles);
})
.catch(error => {
console.error('Error:', error);
});
},
loadDataFromFile: function (pluginFileID, callBack) {
var _self = this;
if (pluginFileID === 0) {
Dialog.close();
Dialog.show({
title: '<i class="fa fa-exclamation-circle" style="color:red;margin-right:5px;font-size:14px;"></i>Invalid file or filename',
content: 'The file or filename that was given is invalid or does not exist.',
btnOkLabel: 'Close',
btnCancel: false
});
} else {
fetch(`/api/v1/plugins/files/${pluginFileID}/download`)
.then(response => {
if (!response.ok) {
if (response.status === 404) {
// Handle 404 status
} else {
throw new Error('Network response was not ok');
}
}
return response.json();
})
.then(data => {
callBack(data);
})
.catch(error => {
console.error('Error:', error);
});
}
}
});
// This need to be called to make the add-on active via the developer tab inside eLab. When the add-on is added to the marketplace, this is not needed anymore.
context.init({
forcePluginID: 320 // Please remove in production
});
})(FileParseExample);
Updated 8 months ago