Commit 3cce33e5 authored by David Hoksza's avatar David Hoksza
Browse files

initial commit

parents
Pipeline #9927 failed with stages
in 37 seconds
image: node
before_script:
stages:
- build
- deploy
build:
stage: build
script:
- npm install
- npm run build
deploy:
stage: deploy
only:
- master
script:
- eval $(ssh-agent -s)
- ssh-add <(echo "$SSH_PRIVATE_KEY")
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
- npm install
- npm run build
- echo "mkdir plugins-www/annotation-linker" | sftp -P 8022 gitlab-ci@10.240.6.160
- echo "put dist/plugin.js plugins-www/annotation-linker/" | sftp -P 8022 gitlab-ci@10.240.6.160
# Annotations linker
`Annotations linker` is a plugin which allows the users to open html links
containing placeholders to be filled with a text string comming from a
selected annotation.
![Plugin example](img/printscreen.png)
### General instructions
In order to use the precompiled and publicly available version of the plugin,
open the plugin menu in the MINERVA's upper left corner (see image below) and click plugins.
In the dialog which appears enter the following address in the URL box:
`https://minerva-dev.lcsb.uni.lu/plugins/annotations-linker/plugin.js` .
The plugin shows up in the plugins panel on the right hand side of the screen.
### Plugin functionality
The plugin listens to search and click events of the map. When an element is chosen, the plugin prints
the element's name together with all its annotations. If the address is set, annotations IDs are converted
to hyperlinks on the basis of the entered address; each occurrence of curly braces {}
in the address is replaced by the respective annotation ID.
The address is stored in the browser's cookies and thus needs to be entered only ones or after
the cookies are cleaned.
{
"name": "annotation-linker",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build-css": "node-sass --include-path src/css src/css/styles.scss src/css/styles.css",
"build": "mkdirp dist && npm run build-css && browserify -t [ babelify --presets es2015 ] -t browserify-css src/js/index.js | uglifyjs --compress --mangle > dist/plugin.js ",
"build-debug": "mkdirp dist && npm run build-css && browserify -t [ babelify --presets es2015 ] -t browserify-css src/js/index.js> dist/plugin.js ",
"watch-js": "mkdirp dist && npm run build-css && watchify -v -t [ babelify --presets es2015 ] -t browserify-css src/js/index.js -o dist/plugin.js",
"clean": "rimraf dist"
},
"author": "David Hoksza",
"license": "MIT",
"devDependencies": {
"babel-core": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"babelify": "^8.0.0",
"browserify": "^14.5.0",
"browserify-css": "^0.13.1",
"mkdirp": "^0.5.1",
"node-sass": "^4.6.1",
"rimraf": "latest",
"uglify-js": "^3.1.9"
},
"dependencies": {
"bootstrap-table": "^1.12.1",
"bootstrap-treeview": "github:diegokogan/bootstrap-treeview",
"html-linkify": "^1.2.2"
}
}
$pluginName: annotation-linker;
.#{$pluginName}-container {
padding: 15px;
}
.#{$pluginName}-container .al_annotations_label{
font-weight: bold;
padding-bottom: 10px;
}
.#{$pluginName}-container .al_warning {
margin-top: 10px;
margin-bottom: 0px;
}
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for(var i = 0; i <ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
function setCookie(cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays*24*60*60*1000));
var expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
module.exports = {
getCookie: getCookie
, setCookie: setCookie
}
\ No newline at end of file
require('../css/styles.css');
const cookies = require('./cookies');
const pluginName = 'annotation-linker';
const pluginLabel = 'Annotation linker';
const pluginVersion = '1.0.0';
const cookieKey = 'minerva-plugin-annotation-linker-address'
const globals = {
selected: []
};
// ******************************************************************************
// ********************* PLUGIN REGISTRATION WITH MINERVA *********************
// ******************************************************************************
let minervaProxy;
let pluginContainer;
let pluginContainerId;
const register = function(_minerva) {
// console.log('registering ' + pluginName + ' plugin');
$(".tab-content").css('position', 'relative');
minervaProxy = _minerva;
pluginContainer = $(minervaProxy.element);
pluginContainerId = pluginContainer.attr('id');
if (!pluginContainerId) {
//the structure of plugin was changed at some point and additional div was added which is the container but does not have any properties (id or height)
pluginContainer.css('height', '100%');
pluginContainerId = pluginContainer.parent().attr('id');
}
// console.log('minerva object ', minervaProxy);
// console.log('project id: ', minervaProxy.project.data.getProjectId());
// console.log('model id: ', minervaProxy.project.data.getModels()[0].modelId);
initPlugin();
};
const unregister = function () {
// console.log('unregistering ' + pluginName + ' plugin');
unregisterListeners();
return deHighlightAll();
};
const getName = function() {
return pluginLabel;
};
const getVersion = function() {
return pluginVersion;
};
const notifyError = function(data) {
console.error(data);
};
/**
* Function provided by Minerva to register the plugin
*/
minervaDefine(function (){
return {
register: register,
unregister: unregister,
getName: getName,
getVersion: getVersion
,notifyError: notifyError
,minWidth: 300
,defaultWidth: 600
}
});
function initPlugin () {
const container = initMainContainer();
initMainPageStructure(container);
registerListeners();
}
function registerListeners(){
minervaProxy.project.map.addListener({
dbOverlayName: "search",
type: "onSearch",
callback: searchListener
});
}
function unregisterListeners() {
minervaProxy.project.map.removeAllListeners();
}
// ****************************************************************************
// ********************* MINERVA INTERACTION*********************
// ****************************************************************************
function deHighlightAll(){
return minervaProxy.project.map.getHighlightedBioEntities().then( highlighted => minervaProxy.project.map.hideBioEntity(highlighted) );
}
// ****************************************************************************
// ********************* PLUGIN STRUCTURE AND INTERACTION*********************
// ****************************************************************************
function getContainerClass() {
return pluginName + '-container';
}
function initMainContainer(){
const container = $(`<div class="${getContainerClass()}"></div>`).appendTo(pluginContainer);
return container;
}
function initMainPageStructure(container){
container.append(`
<div class="panel panel-default al-settings">
<div class="panel-heading" data-toggle="collapse" data-target="#al_panel_${pluginContainerId}">
Address
<span class="pull-right glyphicon glyphicon-chevron-down">
</div>
<div id="al_panel_${pluginContainerId}" class="panel-body panel-default panel-collapse collapse">
<input type="text" title="Address with {} as a placeholder" class="form-control al_link" name="msg"
placeholder="https://domain/{}" value="${cookies.getCookie(cookieKey)}">
</div>
</div>
<div class="panel panel-default">
<div class="panel-body al_annotations">
<div class="row">
<div class="col-md-4 al_annotations_label">Selected species: </div>
<div class="col-md-8 al_selected_species"></div>
</div>
<div class="row">
<div class="col-md-4 al_annotations_label">Annotations: </div>
<div class="col-md-8 al_selected_species_annotations"></div>
</div>
</div>
</div>
`);
container.keyup(function (e){
cookies.setCookie(cookieKey, $(e.target).val());
})
}
function cleanAnnotations(){
pluginContainer.find('.al_selected_species').empty();
pluginContainer.find('.al_selected_species_annotations').empty();
pluginContainer.find('.al_warning').remove();
}
const unique = function(value, index, self){
for (let i = 0; i < self.length; i++){
if (self[i][0] === value[0] && self[i][1] === value[1]) {
return i === index;
}
}
};
const sortPair = function (p1, p2) {
if (p1[0] == p2[0]) {
if (p1[1] < p2[1]) return -1;
else if (p1[1] === p2[1]) return 0;
else return 1;
} else {
if (p1[0] < p2[0]) return -1;
else if (p1[0] === p2[0]) return 0;
else return 1;
}
};
function getAddress() {
return pluginContainer.find('.al_link').val();
}
function setAddress(address) {
pluginContainer.find('.al_link').val(address);
}
function searchListener(entites){
// console.log(globals.selected);
if (entites[0].length > 0) {
globals.selected = entites[0];
cleanAnnotations();
const e = globals.selected[0];
const name = 'getName' in e ? e.getName() : e.getReactionId();
pluginContainer.find('.al_selected_species').text(name);
const annotContainer = pluginContainer.find('.al_selected_species_annotations');
const link = getAddress();
e.getReferences()
.map(annot=>[annot.getType(), annot.getResource()])
.filter(unique)
.sort(sortPair)
.forEach(ann => {
let annLabel = ann[0];
let annValue = ann[1];
if (link.trim() !== "") {
let address = link.replace(/\{\}/g, ann[1]);
annValue = `<a href="${address}" target="_blank">${ann[1]}</a>`;
}
annotContainer.append(`<div class="row">
<div class="col-md-5 al_annotation_label">${annLabel}:</div>
<div class="col-md-7 al_annotation_value">${annValue}</div>
</div>`);
});
if (link.trim() === "") {
pluginContainer.find(".al_annotations").append(`<div class="alert alert-danger al_warning" role="alert">
Please specify the address and select the species again.
</div>`);
return;
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment