UNPKG

chupim-web

Version:

A Web Pipeline Framework to build APIs

409 lines (341 loc) 10.4 kB
var selectedItem; var pressedKey = undefined; var fixedNodes = ['Input','Output']; var points = []; var prefixColors = [ {bg:'#5899DA',fg:'#fff'}, {bg:'#E8743B', fg:'#fff'}, {bg:'#19A979',fg:'#fff'}, {bg:'#ED4A7B', fg:'#fff'}, {bg:'#945ECF', fg:'#fff'}, {bg:'#13A4B4', fg:'#fff'}, {bg:'#525DF4', fg:'#fff'}, {bg:'#BF399E', fg:'#fff'}, {bg:'#6C8893', fg:'#fff'}, {bg:'#EE6868', fg:'#fff'}, {bg:'#2F6497', fg:'#fff'} ]; var prefixColorMap = {}; var prefixColorIndx = 0; var defaultElements = { nodes: [ { data: { id: fixedNodes[0], type:'source', label:`${fixedNodes[0]}`}, classes:'fixed-node' }, { data: { id: fixedNodes[1], type:'sink', label:`${fixedNodes[1]}`}, classes:'fixed-node' } ], edges: [ ] }; var cy; var css = cytoscape.stylesheet() .selector('node') .css({ 'content': 'data(label)', 'text-opacity': 1.0, 'text-valign': 'center', 'text-halign': 'center', 'background-color': '#eee', 'color':'#666', 'height': '30', 'border-width':'1', 'border-color':'#fff', 'shape':'roundrectangle', 'font-size': '12px', 'font-family':'Inconsolata' }) .selector('edge') .css({ 'curve-style': 'bezier', 'width': 1, 'arrow-scale':'1', 'target-arrow-shape': 'triangle', 'line-color': '#666', 'target-arrow-color': '#666' }) .selector('.fixed-node') .css({ 'content': 'data(label)', 'color':'#666', 'width': '60', 'shape': 'tag', 'border-color':'#888', 'padding':'0px' }) .selector('.selected') .css({ 'border-color':'#f00', 'line-color': '#f00', 'target-arrow-color': '#f00', 'border-width': '2px' }); function buildGraph(el){ cy = window.cy = cytoscape({ container: document.getElementById('workspace'), boxSelectionEnabled: true, autounselectify: false, zoom: 10, pan: { x: 0, y: 0 }, minZoom: 0.6345643593969714, maxZoom: 10, zoomingEnabled: true, userZoomingEnabled: true, elements: el, layout: { name: 'dagre' }, style: css }); cy.on('select', 'node', function(evt){ var element = evt.target; if(selectedItem != undefined && selectedItem !== element){ connectElements(selectedItem, element); }else{ element.addClass('selected'); selectedItem = evt.target; } }); cy.on('unselect', 'node', function(evt){ var element = evt.target; element.removeClass('selected'); if(pressedKey != 17){ selectedItem = undefined; } }); cy.on('select', 'edge', function(evt){ var element = evt.target; element.addClass('selected'); selectedItem = element; }); cy.on('unselect', 'edge', function(evt){ var element = evt.target; element.removeClass('selected'); if(pressedKey != 17){ selectedItem = undefined; } }); } function hasConnectionBetween(sourceElement, targetElement){ var sourceId = sourceElement.json().data.id; var targetId = targetElement.json().data.id; var has = false; if(cy.json().elements.edges == undefined) return false; cy.json().elements.edges.map( e => { if( (e.data.source == sourceId && e.data.target == targetId) || (e.data.source == targetId && e.data.target == sourceId))has = true; }); return has; } function connectElements(sourceElement, targetElement){ if(sourceElement === targetElement)return; // var sourceType = sourceElement.json().data.type; // var targetType = targetElement.json().data.type; generateComponent(); if(hasConnectionBetween(sourceElement, targetElement)){ return; } cy.add({ group: "edges", data: { source: sourceElement.data().id, target: targetElement.data().id } }); sourceElement.removeClass('selected'); targetElement.addClass('selected'); sourceElement.deselect(); selectedItem = targetElement; } window.addEventListener("keydown", function(e,obj){ if( (e.keyCode == 127 || e.keyCode == 8) && selectedItem != undefined && isDeleteable(selectedItem)){ cy.remove(selectedItem); selectedItem = undefined; } if(e.keyCode == 27 && selectedItem != undefined){ selectedItem.toggleClass('selected'); selectedItem = undefined; } if(e.keyCode == 83 && pressedKey == 17){ savePipeline(); e.preventDefault(); } pressedKey = e.keyCode; }); window.addEventListener("keyup", function(e){ if(e.keyCode == pressedKey)pressedKey = undefined; }); $(document).ready(function(){ var forms = document.getElementsByClassName('needs-validation'); Array.prototype.filter.call(forms, function(form) { form.addEventListener('submit', function(event) { if (form.checkValidity() === false) { event.preventDefault(); event.stopPropagation(); } form.classList.add('was-validated'); }, false); }); $('#pipeline-save-form').submit(validatePipelineForm); var packageList = []; $('h5.stage-prefix').each( (a,b) => packageList.push(hash(b.innerText))); for(var i=0; i<packageList.length; i++){ var p = packageList[i]; var colors = getPrefixColor(p); css.selector(`.${p}`).css({ 'background-color':colors.bg, 'color':colors.fg }); } var elements = $('#edit-component').val(); if(elements){ elements = JSON.parse(elements); elements.nodes.forEach(e => { if(!fixedNodes.includes(e.data.id)){ e.classes = hash(e.data.type); }else{ e.classes='fixed-node'; } e.data.label += "()"; }); buildGraph(elements); }else{ buildGraph(defaultElements); } render(); $('.stages').click(function(){ var type = $(this).attr('data-type'); var rootId = $(this).attr('data-name'); var configName = `${type}.${rootId}`; rootId = rootId.substring(0,1).toUpperCase()+rootId.substring(1)+"()"; var width = (rootId.length*8)+4; cy.add({ group: "nodes", data: { type:type, configName:configName, label:rootId}, style:{width: width}, classes: hash(type), position: { x: 100, y: 30 } }); }); $('#menu-pipeline-save').click(savePipeline); }); function savePipeline(){ generateComponent(); var pipeline = extractSerialPipeline(points[fixedNodes[0]]); $('#pipeline-save-form input[name=stages]').val(JSON.stringify(pipeline)); $('#pipeline-save-form input[name=elements]').val(JSON.stringify(cy.json().elements)); $('#pipeline-save-modal').modal({}); return false; } function render(){ if(cy.json().elements.nodes){ cy.json().elements.nodes.forEach(element => { if(fixedNodes.includes(element.data.id))return; var width = element.data.label.length*8+4; var e = cy.getElementById(element.data.id); e.style({width:width}); }); } } function isDeleteable(element){ if(element != undefined && !fixedNodes.includes(element.id())){ return true; }else{ return false; } } function generateComponent(){ //var nodes = cy.json().elements.nodes == undefined?[]:cy.json().elements.nodes; var edges = cy.json().elements.edges == undefined?[]:cy.json().elements.edges; points = []; for(var i=0; i< edges.length; i++){ var edge = edges[i]; var n = cy.getElementById(edge.data.source).json(); if(Object.keys(points).includes(n.data.id)){ n = points[n.data.id]; }else{ points[n.data.id] = n; } var c = cy.getElementById(edge.data.target).json(); if(Object.keys(points).includes(c.data.id)){ c = points[c.data.id]; }else{ points[c.data.id] = c; } if(n.children == undefined){ n.children = []; } if(c.parents == undefined){ c.parents = []; } n.children[c.data.id] = c; c.parents[n.data.id] = n; } } function extractSerialPipeline(node, pipeline){ if(node == undefined)return; if(pipeline == undefined) pipeline = new Array(); if(node.data != undefined && node.data.configName != undefined){ pipeline.push(node.data.configName); } if(node.children != undefined){ var child; if(Object.keys(node.children).length > 1){ child = extractParallelPipeline(node.children, pipeline); return extractSerialPipeline(child, pipeline); }else{ var key = Object.keys(node.children)[0]; child = node.children[key]; if( Object.keys(child.parents).length == 1){ extractSerialPipeline(child, pipeline); }else{ return child; } } } return pipeline; } function extractParallelPipeline(children, pipeline){ if(pipeline == undefined) pipeline = new Array(); var lastChild; var parallelPipeline = new Array(); for(var i=0; i< Object.keys(children).length; i++){ var key = Object.keys(children)[i]; var child = children[key]; var localParallelPipeline = new Array(); lastChild = extractSerialPipeline(child, localParallelPipeline); parallelPipeline.push(localParallelPipeline); } pipeline.push(parallelPipeline); return lastChild; } function getPrefixColor(type){ if(prefixColorMap[type] == undefined){ prefixColorMap[type] = prefixColorIndx; prefixColorIndx++; if(prefixColorIndx > prefixColors.length-1)prefixColorIndx = 0; return prefixColors[prefixColorMap[type]]; }else{ return prefixColors[prefixColorMap[type]]; } } function validatePipelineForm(){ var name = document.forms["newPipelineForm"]["name"].value; if(name == undefined || name.trim() == ""){ $(document.forms["newPipelineForm"]["name"]).addClass('invalid'); return false; } var path = document.forms["newPipelineForm"]["path"].value; if(path == undefined || path.trim() == ""){ return false; } var stages = document.forms["newPipelineForm"]["stages"].value; if(stages == undefined || stages.trim() == ""){ $(document.forms["newPipelineForm"]["stages"]).siblings('.invalid-feedback').show(); return false; } var elements = document.forms["newPipelineForm"]["elements"].value; if(elements == undefined || elements.trim() == ""){ $(document.forms["newPipelineForm"]["stages"]).siblings('.invalid-feedback').show(); return false; } return true; } function hash(str){ if(str != undefined){ str = str.trim().toLowerCase(); return Array.from(str).map( c => c.charCodeAt(0).toString(16) ).join("").toUpperCase(); } throw new Error("Invalid string"); }