v;v++)mxEdgeStyle.limits[v][1]=
-n[v][0]-A[v],mxEdgeStyle.limits[v][2]=n[v][1]-A[v],mxEdgeStyle.limits[v][4]=n[v][0]+n[v][2]+A[v],mxEdgeStyle.limits[v][8]=n[v][1]+n[v][3]+A[v];A=n[0][1]+n[0][3]/2;p=n[1][1]+n[1][3]/2;v=n[0][0]+n[0][2]/2-(n[1][0]+n[1][2]/2);B=A-p;A=0;0>v?A=0>B?2:1:0>=B&&(A=3,0==v&&(A=2));p=null;null!=b&&(p=l);b=[[.5,.5],[.5,.5]];for(v=0;2>v;v++)null!=p&&(b[v][0]=(p.x-n[v][0])/n[v][2],1>=Math.abs(p.x-n[v][0])?a[v]=mxConstants.DIRECTION_MASK_WEST:1>=Math.abs(p.x-n[v][0]-n[v][2])&&(a[v]=mxConstants.DIRECTION_MASK_EAST),
-b[v][1]=(p.y-n[v][1])/n[v][3],1>=Math.abs(p.y-n[v][1])?a[v]=mxConstants.DIRECTION_MASK_NORTH:1>=Math.abs(p.y-n[v][1]-n[v][3])&&(a[v]=mxConstants.DIRECTION_MASK_SOUTH)),p=null,null!=c&&(p=m);v=n[0][1]-(n[1][1]+n[1][3]);m=n[0][0]-(n[1][0]+n[1][2]);p=n[1][1]-(n[0][1]+n[0][3]);q=n[1][0]-(n[0][0]+n[0][2]);mxEdgeStyle.vertexSeperations[1]=Math.max(m-z,0);mxEdgeStyle.vertexSeperations[2]=Math.max(v-z,0);mxEdgeStyle.vertexSeperations[4]=Math.max(p-z,0);mxEdgeStyle.vertexSeperations[3]=Math.max(q-z,0);z=[];
-c=[];l=[];c[0]=m>=q?mxConstants.DIRECTION_MASK_WEST:mxConstants.DIRECTION_MASK_EAST;l[0]=v>=p?mxConstants.DIRECTION_MASK_NORTH:mxConstants.DIRECTION_MASK_SOUTH;c[1]=mxUtils.reversePortConstraints(c[0]);l[1]=mxUtils.reversePortConstraints(l[0]);m=m>=q?m:q;p=v>=p?v:p;q=[[0,0],[0,0]];r=!1;for(v=0;2>v;v++)0==a[v]&&(0==(c[v]&d[v])&&(c[v]=mxUtils.reversePortConstraints(c[v])),0==(l[v]&d[v])&&(l[v]=mxUtils.reversePortConstraints(l[v])),q[v][0]=l[v],q[v][1]=c[v]);0v;v++)0==a[v]&&(0==(q[v][0]&d[v])&&(q[v][0]=q[v][1]),z[v]=q[v][0]&d[v],z[v]|=(q[v][1]&d[v])<<8,z[v]|=(q[1-v][v]&d[v])<<16,z[v]|=(q[1-v][1-v]&d[v])<<24,0==(z[v]&15)&&(z[v]<<=8),0==(z[v]&3840)&&(z[v]=z[v]&15|z[v]>>8),0==(z[v]&
-983040)&&(z[v]=z[v]&65535|(z[v]&251658240)>>8),a[v]=z[v]&15,d[v]==mxConstants.DIRECTION_MASK_WEST||d[v]==mxConstants.DIRECTION_MASK_NORTH||d[v]==mxConstants.DIRECTION_MASK_EAST||d[v]==mxConstants.DIRECTION_MASK_SOUTH)&&(a[v]=d[v]);d=a[0]==mxConstants.DIRECTION_MASK_EAST?3:a[0];z=a[1]==mxConstants.DIRECTION_MASK_EAST?3:a[1];d-=A;z-=A;1>d&&(d+=4);1>z&&(z+=4);d=mxEdgeStyle.routePatterns[d-1][z-1];mxEdgeStyle.wayPoints1[0][0]=n[0][0];mxEdgeStyle.wayPoints1[0][1]=n[0][1];switch(a[0]){case mxConstants.DIRECTION_MASK_WEST:mxEdgeStyle.wayPoints1[0][0]-=
-f;mxEdgeStyle.wayPoints1[0][1]+=b[0][1]*n[0][3];break;case mxConstants.DIRECTION_MASK_SOUTH:mxEdgeStyle.wayPoints1[0][0]+=b[0][0]*n[0][2];mxEdgeStyle.wayPoints1[0][1]+=n[0][3]+f;break;case mxConstants.DIRECTION_MASK_EAST:mxEdgeStyle.wayPoints1[0][0]+=n[0][2]+f;mxEdgeStyle.wayPoints1[0][1]+=b[0][1]*n[0][3];break;case mxConstants.DIRECTION_MASK_NORTH:mxEdgeStyle.wayPoints1[0][0]+=b[0][0]*n[0][2],mxEdgeStyle.wayPoints1[0][1]-=f}f=0;c=z=0<(a[0]&(mxConstants.DIRECTION_MASK_EAST|mxConstants.DIRECTION_MASK_WEST))?
-0:1;for(v=0;v>5,p<<=A,15>=4),q=0<(d[v]&mxEdgeStyle.CENTER_MASK),(u||t)&&9>p?(r=u?0:1,p=q&&0==l?n[r][0]+b[r][0]*n[r][2]:q?n[r][1]+b[r][1]*
-n[r][3]:mxEdgeStyle.limits[r][p],0==l?(p=(p-mxEdgeStyle.wayPoints1[f][0])*m[0],0
e&&(e+=4);1>a&&(a+=4);b=routePatterns[e-1][a-1];0!=c&&0!=d||null==inlineRoutePatterns[e-1][a-
-1]||(b=inlineRoutePatterns[e-1][a-1]);return b}},mxStyleRegistry={values:[],putValue:function(a,b){mxStyleRegistry.values[a]=b},getValue:function(a){return mxStyleRegistry.values[a]},getName:function(a){for(var b in mxStyleRegistry.values)if(mxStyleRegistry.values[b]==a)return b;return null}};mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ELBOW,mxEdgeStyle.ElbowConnector);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ENTITY_RELATION,mxEdgeStyle.EntityRelation);
-mxStyleRegistry.putValue(mxConstants.EDGESTYLE_LOOP,mxEdgeStyle.Loop);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_SIDETOSIDE,mxEdgeStyle.SideToSide);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_TOPTOBOTTOM,mxEdgeStyle.TopToBottom);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_ORTHOGONAL,mxEdgeStyle.OrthConnector);mxStyleRegistry.putValue(mxConstants.EDGESTYLE_SEGMENT,mxEdgeStyle.SegmentConnector);mxStyleRegistry.putValue(mxConstants.PERIMETER_ELLIPSE,mxPerimeter.EllipsePerimeter);
-mxStyleRegistry.putValue(mxConstants.PERIMETER_RECTANGLE,mxPerimeter.RectanglePerimeter);mxStyleRegistry.putValue(mxConstants.PERIMETER_RHOMBUS,mxPerimeter.RhombusPerimeter);mxStyleRegistry.putValue(mxConstants.PERIMETER_TRIANGLE,mxPerimeter.TrianglePerimeter);mxStyleRegistry.putValue(mxConstants.PERIMETER_HEXAGON,mxPerimeter.HexagonPerimeter);function mxGraphView(a){this.graph=a;this.translate=new mxPoint;this.graphBounds=new mxRectangle;this.states=new mxDictionary}mxGraphView.prototype=new mxEventSource;
-mxGraphView.prototype.constructor=mxGraphView;mxGraphView.prototype.EMPTY_POINT=new mxPoint;mxGraphView.prototype.doneResource="none"!=mxClient.language?"done":"";mxGraphView.prototype.updatingDocumentResource="none"!=mxClient.language?"updatingDocument":"";mxGraphView.prototype.allowEval=!1;mxGraphView.prototype.captureDocumentGesture=!0;mxGraphView.prototype.optimizeVmlReflows=!0;mxGraphView.prototype.rendering=!0;mxGraphView.prototype.graph=null;mxGraphView.prototype.currentRoot=null;
-mxGraphView.prototype.graphBounds=null;mxGraphView.prototype.scale=1;mxGraphView.prototype.translate=null;mxGraphView.prototype.states=null;mxGraphView.prototype.updateStyle=!1;mxGraphView.prototype.lastNode=null;mxGraphView.prototype.lastHtmlNode=null;mxGraphView.prototype.lastForegroundNode=null;mxGraphView.prototype.lastForegroundHtmlNode=null;mxGraphView.prototype.getGraphBounds=function(){return this.graphBounds};mxGraphView.prototype.setGraphBounds=function(a){this.graphBounds=a};
-mxGraphView.prototype.getBounds=function(a){var b=null;if(null!=a&&0
-c.length||null==c[0]||null==c[c.length-1])?this.clear(a.cell,!0):(this.updateEdgeBounds(a),this.updateEdgeLabelOffset(a)))};
-mxGraphView.prototype.updateVertexLabelOffset=function(a){var b=mxUtils.getValue(a.style,mxConstants.STYLE_LABEL_POSITION,mxConstants.ALIGN_CENTER);if(b==mxConstants.ALIGN_LEFT)b=mxUtils.getValue(a.style,mxConstants.STYLE_LABEL_WIDTH,null),b=null!=b?b*this.scale:a.width,a.absoluteOffset.x-=b;else if(b==mxConstants.ALIGN_RIGHT)a.absoluteOffset.x+=a.width;else if(b==mxConstants.ALIGN_CENTER&&(b=mxUtils.getValue(a.style,mxConstants.STYLE_LABEL_WIDTH,null),null!=b)){var c=mxUtils.getValue(a.style,mxConstants.STYLE_ALIGN,
-mxConstants.ALIGN_CENTER),d=0;c==mxConstants.ALIGN_CENTER?d=.5:c==mxConstants.ALIGN_RIGHT&&(d=1);0!=d&&(a.absoluteOffset.x-=(b*this.scale-a.width)*d)}b=mxUtils.getValue(a.style,mxConstants.STYLE_VERTICAL_LABEL_POSITION,mxConstants.ALIGN_MIDDLE);b==mxConstants.ALIGN_TOP?a.absoluteOffset.y-=a.height:b==mxConstants.ALIGN_BOTTOM&&(a.absoluteOffset.y+=a.height)};mxGraphView.prototype.resetValidationState=function(){this.lastForegroundHtmlNode=this.lastForegroundNode=this.lastHtmlNode=this.lastNode=null};
-mxGraphView.prototype.stateValidated=function(a){var b=this.graph.getModel().isEdge(a.cell)&&this.graph.keepEdgesInForeground||this.graph.getModel().isVertex(a.cell)&&this.graph.keepEdgesInBackground;a=this.graph.cellRenderer.insertStateAfter(a,b?this.lastForegroundNode||this.lastNode:this.lastNode,b?this.lastForegroundHtmlNode||this.lastHtmlNode:this.lastHtmlNode);b?(this.lastForegroundHtmlNode=a[1],this.lastForegroundNode=a[0]):(this.lastHtmlNode=a[1],this.lastNode=a[0])};
-mxGraphView.prototype.updateFixedTerminalPoints=function(a,b,c){this.updateFixedTerminalPoint(a,b,!0,this.graph.getConnectionConstraint(a,b,!0));this.updateFixedTerminalPoint(a,c,!1,this.graph.getConnectionConstraint(a,c,!1))};mxGraphView.prototype.updateFixedTerminalPoint=function(a,b,c,d){a.setAbsoluteTerminalPoint(this.getFixedTerminalPoint(a,b,c,d),c)};
-mxGraphView.prototype.getFixedTerminalPoint=function(a,b,c,d){var e=null;null!=d&&(e=this.graph.getConnectionPoint(b,d));if(null==e&&null==b){b=this.scale;d=this.translate;var f=a.origin,e=this.graph.getCellGeometry(a.cell).getTerminalPoint(c);null!=e&&(e=new mxPoint(b*(d.x+e.x+f.x),b*(d.y+e.y+f.y)))}return e};
-mxGraphView.prototype.updateBoundsFromStencil=function(a){var b=null;if(null!=a&&null!=a.shape&&null!=a.shape.stencil&&"fixed"==a.shape.stencil.aspect){var b=mxRectangle.fromRectangle(a),c=a.shape.stencil.computeAspect(a.style,a.x,a.y,a.width,a.height);a.setRect(c.x,c.y,a.shape.stencil.w0*c.width,a.shape.stencil.h0*c.height)}return b};
-mxGraphView.prototype.updatePoints=function(a,b,c,d){if(null!=a){var e=[];e.push(a.absolutePoints[0]);var f=this.getEdgeStyle(a,b,c,d);if(null!=f){c=this.getTerminalPort(a,c,!0);d=this.getTerminalPort(a,d,!1);var g=this.updateBoundsFromStencil(c),k=this.updateBoundsFromStencil(d);f(a,c,d,b,e);null!=g&&c.setRect(g.x,g.y,g.width,g.height);null!=k&&d.setRect(k.x,k.y,k.width,k.height)}else if(null!=b)for(f=0;fb.length)||mxUtils.getValue(a.style,mxConstants.STYLE_ORTHOGONAL_LOOP,!1)&&(null!=e&&null!=e.point||null!=f&&null!=f.point)?!1:null!=c&&c==d};
-mxGraphView.prototype.getEdgeStyle=function(a,b,c,d){a=this.isLoopStyleEnabled(a,b,c,d)?mxUtils.getValue(a.style,mxConstants.STYLE_LOOP,this.graph.defaultLoopStyle):mxUtils.getValue(a.style,mxConstants.STYLE_NOEDGESTYLE,!1)?null:a.style[mxConstants.STYLE_EDGE];"string"==typeof a&&(b=mxStyleRegistry.getValue(a),null==b&&this.isAllowEval()&&(b=mxUtils.eval(a)),a=b);return"function"==typeof a?a:null};
-mxGraphView.prototype.updateFloatingTerminalPoints=function(a,b,c){var d=a.absolutePoints,e=d[0];null==d[d.length-1]&&null!=c&&this.updateFloatingTerminalPoint(a,c,b,!1);null==e&&null!=b&&this.updateFloatingTerminalPoint(a,b,c,!0)};mxGraphView.prototype.updateFloatingTerminalPoint=function(a,b,c,d){a.setAbsoluteTerminalPoint(this.getFloatingTerminalPoint(a,b,c,d),d)};
-mxGraphView.prototype.getFloatingTerminalPoint=function(a,b,c,d){b=this.getTerminalPort(a,b,d);var e=this.getNextPoint(a,c,d),f=this.graph.isOrthogonal(a);c=mxUtils.toRadians(Number(b.style[mxConstants.STYLE_ROTATION]||"0"));var g=new mxPoint(b.getCenterX(),b.getCenterY());if(0!=c)var k=Math.cos(-c),l=Math.sin(-c),e=mxUtils.getRotatedPoint(e,k,l,g);k=parseFloat(a.style[mxConstants.STYLE_PERIMETER_SPACING]||0);k+=parseFloat(a.style[d?mxConstants.STYLE_SOURCE_PERIMETER_SPACING:mxConstants.STYLE_TARGET_PERIMETER_SPACING]||
-0);a=this.getPerimeterPoint(b,e,0==c&&f,k);0!=c&&(k=Math.cos(c),l=Math.sin(c),a=mxUtils.getRotatedPoint(a,k,l,g));return a};mxGraphView.prototype.getTerminalPort=function(a,b,c){a=mxUtils.getValue(a.style,c?mxConstants.STYLE_SOURCE_PORT:mxConstants.STYLE_TARGET_PORT);null!=a&&(a=this.getState(this.graph.getModel().getCell(a)),null!=a&&(b=a));return b};
-mxGraphView.prototype.getPerimeterPoint=function(a,b,c,d){var e=null;if(null!=a){var f=this.getPerimeterFunction(a);if(null!=f&&null!=b&&(d=this.getPerimeterBounds(a,d),0=Math.round(k+g)&&l=f?0:f*f/(a*a+m*m));a>e&&(a=e);e=Math.sqrt(mxUtils.ptSegDistSq(g.x,g.y,k.x,k.y,b,c));-1==mxUtils.relativeCcw(g.x,g.y,k.x,k.y,b,c)&&(e=-e);return new mxPoint((d/2-p-a)/d*-2,e/this.scale)}}return new mxPoint};
-mxGraphView.prototype.updateEdgeLabelOffset=function(a){var b=a.absolutePoints;a.absoluteOffset.x=a.getCenterX();a.absoluteOffset.y=a.getCenterY();if(null!=b&&0c&&a.x>c+2&&a.x<=b)return!0;b=this.graph.container.offsetHeight;c=this.graph.container.clientHeight;return b>c&&a.y>c+2&&a.y<=b?!0:!1};
-mxGraphView.prototype.init=function(){this.installListeners();var a=this.graph;a.dialect==mxConstants.DIALECT_SVG?this.createSvg():a.dialect==mxConstants.DIALECT_VML?this.createVml():this.createHtml()};
-mxGraphView.prototype.installListeners=function(){var a=this.graph,b=a.container;if(null!=b){mxClient.IS_TOUCH&&(mxEvent.addListener(b,"gesturestart",mxUtils.bind(this,function(b){a.fireGestureEvent(b);mxEvent.consume(b)})),mxEvent.addListener(b,"gesturechange",mxUtils.bind(this,function(b){a.fireGestureEvent(b);mxEvent.consume(b)})),mxEvent.addListener(b,"gestureend",mxUtils.bind(this,function(b){a.fireGestureEvent(b);mxEvent.consume(b)})));mxEvent.addGestureListeners(b,mxUtils.bind(this,function(b){!this.isContainerEvent(b)||
-(mxClient.IS_IE||mxClient.IS_IE11||mxClient.IS_GC||mxClient.IS_OP||mxClient.IS_SF)&&this.isScrollEvent(b)||a.fireMouseEvent(mxEvent.MOUSE_DOWN,new mxMouseEvent(b))}),mxUtils.bind(this,function(b){this.isContainerEvent(b)&&a.fireMouseEvent(mxEvent.MOUSE_MOVE,new mxMouseEvent(b))}),mxUtils.bind(this,function(b){this.isContainerEvent(b)&&a.fireMouseEvent(mxEvent.MOUSE_UP,new mxMouseEvent(b))}));mxEvent.addListener(b,"dblclick",mxUtils.bind(this,function(b){this.isContainerEvent(b)&&a.dblClick(b)}));
-var c=function(c){var d=null;mxClient.IS_TOUCH&&(d=mxEvent.getClientX(c),c=mxEvent.getClientY(c),c=mxUtils.convertPoint(b,d,c),d=a.view.getState(a.getCellAt(c.x,c.y)));return d};a.addMouseListener({mouseDown:function(b,c){a.popupMenuHandler.hideMenu()},mouseMove:function(){},mouseUp:function(){}});this.moveHandler=mxUtils.bind(this,function(b){null!=a.tooltipHandler&&a.tooltipHandler.isHideOnHover()&&a.tooltipHandler.hide();this.captureDocumentGesture&&a.isMouseDown&&null!=a.container&&!this.isContainerEvent(b)&&
-"none"!=a.container.style.display&&"hidden"!=a.container.style.visibility&&!mxEvent.isConsumed(b)&&a.fireMouseEvent(mxEvent.MOUSE_MOVE,new mxMouseEvent(b,c(b)))});this.endHandler=mxUtils.bind(this,function(b){this.captureDocumentGesture&&a.isMouseDown&&null!=a.container&&!this.isContainerEvent(b)&&"none"!=a.container.style.display&&"hidden"!=a.container.style.visibility&&a.fireMouseEvent(mxEvent.MOUSE_UP,new mxMouseEvent(b))});mxEvent.addGestureListeners(document,null,this.moveHandler,this.endHandler)}};
-mxGraphView.prototype.createHtml=function(){var a=this.graph.container;null!=a&&(this.canvas=this.createHtmlPane("100%","100%"),this.canvas.style.overflow="hidden",this.backgroundPane=this.createHtmlPane("1px","1px"),this.drawPane=this.createHtmlPane("1px","1px"),this.overlayPane=this.createHtmlPane("1px","1px"),this.decoratorPane=this.createHtmlPane("1px","1px"),this.canvas.appendChild(this.backgroundPane),this.canvas.appendChild(this.drawPane),this.canvas.appendChild(this.overlayPane),this.canvas.appendChild(this.decoratorPane),
-a.appendChild(this.canvas),this.updateContainerStyle(a),mxClient.IS_QUIRKS&&(a=mxUtils.bind(this,function(a){a=this.getGraphBounds();this.updateHtmlCanvasSize(a.x+a.width+this.graph.border,a.y+a.height+this.graph.border)}),mxEvent.addListener(window,"resize",a)))};
-mxGraphView.prototype.updateHtmlCanvasSize=function(a,b){if(null!=this.graph.container){var c=this.graph.container.offsetHeight;this.canvas.style.width=this.graph.container.offsetWidth'+mxClient.VML_PREFIX+":group>")};
-mxGraph.prototype.createHandlers=function(){this.tooltipHandler=this.createTooltipHandler();this.tooltipHandler.setEnabled(!1);this.selectionCellsHandler=this.createSelectionCellsHandler();this.connectionHandler=this.createConnectionHandler();this.connectionHandler.setEnabled(!1);this.graphHandler=this.createGraphHandler();this.panningHandler=this.createPanningHandler();this.panningHandler.panningEnabled=!1;this.popupMenuHandler=this.createPopupMenuHandler()};
-mxGraph.prototype.createTooltipHandler=function(){return new mxTooltipHandler(this)};mxGraph.prototype.createSelectionCellsHandler=function(){return new mxSelectionCellsHandler(this)};mxGraph.prototype.createConnectionHandler=function(){return new mxConnectionHandler(this)};mxGraph.prototype.createGraphHandler=function(){return new mxGraphHandler(this)};mxGraph.prototype.createPanningHandler=function(){return new mxPanningHandler(this)};mxGraph.prototype.createPopupMenuHandler=function(){return new mxPopupMenuHandler(this)};
-mxGraph.prototype.createSelectionModel=function(){return new mxGraphSelectionModel(this)};mxGraph.prototype.createStylesheet=function(){return new mxStylesheet};mxGraph.prototype.createGraphView=function(){return new mxGraphView(this)};mxGraph.prototype.createCellRenderer=function(){return new mxCellRenderer};mxGraph.prototype.createCellEditor=function(){return new mxCellEditor(this)};mxGraph.prototype.getModel=function(){return this.model};mxGraph.prototype.getView=function(){return this.view};
-mxGraph.prototype.getStylesheet=function(){return this.stylesheet};mxGraph.prototype.setStylesheet=function(a){this.stylesheet=a};mxGraph.prototype.getSelectionModel=function(){return this.selectionModel};mxGraph.prototype.setSelectionModel=function(a){this.selectionModel=a};
-mxGraph.prototype.getSelectionCellsForChanges=function(a){for(var b=[],c=0;c mxUtils.indexOf(b,e)&&b.push(e)}}return this.getModel().getTopmostCells(b)};
-mxGraph.prototype.graphModelChanged=function(a){for(var b=0;b"+b+""),d&&b.addListener(mxEvent.CLICK,mxUtils.bind(this,function(b,c){this.isEnabled()&&this.setSelectionCell(a)})),this.addCellOverlay(a,b);this.removeCellOverlays(a);return null};mxGraph.prototype.startEditing=function(a){this.startEditingAtCell(null,a)};
-mxGraph.prototype.startEditingAtCell=function(a,b){null!=b&&mxEvent.isMultiTouchEvent(b)||(null==a&&(a=this.getSelectionCell(),null==a||this.isCellEditable(a)||(a=null)),null!=a&&(this.fireEvent(new mxEventObject(mxEvent.START_EDITING,"cell",a,"event",b)),this.cellEditor.startEditing(a,b),this.fireEvent(new mxEventObject(mxEvent.EDITING_STARTED,"cell",a,"event",b))))};mxGraph.prototype.getEditingValue=function(a,b){return this.convertValueToString(a)};
-mxGraph.prototype.stopEditing=function(a){this.cellEditor.stopEditing(a);this.fireEvent(new mxEventObject(mxEvent.EDITING_STOPPED,"cancel",a))};mxGraph.prototype.labelChanged=function(a,b,c){this.model.beginUpdate();try{var d=a.value;this.cellLabelChanged(a,b,this.isAutoSizeCell(a));this.fireEvent(new mxEventObject(mxEvent.LABEL_CHANGED,"cell",a,"value",b,"old",d,"event",c))}finally{this.model.endUpdate()}return a};
-mxGraph.prototype.cellLabelChanged=function(a,b,c){this.model.beginUpdate();try{this.model.setValue(a,b),c&&this.cellSizeUpdated(a,!1)}finally{this.model.endUpdate()}};mxGraph.prototype.escape=function(a){this.fireEvent(new mxEventObject(mxEvent.ESCAPE,"event",a))};
-mxGraph.prototype.click=function(a){var b=a.getEvent(),c=a.getCell(),d=new mxEventObject(mxEvent.CLICK,"event",b,"cell",c);a.isConsumed()&&d.consume();this.fireEvent(d);if(this.isEnabled()&&!mxEvent.isConsumed(b)&&!d.isConsumed())if(null!=c){if(this.isTransparentClickEvent(b)){var e=!1;a=this.getCellAt(a.graphX,a.graphY,null,null,null,mxUtils.bind(this,function(a){a=this.isCellSelected(a.cell);e=e||a;return!e||a}));null!=a&&(c=a)}this.selectCellForEvent(c,b)}else c=null,this.isSwimlaneSelectionEnabled()&&
-(c=this.getSwimlaneAt(a.getGraphX(),a.getGraphY())),null!=c?this.selectCellForEvent(c,b):this.isToggleEvent(b)||this.clearSelection()};mxGraph.prototype.dblClick=function(a,b){var c=new mxEventObject(mxEvent.DOUBLE_CLICK,"event",a,"cell",b);this.fireEvent(c);!this.isEnabled()||mxEvent.isConsumed(a)||c.isConsumed()||null==b||!this.isCellEditable(b)||this.isEditing(b)||(this.startEditingAtCell(b,a),mxEvent.consume(a))};
-mxGraph.prototype.tapAndHold=function(a){var b=a.getEvent(),c=new mxEventObject(mxEvent.TAP_AND_HOLD,"event",b,"cell",a.getCell());this.fireEvent(c);c.isConsumed()&&(this.panningHandler.panningTrigger=!1);this.isEnabled()&&!mxEvent.isConsumed(b)&&!c.isConsumed()&&this.connectionHandler.isEnabled()&&(b=this.view.getState(this.connectionHandler.marker.getCell(a)),null!=b&&(this.connectionHandler.marker.currentColor=this.connectionHandler.marker.validColor,this.connectionHandler.marker.markedState=b,
-this.connectionHandler.marker.mark(),this.connectionHandler.first=new mxPoint(a.getGraphX(),a.getGraphY()),this.connectionHandler.edgeState=this.connectionHandler.createEdgeState(a),this.connectionHandler.previous=b,this.connectionHandler.fireEvent(new mxEventObject(mxEvent.START,"state",this.connectionHandler.previous))))};
-mxGraph.prototype.scrollPointToVisible=function(a,b,c,d){if(this.timerAutoScroll||!this.ignoreScrollbars&&!mxUtils.hasScrollbars(this.container))this.allowAutoPanning&&!this.panningHandler.isActive()&&(null==this.panningManager&&(this.panningManager=this.createPanningManager()),this.panningManager.panTo(a+this.panDx,b+this.panDy));else{var e=this.container;d=null!=d?d:20;if(a>=e.scrollLeft&&b>=e.scrollTop&&a<=e.scrollLeft+e.clientWidth&&b<=e.scrollTop+e.clientHeight){var f=e.scrollLeft+e.clientWidth-
-a;if(fthis.minPageBreakDist)?Math.ceil(d.height/f.height)+1:0,k=a?Math.ceil(d.width/f.width)+1:0,l=(k-1)*f.width,m=(g-1)*f.height;null==this.horizontalPageBreaks&&0this.model.getChildCount(b)&&c--;this.model.add(b,a[l],c+l);this.autoSizeCellsOnAdd&&this.autoSizeCell(a[l],!0);(null==k||k)&&this.isExtendParentsOnAdd(a[l])&&this.isExtendParent(a[l])&&this.extendParent(a[l]);(null==g||g)&&this.constrainChild(a[l]);null!=d&&this.cellConnected(a[l],d,!0);null!=e&&this.cellConnected(a[l],e,!1)}this.fireEvent(new mxEventObject(mxEvent.CELLS_ADDED,"cells",a,"parent",b,"index",c,"source",
-d,"target",e,"absolute",f))}finally{this.model.endUpdate()}}};mxGraph.prototype.autoSizeCell=function(a,b){if(null!=b?b:1)for(var c=this.model.getChildCount(a),d=0;d"),e=mxUtils.getSizeForString(f,e,d[mxConstants.STYLE_FONTFAMILY]),c=e.width+b,a=e.height+a,mxUtils.getValue(d,mxConstants.STYLE_HORIZONTAL,!0)||(d=a,a=c,c=d),this.gridEnabled&&(c=this.snap(c+this.gridSize/2),a=this.snap(a+this.gridSize/2)),b=new mxRectangle(0,0,c,a)):(d=4*this.gridSize,b=new mxRectangle(0,0,d,d))}}return b};mxGraph.prototype.resizeCell=function(a,b,c){return this.resizeCells([a],[b],c)[0]};
-mxGraph.prototype.resizeCells=function(a,b,c){c=null!=c?c:this.isRecursiveResize();this.model.beginUpdate();try{this.cellsResized(a,b,c),this.fireEvent(new mxEventObject(mxEvent.RESIZE_CELLS,"cells",a,"bounds",b))}finally{this.model.endUpdate()}return a};
-mxGraph.prototype.cellsResized=function(a,b,c){c=null!=c?c:!1;if(null!=a&&null!=b&&a.length==b.length){this.model.beginUpdate();try{for(var d=0;de.width&&(f=c.width-e.width,c.width-=f);d.x+d.width>e.x+e.width&&(f-=d.x+d.width-e.x-e.width-f);g=0;c.height>e.height&&(g=c.height-e.height,c.height-=g);d.y+d.height>
-e.y+e.height&&(g-=d.y+d.height-e.y-e.height-g);d.xf&&(n=0),b>g&&(p=0),this.view.setTranslate(Math.floor(n/2-k.x),Math.floor(p/2-k.y)),this.container.scrollLeft=(a-f)/
-2,this.container.scrollTop=(b-g)/2):this.view.setTranslate(a?Math.floor(l.x-k.x*m+n*c/m):l.x,b?Math.floor(l.y-k.y*m+p*d/m):l.y)};
-mxGraph.prototype.zoom=function(a,b){b=null!=b?b:this.centerZoom;var c=Math.round(this.view.scale*a*100)/100,d=this.view.getState(this.getSelectionCell());a=c/this.view.scale;if(this.keepSelectionVisibleOnZoom&&null!=d)d=new mxRectangle(d.x*a,d.y*a,d.width*a,d.height*a),this.view.scale=c,this.scrollRectToVisible(d)||(this.view.revalidate(),this.view.setScale(c));else if(d=mxUtils.hasScrollbars(this.container),b&&!d){var d=this.container.offsetWidth,e=this.container.offsetHeight;if(1b?(b=a.height/b,c=(b-a.height)/2,a.height=b,a.y-=Math.min(a.y,c),d=Math.min(this.container.scrollHeight,a.y+a.height),a.height=d-a.y):(b*=a.width,c=(b-a.width)/2,a.width=b,a.x-=Math.min(a.x,c),c=Math.min(this.container.scrollWidth,
-a.x+a.width),a.width=c-a.x);b=this.container.clientWidth/a.width;c=this.view.scale*b;mxUtils.hasScrollbars(this.container)?(this.view.setScale(c),this.container.scrollLeft=Math.round(a.x*b),this.container.scrollTop=Math.round(a.y*b)):this.view.scaleAndTranslate(c,this.view.translate.x-a.x/this.view.scale,this.view.translate.y-a.y/this.view.scale)};
-mxGraph.prototype.scrollCellToVisible=function(a,b){var c=-this.view.translate.x,d=-this.view.translate.y,e=this.view.getState(a);null!=e&&(c=new mxRectangle(c+e.x,d+e.y,e.width,e.height),b&&null!=this.container&&(d=this.container.clientWidth,e=this.container.clientHeight,c.x=c.getCenterX()-d/2,c.width=d,c.y=c.getCenterY()-e/2,c.height=e),d=new mxPoint(this.view.translate.x,this.view.translate.y),this.scrollRectToVisible(c)&&(c=new mxPoint(this.view.translate.x,this.view.translate.y),this.view.translate.x=
-d.x,this.view.translate.y=d.y,this.view.setTranslate(c.x,c.y)))};
-mxGraph.prototype.scrollRectToVisible=function(a){var b=!1;if(null!=a){var c=this.container.offsetWidth,d=this.container.offsetHeight,e=Math.min(c,a.width),f=Math.min(d,a.height);if(mxUtils.hasScrollbars(this.container)){c=this.container;a.x+=this.view.translate.x;a.y+=this.view.translate.y;var g=c.scrollLeft-a.x,d=Math.max(g-c.scrollLeft,0);0g+c&&(this.view.translate.x-=(a.x+e-c-g)/l,b=!0);a.y+f>k+d&&(this.view.translate.y-=(a.y+f-d-k)/l,b=!0);a.x")):this.setCellWarning(f,null);c=c&&null==g}d="";this.isCellCollapsed(a)&&!c&&(d+=(mxResources.get(this.containsValidationErrorsResource)||this.containsValidationErrorsResource)+"\n");d=this.model.isEdge(a)?d+
-(this.getEdgeValidationError(a,this.model.getTerminal(a,!0),this.model.getTerminal(a,!1))||""):d+(this.getCellValidationError(a)||"");e=this.validateCell(a,b);null!=e&&(d+=e);null==this.model.getParent(a)&&this.view.validate();return 0f.max||bf.max||c")),null==e&&null!=a.overlays&&a.overlays.visit(function(a,c){null!=e||b!=c.node&&b.parentNode!=c.node||(e=c.overlay.toString())}),null==e&&(c=this.selectionCellsHandler.getHandler(a.cell),null!=c&&"function"==typeof c.getTooltipForNode&&(e=c.getTooltipForNode(b))),null==
-e&&(e=this.getTooltipForCell(a.cell)));return e};mxGraph.prototype.getTooltipForCell=function(a){return null!=a&&null!=a.getTooltip?a.getTooltip():this.convertValueToString(a)};mxGraph.prototype.getLinkForCell=function(a){return null};mxGraph.prototype.getCursorForMouseEvent=function(a){return this.getCursorForCell(a.getCell())};mxGraph.prototype.getCursorForCell=function(a){return null};
-mxGraph.prototype.getStartSize=function(a){var b=new mxRectangle,c=this.view.getState(a);a=null!=c?c.style:this.getCellStyle(a);null!=a&&(c=parseInt(mxUtils.getValue(a,mxConstants.STYLE_STARTSIZE,mxConstants.DEFAULT_STARTSIZE)),mxUtils.getValue(a,mxConstants.STYLE_HORIZONTAL,!0)?b.height=c:b.width=c);return b};mxGraph.prototype.getImage=function(a){return null!=a&&null!=a.style?a.style[mxConstants.STYLE_IMAGE]:null};
-mxGraph.prototype.getVerticalAlign=function(a){return null!=a&&null!=a.style?a.style[mxConstants.STYLE_VERTICAL_ALIGN]||mxConstants.ALIGN_MIDDLE:null};mxGraph.prototype.getIndicatorColor=function(a){return null!=a&&null!=a.style?a.style[mxConstants.STYLE_INDICATOR_COLOR]:null};mxGraph.prototype.getIndicatorGradientColor=function(a){return null!=a&&null!=a.style?a.style[mxConstants.STYLE_INDICATOR_GRADIENTCOLOR]:null};
-mxGraph.prototype.getIndicatorShape=function(a){return null!=a&&null!=a.style?a.style[mxConstants.STYLE_INDICATOR_SHAPE]:null};mxGraph.prototype.getIndicatorImage=function(a){return null!=a&&null!=a.style?a.style[mxConstants.STYLE_INDICATOR_IMAGE]:null};mxGraph.prototype.getBorder=function(){return this.border};mxGraph.prototype.setBorder=function(a){this.border=a};
-mxGraph.prototype.isSwimlane=function(a){if(null!=a&&this.model.getParent(a)!=this.model.getRoot()){var b=this.view.getState(a),b=null!=b?b.style:this.getCellStyle(a);if(null!=b&&!this.model.isEdge(a))return b[mxConstants.STYLE_SHAPE]==mxConstants.SHAPE_SWIMLANE}return!1};mxGraph.prototype.isResizeContainer=function(){return this.resizeContainer};mxGraph.prototype.setResizeContainer=function(a){this.resizeContainer=a};mxGraph.prototype.isEnabled=function(){return this.enabled};
-mxGraph.prototype.setEnabled=function(a){this.enabled=a};mxGraph.prototype.isEscapeEnabled=function(){return this.escapeEnabled};mxGraph.prototype.setEscapeEnabled=function(a){this.escapeEnabled=a};mxGraph.prototype.isInvokesStopCellEditing=function(){return this.invokesStopCellEditing};mxGraph.prototype.setInvokesStopCellEditing=function(a){this.invokesStopCellEditing=a};mxGraph.prototype.isEnterStopsCellEditing=function(){return this.enterStopsCellEditing};
-mxGraph.prototype.setEnterStopsCellEditing=function(a){this.enterStopsCellEditing=a};mxGraph.prototype.isCellLocked=function(a){var b=this.model.getGeometry(a);return this.isCellsLocked()||null!=b&&this.model.isVertex(a)&&b.relative};mxGraph.prototype.isCellsLocked=function(){return this.cellsLocked};mxGraph.prototype.setCellsLocked=function(a){this.cellsLocked=a};mxGraph.prototype.getCloneableCells=function(a){return this.model.filterCells(a,mxUtils.bind(this,function(a){return this.isCellCloneable(a)}))};
-mxGraph.prototype.isCellCloneable=function(a){var b=this.view.getState(a);a=null!=b?b.style:this.getCellStyle(a);return this.isCellsCloneable()&&0!=a[mxConstants.STYLE_CLONEABLE]};mxGraph.prototype.isCellsCloneable=function(){return this.cellsCloneable};mxGraph.prototype.setCellsCloneable=function(a){this.cellsCloneable=a};mxGraph.prototype.getExportableCells=function(a){return this.model.filterCells(a,mxUtils.bind(this,function(a){return this.canExportCell(a)}))};
-mxGraph.prototype.canExportCell=function(a){return this.exportEnabled};mxGraph.prototype.getImportableCells=function(a){return this.model.filterCells(a,mxUtils.bind(this,function(a){return this.canImportCell(a)}))};mxGraph.prototype.canImportCell=function(a){return this.importEnabled};mxGraph.prototype.isCellSelectable=function(a){return this.isCellsSelectable()};mxGraph.prototype.isCellsSelectable=function(){return this.cellsSelectable};
-mxGraph.prototype.setCellsSelectable=function(a){this.cellsSelectable=a};mxGraph.prototype.getDeletableCells=function(a){return this.model.filterCells(a,mxUtils.bind(this,function(a){return this.isCellDeletable(a)}))};mxGraph.prototype.isCellDeletable=function(a){var b=this.view.getState(a);a=null!=b?b.style:this.getCellStyle(a);return this.isCellsDeletable()&&0!=a[mxConstants.STYLE_DELETABLE]};mxGraph.prototype.isCellsDeletable=function(){return this.cellsDeletable};
-mxGraph.prototype.setCellsDeletable=function(a){this.cellsDeletable=a};mxGraph.prototype.isLabelMovable=function(a){return!this.isCellLocked(a)&&(this.model.isEdge(a)&&this.edgeLabelsMovable||this.model.isVertex(a)&&this.vertexLabelsMovable)};mxGraph.prototype.isCellRotatable=function(a){var b=this.view.getState(a);return 0!=(null!=b?b.style:this.getCellStyle(a))[mxConstants.STYLE_ROTATABLE]};mxGraph.prototype.getMovableCells=function(a){return this.model.filterCells(a,mxUtils.bind(this,function(a){return this.isCellMovable(a)}))};
-mxGraph.prototype.isCellMovable=function(a){var b=this.view.getState(a),b=null!=b?b.style:this.getCellStyle(a);return this.isCellsMovable()&&!this.isCellLocked(a)&&0!=b[mxConstants.STYLE_MOVABLE]};mxGraph.prototype.isCellsMovable=function(){return this.cellsMovable};mxGraph.prototype.setCellsMovable=function(a){this.cellsMovable=a};mxGraph.prototype.isGridEnabled=function(){return this.gridEnabled};mxGraph.prototype.setGridEnabled=function(a){this.gridEnabled=a};mxGraph.prototype.isPortsEnabled=function(){return this.portsEnabled};
-mxGraph.prototype.setPortsEnabled=function(a){this.portsEnabled=a};mxGraph.prototype.getGridSize=function(){return this.gridSize};mxGraph.prototype.setGridSize=function(a){this.gridSize=a};mxGraph.prototype.getTolerance=function(){return this.tolerance};mxGraph.prototype.setTolerance=function(a){this.tolerance=a};mxGraph.prototype.isVertexLabelsMovable=function(){return this.vertexLabelsMovable};mxGraph.prototype.setVertexLabelsMovable=function(a){this.vertexLabelsMovable=a};
-mxGraph.prototype.isEdgeLabelsMovable=function(){return this.edgeLabelsMovable};mxGraph.prototype.setEdgeLabelsMovable=function(a){this.edgeLabelsMovable=a};mxGraph.prototype.isSwimlaneNesting=function(){return this.swimlaneNesting};mxGraph.prototype.setSwimlaneNesting=function(a){this.swimlaneNesting=a};mxGraph.prototype.isSwimlaneSelectionEnabled=function(){return this.swimlaneSelectionEnabled};mxGraph.prototype.setSwimlaneSelectionEnabled=function(a){this.swimlaneSelectionEnabled=a};
-mxGraph.prototype.isMultigraph=function(){return this.multigraph};mxGraph.prototype.setMultigraph=function(a){this.multigraph=a};mxGraph.prototype.isAllowLoops=function(){return this.allowLoops};mxGraph.prototype.setAllowDanglingEdges=function(a){this.allowDanglingEdges=a};mxGraph.prototype.isAllowDanglingEdges=function(){return this.allowDanglingEdges};mxGraph.prototype.setConnectableEdges=function(a){this.connectableEdges=a};mxGraph.prototype.isConnectableEdges=function(){return this.connectableEdges};
-mxGraph.prototype.setCloneInvalidEdges=function(a){this.cloneInvalidEdges=a};mxGraph.prototype.isCloneInvalidEdges=function(){return this.cloneInvalidEdges};mxGraph.prototype.setAllowLoops=function(a){this.allowLoops=a};mxGraph.prototype.isDisconnectOnMove=function(){return this.disconnectOnMove};mxGraph.prototype.setDisconnectOnMove=function(a){this.disconnectOnMove=a};mxGraph.prototype.isDropEnabled=function(){return this.dropEnabled};
-mxGraph.prototype.setDropEnabled=function(a){this.dropEnabled=a};mxGraph.prototype.isSplitEnabled=function(){return this.splitEnabled};mxGraph.prototype.setSplitEnabled=function(a){this.splitEnabled=a};mxGraph.prototype.isCellResizable=function(a){var b=this.view.getState(a),b=null!=b?b.style:this.getCellStyle(a);return this.isCellsResizable()&&!this.isCellLocked(a)&&"0"!=mxUtils.getValue(b,mxConstants.STYLE_RESIZABLE,"1")};mxGraph.prototype.isCellsResizable=function(){return this.cellsResizable};
-mxGraph.prototype.setCellsResizable=function(a){this.cellsResizable=a};mxGraph.prototype.isTerminalPointMovable=function(a,b){return!0};mxGraph.prototype.isCellBendable=function(a){var b=this.view.getState(a),b=null!=b?b.style:this.getCellStyle(a);return this.isCellsBendable()&&!this.isCellLocked(a)&&0!=b[mxConstants.STYLE_BENDABLE]};mxGraph.prototype.isCellsBendable=function(){return this.cellsBendable};mxGraph.prototype.setCellsBendable=function(a){this.cellsBendable=a};
-mxGraph.prototype.isCellEditable=function(a){var b=this.view.getState(a),b=null!=b?b.style:this.getCellStyle(a);return this.isCellsEditable()&&!this.isCellLocked(a)&&0!=b[mxConstants.STYLE_EDITABLE]};mxGraph.prototype.isCellsEditable=function(){return this.cellsEditable};mxGraph.prototype.setCellsEditable=function(a){this.cellsEditable=a};mxGraph.prototype.isCellDisconnectable=function(a,b,c){return this.isCellsDisconnectable()&&!this.isCellLocked(a)};mxGraph.prototype.isCellsDisconnectable=function(){return this.cellsDisconnectable};
-mxGraph.prototype.setCellsDisconnectable=function(a){this.cellsDisconnectable=a};mxGraph.prototype.isValidSource=function(a){return null==a&&this.allowDanglingEdges||null!=a&&(!this.model.isEdge(a)||this.connectableEdges)&&this.isCellConnectable(a)};mxGraph.prototype.isValidTarget=function(a){return this.isValidSource(a)};mxGraph.prototype.isValidConnection=function(a,b){return this.isValidSource(a)&&this.isValidTarget(b)};mxGraph.prototype.setConnectable=function(a){this.connectionHandler.setEnabled(a)};
-mxGraph.prototype.isConnectable=function(a){return this.connectionHandler.isEnabled()};mxGraph.prototype.setTooltips=function(a){this.tooltipHandler.setEnabled(a)};mxGraph.prototype.setPanning=function(a){this.panningHandler.panningEnabled=a};mxGraph.prototype.isEditing=function(a){if(null!=this.cellEditor){var b=this.cellEditor.getEditingCell();return null==a?null!=b:a==b}return!1};
-mxGraph.prototype.isAutoSizeCell=function(a){var b=this.view.getState(a);a=null!=b?b.style:this.getCellStyle(a);return this.isAutoSizeCells()||1==a[mxConstants.STYLE_AUTOSIZE]};mxGraph.prototype.isAutoSizeCells=function(){return this.autoSizeCells};mxGraph.prototype.setAutoSizeCells=function(a){this.autoSizeCells=a};mxGraph.prototype.isExtendParent=function(a){return!this.getModel().isEdge(a)&&this.isExtendParents()};mxGraph.prototype.isExtendParents=function(){return this.extendParents};
-mxGraph.prototype.setExtendParents=function(a){this.extendParents=a};mxGraph.prototype.isExtendParentsOnAdd=function(a){return this.extendParentsOnAdd};mxGraph.prototype.setExtendParentsOnAdd=function(a){this.extendParentsOnAdd=a};mxGraph.prototype.isExtendParentsOnMove=function(){return this.extendParentsOnMove};mxGraph.prototype.setExtendParentsOnMove=function(a){this.extendParentsOnMove=a};mxGraph.prototype.isRecursiveResize=function(a){return this.recursiveResize};
-mxGraph.prototype.setRecursiveResize=function(a){this.recursiveResize=a};mxGraph.prototype.isConstrainChild=function(a){return this.isConstrainChildren()&&!this.getModel().isEdge(this.getModel().getParent(a))};mxGraph.prototype.isConstrainChildren=function(){return this.constrainChildren};mxGraph.prototype.setConstrainChildren=function(a){this.constrainChildren=a};mxGraph.prototype.isConstrainRelativeChildren=function(){return this.constrainRelativeChildren};
-mxGraph.prototype.setConstrainRelativeChildren=function(a){this.constrainRelativeChildren=a};mxGraph.prototype.isAllowNegativeCoordinates=function(){return this.allowNegativeCoordinates};mxGraph.prototype.setAllowNegativeCoordinates=function(a){this.allowNegativeCoordinates=a};mxGraph.prototype.getOverlap=function(a){return this.isAllowOverlapParent(a)?this.defaultOverlap:0};mxGraph.prototype.isAllowOverlapParent=function(a){return!1};
-mxGraph.prototype.getFoldableCells=function(a,b){return this.model.filterCells(a,mxUtils.bind(this,function(a){return this.isCellFoldable(a,b)}))};mxGraph.prototype.isCellFoldable=function(a,b){var c=this.view.getState(a),c=null!=c?c.style:this.getCellStyle(a);return 0mxUtils.indexOf(a,g);)g=this.model.getParent(g);return this.model.isLayer(c)||null!=g?null:c};mxGraph.prototype.getDefaultParent=function(){var a=this.getCurrentRoot();null==a&&(a=this.defaultParent,null==a&&(a=this.model.getRoot(),a=this.model.getChildAt(a,0)));return a};mxGraph.prototype.setDefaultParent=function(a){this.defaultParent=a};mxGraph.prototype.getSwimlane=function(a){for(;null!=a&&!this.isSwimlane(a);)a=this.model.getParent(a);return a};
-mxGraph.prototype.getSwimlaneAt=function(a,b,c){c=c||this.getDefaultParent();if(null!=c)for(var d=this.model.getChildCount(c),e=0;ea.width*e||0a.height*e)return!0}return!1};mxGraph.prototype.getChildVertices=function(a){return this.getChildCells(a,!0,!1)};mxGraph.prototype.getChildEdges=function(a){return this.getChildCells(a,!1,!0)};
-mxGraph.prototype.getChildCells=function(a,b,c){a=null!=a?a:this.getDefaultParent();a=this.model.getChildCells(a,null!=b?b:!1,null!=c?c:!1);b=[];for(c=0;c=a&&q.y+q.height<=l&&q.y>=b&&q.x+q.width<=k?f.push(p):this.getCells(a,
-b,c,d,p,f)}}}return f};mxGraph.prototype.getCellsBeyond=function(a,b,c,d,e){var f=[];if(d||e)if(null==c&&(c=this.getDefaultParent()),null!=c)for(var g=this.model.getChildCount(c),k=0;k=a)&&(!e||m.y>=b)&&f.push(l)}return f};
-mxGraph.prototype.findTreeRoots=function(a,b,c){b=null!=b?b:!1;c=null!=c?c:!1;var d=[];if(null!=a){for(var e=this.getModel(),f=e.getChildCount(a),g=null,k=0,l=0;lk&&(k=n,g=m)}}0==d.length&&null!=g&&d.push(g)}return d};
-mxGraph.prototype.traverse=function(a,b,c,d,e,f){if(null!=c&&null!=a&&(b=null!=b?b:!0,f=null!=f?f:!1,e=e||new mxDictionary,!e.get(a)&&(e.put(a,!0),d=c(a,d),null==d||d))&&(d=this.model.getEdgeCount(a),0b?f-1:b)),this.setSelectionCell(a)):this.getCurrentRoot()!=d&&this.setSelectionCell(d)};mxGraph.prototype.selectAll=function(a,b){a=a||this.getDefaultParent();var c=b?this.model.filterDescendants(function(b){return b!=a},a):this.model.getChildren(a);null!=c&&this.setSelectionCells(c)};mxGraph.prototype.selectVertices=function(a){this.selectCells(!0,!1,a)};mxGraph.prototype.selectEdges=function(a){this.selectCells(!1,!0,a)};
-mxGraph.prototype.selectCells=function(a,b,c){c=c||this.getDefaultParent();var d=mxUtils.bind(this,function(c){return null!=this.view.getState(c)&&(0==this.model.getChildCount(c)&&this.model.isVertex(c)&&a&&!this.model.isEdge(this.model.getParent(c))||this.model.isEdge(c)&&b)});c=this.model.filterDescendants(d,c);this.setSelectionCells(c)};
-mxGraph.prototype.selectCellForEvent=function(a,b){var c=this.isCellSelected(a);this.isToggleEvent(b)?c?this.removeSelectionCell(a):this.addSelectionCell(a):c&&1==this.getSelectionCount()||this.setSelectionCell(a)};mxGraph.prototype.selectCellsForEvent=function(a,b){this.isToggleEvent(b)?this.addSelectionCells(a):this.setSelectionCells(a)};
-mxGraph.prototype.createHandler=function(a){var b=null;if(null!=a)if(this.model.isEdge(a.cell))var b=a.getVisibleTerminalState(!0),c=a.getVisibleTerminalState(!1),d=this.getCellGeometry(a.cell),b=this.view.getEdgeStyle(a,null!=d?d.points:null,b,c),b=this.createEdgeHandler(a,b);else b=this.createVertexHandler(a);return b};mxGraph.prototype.createVertexHandler=function(a){return new mxVertexHandler(a)};
-mxGraph.prototype.createEdgeHandler=function(a,b){return b==mxEdgeStyle.Loop||b==mxEdgeStyle.ElbowConnector||b==mxEdgeStyle.SideToSide||b==mxEdgeStyle.TopToBottom?this.createElbowEdgeHandler(a):b==mxEdgeStyle.SegmentConnector||b==mxEdgeStyle.OrthConnector?this.createEdgeSegmentHandler(a):new mxEdgeHandler(a)};mxGraph.prototype.createEdgeSegmentHandler=function(a){return new mxEdgeSegmentHandler(a)};mxGraph.prototype.createElbowEdgeHandler=function(a){return new mxElbowEdgeHandler(a)};
-mxGraph.prototype.addMouseListener=function(a){null==this.mouseListeners&&(this.mouseListeners=[]);this.mouseListeners.push(a)};mxGraph.prototype.removeMouseListener=function(a){if(null!=this.mouseListeners)for(var b=0;bthis.doubleClickCounter){if(this.doubleClickCounter++,d=!1,a==mxEvent.MOUSE_UP?b.getCell()==this.lastTouchCell&&null!=this.lastTouchCell&&(this.lastTouchTime=0,d=this.lastTouchCell,this.lastTouchCell=null,mxClient.IS_QUIRKS&&b.getSource().fireEvent("ondblclick"),this.dblClick(b.getEvent(),
-d),d=!0):(this.fireDoubleClick=!0,this.lastTouchTime=0),!mxClient.IS_QUIRKS||d){mxEvent.consume(b.getEvent());return}}else{if(null==this.lastTouchEvent||this.lastTouchEvent!=b.getEvent())this.lastTouchCell=b.getCell(),this.lastTouchX=b.getX(),this.lastTouchY=b.getY(),this.lastTouchTime=d,this.lastTouchEvent=b.getEvent(),this.doubleClickCounter=0}else if((this.isMouseDown||a==mxEvent.MOUSE_UP)&&this.fireDoubleClick){this.fireDoubleClick=!1;d=this.lastTouchCell;this.lastTouchCell=null;this.isMouseDown=
-!1;(null!=d||(mxEvent.isTouchEvent(b.getEvent())||mxEvent.isPenEvent(b.getEvent()))&&(mxClient.IS_GC||mxClient.IS_SF))&&Math.abs(this.lastTouchX-b.getX())c.x&&(f-=c.x);0>c.y&&(g-=c.y);if(b.translate.x!=f||b.translate.y!=g)b.translate.x=f,b.translate.y=g,a=!0;var c=b.translate,d=this.source.getView().scale,f=d/b.scale,g=1/b.scale,k=this.source.container;this.bounds=new mxRectangle((c.x-e.x-this.source.panDx)/g,(c.y-e.y-this.source.panDy)/g,k.clientWidth/f,k.clientHeight/f);this.bounds.x+=this.source.container.scrollLeft*b.scale/d;this.bounds.y+=this.source.container.scrollTop*b.scale/d;c=this.selectionBorder.bounds;if(c.x!=this.bounds.x||
-c.y!=this.bounds.y||c.width!=this.bounds.width||c.height!=this.bounds.height)this.selectionBorder.bounds=this.bounds,this.selectionBorder.redraw();c=this.sizer.bounds;b=new mxRectangle(this.bounds.x+this.bounds.width-c.width/2,this.bounds.y+this.bounds.height-c.height/2,c.width,c.height);if(c.x!=b.x||c.y!=b.y||c.width!=b.width||c.height!=b.height)this.sizer.bounds=b,"hidden"!=this.sizer.node.style.visibility&&this.sizer.redraw();a&&this.outline.view.revalidate()}}};
-mxOutline.prototype.mouseDown=function(a,b){if(this.enabled&&this.showViewport){var c=mxEvent.isMouseEvent(b.getEvent())?0:this.source.tolerance,c=this.source.allowHandleBoundsCheck&&(mxClient.IS_IE||0=this.max)||!this.source&&(0==this.max||f>=this.max))&&(g+=this.countError+"\n"),null!=this.validNeighbors&&null!=this.typeError&&0mxUtils.indexOf(a,f)&&(f=this.getLayout(f),null!=f&&f.moveCell(a[e],c.x,c.y))}};
-mxLayoutManager.prototype.getCellsForChanges=function(a){for(var b=new mxDictionary,c=[],d=0;df||Math.abs(d)>f){null==this.highlight&&(this.highlight=new mxCellHighlight(this.graph,mxConstants.DROP_TARGET_COLOR,3));null==this.shape&&(this.shape=this.createPreviewShape(this.bounds));var g=c.isGridEnabledEvent(b.getEvent()),
-f=!0;if(null!=this.guide&&this.useGuidesForEvent(b))d=this.guide.move(this.bounds,new mxPoint(e,d),g),f=!1,e=d.x,d=d.y;else if(g)var k=c.getView().translate,l=c.getView().scale,g=this.bounds.x-(c.snap(this.bounds.x/l-k.x)+k.x)*l,k=this.bounds.y-(c.snap(this.bounds.y/l-k.y)+k.y)*l,d=this.snap(new mxPoint(e,d)),e=d.x-g,d=d.y-k;null!=this.guide&&f&&this.guide.hide();c.isConstrainedEvent(b.getEvent())&&(Math.abs(e)>Math.abs(d)?d=0:e=0);this.currentDx=e;this.currentDy=d;this.updatePreviewShape();f=null;
-d=b.getCell();g=c.isCloneEvent(b.getEvent())&&c.isCellsCloneable()&&this.isCloneEnabled();c.isDropEnabled()&&this.highlightEnabled&&(f=c.getDropTarget(this.cells,b.getEvent(),d,g));e=c.getView().getState(f);k=!1;null==e||c.model.getParent(this.cell)==f&&!g?(this.target=null,this.connectOnDrop&&null!=d&&1==this.cells.length&&c.getModel().isVertex(d)&&c.isCellConnectable(d)&&(e=c.getView().getState(d),null!=e&&(c=null==c.getEdgeValidationError(null,this.cell,d)?mxConstants.VALID_COLOR:mxConstants.INVALID_CONNECT_TARGET_COLOR,
-this.setHighlightColor(c),k=!0))):(this.target!=f&&(this.target=f,this.setHighlightColor(mxConstants.DROP_TARGET_COLOR)),k=!0);null!=e&&k?this.highlight.highlight(e):this.highlight.hide()}this.updateHint(b);this.consumeMouseEvent(mxEvent.MOUSE_MOVE,b);mxEvent.consume(b.getEvent())}else!this.isMoveEnabled()&&!this.isCloneEnabled()||!this.updateCursor||b.isConsumed()||null==b.getState()&&null==b.sourceState||c.isMouseDown||(e=c.getCursorForMouseEvent(b),null==e&&c.isEnabled()&&c.isCellMovable(b.getCell())&&
-(e=c.getModel().isEdge(b.getCell())?mxConstants.CURSOR_MOVABLE_EDGE:mxConstants.CURSOR_MOVABLE_VERTEX),null!=e&&null!=b.sourceState&&b.sourceState.setCursor(e))};mxGraphHandler.prototype.updatePreviewShape=function(){null!=this.shape&&(this.shape.bounds=new mxRectangle(Math.round(this.pBounds.x+this.currentDx-this.graph.panDx),Math.round(this.pBounds.y+this.currentDy-this.graph.panDy),this.pBounds.width,this.pBounds.height),this.shape.redraw())};
-mxGraphHandler.prototype.setHighlightColor=function(a){null!=this.highlight&&this.highlight.setHighlightColor(a)};
-mxGraphHandler.prototype.mouseUp=function(a,b){if(!b.isConsumed()){var c=this.graph;if(null!=this.cell&&null!=this.first&&null!=this.shape&&null!=this.currentDx&&null!=this.currentDy){var d=b.getCell();if(this.connectOnDrop&&null==this.target&&null!=d&&c.getModel().isVertex(d)&&c.isCellConnectable(d)&&c.isEdgeValid(null,this.cell,d))c.connectionHandler.connect(this.cell,d,b.getEvent());else{var d=c.isCloneEvent(b.getEvent())&&c.isCellsCloneable()&&this.isCloneEnabled(),e=c.getView().scale,f=this.roundLength(this.currentDx/
-e),e=this.roundLength(this.currentDy/e),g=this.target;c.isSplitEnabled()&&c.isSplitTarget(g,this.cells,b.getEvent())?c.splitEdge(g,this.cells,null,f,e):this.moveCells(this.cells,f,e,d,this.target,b.getEvent())}}else this.isSelectEnabled()&&this.delayedSelection&&null!=this.cell&&this.selectDelayed(b)}this.cellWasClicked&&this.consumeMouseEvent(mxEvent.MOUSE_UP,b);this.reset()};
-mxGraphHandler.prototype.selectDelayed=function(a){this.graph.isCellSelected(this.cell)&&this.graph.popupMenuHandler.isPopupTrigger(a)||this.graph.selectCellForEvent(this.cell,a.getEvent())};mxGraphHandler.prototype.reset=function(){this.destroyShapes();this.removeHint();this.delayedSelection=this.cellWasClicked=!1;this.target=this.cell=this.first=this.guides=this.currentDy=this.currentDx=null};
-mxGraphHandler.prototype.shouldRemoveCellsFromParent=function(a,b,c){if(this.graph.getModel().isVertex(a)&&(a=this.graph.getView().getState(a),null!=a)){c=mxUtils.convertPoint(this.graph.container,mxEvent.getClientX(c),mxEvent.getClientY(c));var d=mxUtils.toRadians(mxUtils.getValue(a.style,mxConstants.STYLE_ROTATION)||0);if(0!=d){b=Math.cos(-d);var d=Math.sin(-d),e=new mxPoint(a.getCenterX(),a.getCenterY());c=mxUtils.getRotatedPoint(c,b,d,e)}return!mxUtils.contains(a,c.x,c.y)}return!1};
-mxGraphHandler.prototype.moveCells=function(a,b,c,d,e,f){d&&(a=this.graph.getCloneableCells(a));null==e&&this.isRemoveCellsFromParent()&&this.shouldRemoveCellsFromParent(this.graph.getModel().getParent(this.cell),a,f)&&(e=this.graph.getDefaultParent());d=d&&!this.graph.isCellLocked(e||this.graph.getDefaultParent());a=this.graph.moveCells(a,b-this.graph.panDx/this.graph.view.scale,c-this.graph.panDy/this.graph.view.scale,d,e,f);this.isSelectEnabled()&&this.scrollOnMove&&this.graph.scrollCellToVisible(a[0]);
-d&&this.graph.setSelectionCells(a)};mxGraphHandler.prototype.destroyShapes=function(){null!=this.shape&&(this.shape.destroy(),this.shape=null);null!=this.guide&&(this.guide.destroy(),this.guide=null);null!=this.highlight&&(this.highlight.destroy(),this.highlight=null)};
-mxGraphHandler.prototype.destroy=function(){this.graph.removeMouseListener(this);this.graph.removeListener(this.panHandler);null!=this.escapeHandler&&(this.graph.removeListener(this.escapeHandler),this.escapeHandler=null);this.destroyShapes();this.removeHint()};
-function mxPanningHandler(a){null!=a&&(this.graph=a,this.graph.addMouseListener(this),this.forcePanningHandler=mxUtils.bind(this,function(a,c){var b=c.getProperty("eventName"),e=c.getProperty("event");b==mxEvent.MOUSE_DOWN&&this.isForcePanningEvent(e)&&(this.start(e),this.active=!0,this.fireEvent(new mxEventObject(mxEvent.PAN_START,"event",e)),e.consume())}),this.graph.addListener(mxEvent.FIRE_MOUSE_EVENT,this.forcePanningHandler),this.gestureHandler=mxUtils.bind(this,function(a,c){if(this.isPinchEnabled()){var b=
-c.getProperty("event");mxEvent.isConsumed(b)||"gesturestart"!=b.type?"gestureend"==b.type&&null!=this.initialScale&&(this.initialScale=null):(this.initialScale=this.graph.view.scale,this.active||null==this.mouseDownEvent||(this.start(this.mouseDownEvent),this.mouseDownEvent=null));if(null!=this.initialScale){var e=Math.round(this.initialScale*b.scale*100)/100;null!=this.minScale&&(e=Math.max(this.minScale,e));null!=this.maxScale&&(e=Math.min(this.maxScale,e));this.graph.view.scale!=e&&(this.graph.zoomTo(e),
-mxEvent.consume(b))}}}),this.graph.addListener(mxEvent.GESTURE,this.gestureHandler),this.mouseUpListener=mxUtils.bind(this,function(){this.active&&this.reset()}),mxEvent.addListener(document,"mouseup",this.mouseUpListener))}mxPanningHandler.prototype=new mxEventSource;mxPanningHandler.prototype.constructor=mxPanningHandler;mxPanningHandler.prototype.graph=null;mxPanningHandler.prototype.useLeftButtonForPanning=!1;mxPanningHandler.prototype.usePopupTrigger=!0;
-mxPanningHandler.prototype.ignoreCell=!1;mxPanningHandler.prototype.previewEnabled=!0;mxPanningHandler.prototype.useGrid=!1;mxPanningHandler.prototype.panningEnabled=!0;mxPanningHandler.prototype.pinchEnabled=!0;mxPanningHandler.prototype.maxScale=8;mxPanningHandler.prototype.minScale=.01;mxPanningHandler.prototype.dx=null;mxPanningHandler.prototype.dy=null;mxPanningHandler.prototype.startX=0;mxPanningHandler.prototype.startY=0;
-mxPanningHandler.prototype.isActive=function(){return this.active||null!=this.initialScale};mxPanningHandler.prototype.isPanningEnabled=function(){return this.panningEnabled};mxPanningHandler.prototype.setPanningEnabled=function(a){this.panningEnabled=a};mxPanningHandler.prototype.isPinchEnabled=function(){return this.pinchEnabled};mxPanningHandler.prototype.setPinchEnabled=function(a){this.pinchEnabled=a};
-mxPanningHandler.prototype.isPanningTrigger=function(a){var b=a.getEvent();return this.useLeftButtonForPanning&&null==a.getState()&&mxEvent.isLeftMouseButton(b)||mxEvent.isControlDown(b)&&mxEvent.isShiftDown(b)||this.usePopupTrigger&&mxEvent.isPopupTrigger(b)};mxPanningHandler.prototype.isForcePanningEvent=function(a){return this.ignoreCell||mxEvent.isMultiTouchEvent(a.getEvent())};
-mxPanningHandler.prototype.mouseDown=function(a,b){this.mouseDownEvent=b;!b.isConsumed()&&this.isPanningEnabled()&&!this.active&&this.isPanningTrigger(b)&&(this.start(b),this.consumePanningTrigger(b))};mxPanningHandler.prototype.start=function(a){this.dx0=-this.graph.container.scrollLeft;this.dy0=-this.graph.container.scrollTop;this.startX=a.getX();this.startY=a.getY();this.dy=this.dx=null;this.panningTrigger=!0};mxPanningHandler.prototype.consumePanningTrigger=function(a){a.consume()};
-mxPanningHandler.prototype.mouseMove=function(a,b){this.dx=b.getX()-this.startX;this.dy=b.getY()-this.startY;if(this.active)this.previewEnabled&&(this.useGrid&&(this.dx=this.graph.snap(this.dx),this.dy=this.graph.snap(this.dy)),this.graph.panGraph(this.dx+this.dx0,this.dy+this.dy0)),this.fireEvent(new mxEventObject(mxEvent.PAN,"event",b));else if(this.panningTrigger){var c=this.active;this.active=Math.abs(this.dx)>this.graph.tolerance||Math.abs(this.dy)>this.graph.tolerance;!c&&this.active&&this.fireEvent(new mxEventObject(mxEvent.PAN_START,
-"event",b))}(this.active||this.panningTrigger)&&b.consume()};mxPanningHandler.prototype.mouseUp=function(a,b){if(this.active){if(null!=this.dx&&null!=this.dy){if(!this.graph.useScrollbarsForPanning||!mxUtils.hasScrollbars(this.graph.container)){var c=this.graph.getView().scale,d=this.graph.getView().translate;this.graph.panGraph(0,0);this.panGraph(d.x+this.dx/c,d.y+this.dy/c)}b.consume()}this.fireEvent(new mxEventObject(mxEvent.PAN_END,"event",b))}this.reset()};
-mxPanningHandler.prototype.reset=function(){this.panningTrigger=!1;this.mouseDownEvent=null;this.active=!1;this.dy=this.dx=null};mxPanningHandler.prototype.panGraph=function(a,b){this.graph.getView().setTranslate(a,b)};mxPanningHandler.prototype.destroy=function(){this.graph.removeMouseListener(this);this.graph.removeListener(this.forcePanningHandler);this.graph.removeListener(this.gestureHandler);mxEvent.removeListener(document,"mouseup",this.mouseUpListener)};
-function mxPopupMenuHandler(a,b){null!=a&&(this.graph=a,this.factoryMethod=b,this.graph.addMouseListener(this),this.gestureHandler=mxUtils.bind(this,function(a,b){this.inTolerance=!1}),this.graph.addListener(mxEvent.GESTURE,this.gestureHandler),this.init())}mxPopupMenuHandler.prototype=new mxPopupMenu;mxPopupMenuHandler.prototype.constructor=mxPopupMenuHandler;mxPopupMenuHandler.prototype.graph=null;mxPopupMenuHandler.prototype.selectOnPopup=!0;
-mxPopupMenuHandler.prototype.clearSelectionOnBackground=!0;mxPopupMenuHandler.prototype.triggerX=null;mxPopupMenuHandler.prototype.triggerY=null;mxPopupMenuHandler.prototype.screenX=null;mxPopupMenuHandler.prototype.screenY=null;mxPopupMenuHandler.prototype.init=function(){mxPopupMenu.prototype.init.apply(this);mxEvent.addGestureListeners(this.div,mxUtils.bind(this,function(a){this.graph.tooltipHandler.hide()}))};mxPopupMenuHandler.prototype.isSelectOnPopup=function(a){return this.selectOnPopup};
-mxPopupMenuHandler.prototype.mouseDown=function(a,b){this.isEnabled()&&!mxEvent.isMultiTouchEvent(b.getEvent())&&(this.hideMenu(),this.triggerX=b.getGraphX(),this.triggerY=b.getGraphY(),this.screenX=mxEvent.getMainEvent(b.getEvent()).screenX,this.screenY=mxEvent.getMainEvent(b.getEvent()).screenY,this.popupTrigger=this.isPopupTrigger(b),this.inTolerance=!0)};
-mxPopupMenuHandler.prototype.mouseMove=function(a,b){this.inTolerance&&null!=this.screenX&&null!=this.screenY&&(Math.abs(mxEvent.getMainEvent(b.getEvent()).screenX-this.screenX)>this.graph.tolerance||Math.abs(mxEvent.getMainEvent(b.getEvent()).screenY-this.screenY)>this.graph.tolerance)&&(this.inTolerance=!1)};
-mxPopupMenuHandler.prototype.mouseUp=function(a,b){if(this.popupTrigger&&this.inTolerance&&null!=this.triggerX&&null!=this.triggerY){var c=this.getCellForPopupEvent(b);this.graph.isEnabled()&&this.isSelectOnPopup(b)&&null!=c&&!this.graph.isCellSelected(c)?this.graph.setSelectionCell(c):this.clearSelectionOnBackground&&null==c&&this.graph.clearSelection();this.graph.tooltipHandler.hide();var d=mxUtils.getScrollOrigin();this.popup(b.getX()+d.x+1,b.getY()+d.y+1,c,b.getEvent());b.consume()}this.inTolerance=
-this.popupTrigger=!1};mxPopupMenuHandler.prototype.getCellForPopupEvent=function(a){return a.getCell()};mxPopupMenuHandler.prototype.destroy=function(){this.graph.removeMouseListener(this);this.graph.removeListener(this.gestureHandler);mxPopupMenu.prototype.destroy.apply(this)};
-function mxCellMarker(a,b,c,d){mxEventSource.call(this);null!=a&&(this.graph=a,this.validColor=null!=b?b:mxConstants.DEFAULT_VALID_COLOR,this.invalidColor=null!=b?c:mxConstants.DEFAULT_INVALID_COLOR,this.hotspot=null!=d?d:mxConstants.DEFAULT_HOTSPOT,this.highlight=new mxCellHighlight(a))}mxUtils.extend(mxCellMarker,mxEventSource);mxCellMarker.prototype.graph=null;mxCellMarker.prototype.enabled=!0;mxCellMarker.prototype.hotspot=mxConstants.DEFAULT_HOTSPOT;mxCellMarker.prototype.hotspotEnabled=!1;
-mxCellMarker.prototype.validColor=null;mxCellMarker.prototype.invalidColor=null;mxCellMarker.prototype.currentColor=null;mxCellMarker.prototype.validState=null;mxCellMarker.prototype.markedState=null;mxCellMarker.prototype.setEnabled=function(a){this.enabled=a};mxCellMarker.prototype.isEnabled=function(){return this.enabled};mxCellMarker.prototype.setHotspot=function(a){this.hotspot=a};mxCellMarker.prototype.getHotspot=function(){return this.hotspot};
-mxCellMarker.prototype.setHotspotEnabled=function(a){this.hotspotEnabled=a};mxCellMarker.prototype.isHotspotEnabled=function(){return this.hotspotEnabled};mxCellMarker.prototype.hasValidState=function(){return null!=this.validState};mxCellMarker.prototype.getValidState=function(){return this.validState};mxCellMarker.prototype.getMarkedState=function(){return this.markedState};mxCellMarker.prototype.reset=function(){this.validState=null;null!=this.markedState&&(this.markedState=null,this.unmark())};
-mxCellMarker.prototype.process=function(a){var b=null;this.isEnabled()&&(b=this.getState(a),this.setCurrentState(b,a));return b};mxCellMarker.prototype.setCurrentState=function(a,b,c){var d=null!=a?this.isValidState(a):!1;c=null!=c?c:this.getMarkerColor(b.getEvent(),a,d);this.validState=d?a:null;if(a!=this.markedState||c!=this.currentColor)this.currentColor=c,null!=a&&null!=this.currentColor?(this.markedState=a,this.mark()):null!=this.markedState&&(this.markedState=null,this.unmark())};
-mxCellMarker.prototype.markCell=function(a,b){var c=this.graph.getView().getState(a);null!=c&&(this.currentColor=null!=b?b:this.validColor,this.markedState=c,this.mark())};mxCellMarker.prototype.mark=function(){this.highlight.setHighlightColor(this.currentColor);this.highlight.highlight(this.markedState);this.fireEvent(new mxEventObject(mxEvent.MARK,"state",this.markedState))};mxCellMarker.prototype.unmark=function(){this.mark()};mxCellMarker.prototype.isValidState=function(a){return!0};
-mxCellMarker.prototype.getMarkerColor=function(a,b,c){return c?this.validColor:this.invalidColor};mxCellMarker.prototype.getState=function(a){var b=this.graph.getView(),c=this.getCell(a),b=this.getStateToMark(b.getState(c));return null!=b&&this.intersects(b,a)?b:null};mxCellMarker.prototype.getCell=function(a){return a.getCell()};mxCellMarker.prototype.getStateToMark=function(a){return a};
-mxCellMarker.prototype.intersects=function(a,b){return this.hotspotEnabled?mxUtils.intersectsHotspot(a,b.getGraphX(),b.getGraphY(),this.hotspot,mxConstants.MIN_HOTSPOT_SIZE,mxConstants.MAX_HOTSPOT_SIZE):!0};mxCellMarker.prototype.destroy=function(){this.graph.getView().removeListener(this.resetHandler);this.graph.getModel().removeListener(this.resetHandler);this.highlight.destroy()};
-function mxSelectionCellsHandler(a){mxEventSource.call(this);this.graph=a;this.handlers=new mxDictionary;this.graph.addMouseListener(this);this.refreshHandler=mxUtils.bind(this,function(a,c){this.isEnabled()&&this.refresh()});this.graph.getSelectionModel().addListener(mxEvent.CHANGE,this.refreshHandler);this.graph.getModel().addListener(mxEvent.CHANGE,this.refreshHandler);this.graph.getView().addListener(mxEvent.SCALE,this.refreshHandler);this.graph.getView().addListener(mxEvent.TRANSLATE,this.refreshHandler);
-this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE,this.refreshHandler);this.graph.getView().addListener(mxEvent.DOWN,this.refreshHandler);this.graph.getView().addListener(mxEvent.UP,this.refreshHandler)}mxUtils.extend(mxSelectionCellsHandler,mxEventSource);mxSelectionCellsHandler.prototype.graph=null;mxSelectionCellsHandler.prototype.enabled=!0;mxSelectionCellsHandler.prototype.refreshHandler=null;mxSelectionCellsHandler.prototype.maxHandlers=100;
-mxSelectionCellsHandler.prototype.handlers=null;mxSelectionCellsHandler.prototype.isEnabled=function(){return this.enabled};mxSelectionCellsHandler.prototype.setEnabled=function(a){this.enabled=a};mxSelectionCellsHandler.prototype.getHandler=function(a){return this.handlers.get(a)};mxSelectionCellsHandler.prototype.reset=function(){this.handlers.visit(function(a,b){b.reset.apply(b)})};
-mxSelectionCellsHandler.prototype.refresh=function(){var a=this.handlers;this.handlers=new mxDictionary;for(var b=this.graph.getSelectionCells(),c=0;cthis.graph.tolerance||g>this.graph.tolerance)&&(this.shape=this.createShape(),
-null!=this.edgeState&&this.shape.apply(this.edgeState),this.updateCurrentState(b,c));null!=this.shape&&(null!=this.edgeState?this.shape.points=this.edgeState.absolutePoints:(c=[e],null!=this.waypoints&&(c=c.concat(this.waypoints)),c.push(d),this.shape.points=c),this.drawPreview());null!=this.cursor&&(this.graph.container.style.cursor=this.cursor);mxEvent.consume(b.getEvent());b.consume()}else this.isEnabled()&&this.graph.isEnabled()?this.previous!=this.currentState&&null==this.edgeState?(this.destroyIcons(),
-null!=this.currentState&&null==this.error&&null==this.constraintHandler.currentConstraint&&(this.icons=this.createIcons(this.currentState),null==this.icons&&(this.currentState.setCursor(mxConstants.CURSOR_CONNECT),b.consume())),this.previous=this.currentState):this.previous!=this.currentState||null==this.currentState||null!=this.icons||this.graph.isMouseDown||b.consume():this.constraintHandler.reset();if(!this.graph.isMouseDown&&null!=this.currentState&&null!=this.icons){c=!1;d=b.getSource();for(e=
-0;ethis.graph.tolerance||b>this.graph.tolerance))null==this.waypoints&&(this.waypoints=[]),c=this.graph.view.scale,b=new mxPoint(this.graph.snap(a.getGraphX()/c)*c,this.graph.snap(a.getGraphY()/c)*c),this.waypoints.push(b)};
-mxConnectionHandler.prototype.mouseUp=function(a,b){if(!b.isConsumed()&&this.isConnecting()){if(this.waypointsEnabled&&!this.isStopEvent(b)){this.addWaypointForEvent(b);b.consume();return}if(null==this.error){var c=null!=this.previous?this.previous.cell:null,d=null;null!=this.constraintHandler.currentConstraint&&null!=this.constraintHandler.currentFocus&&(d=this.constraintHandler.currentFocus.cell);null==d&&null!=this.currentState&&(d=this.currentState.cell);this.connect(c,d,b.getEvent(),b.getCell())}else null!=
-this.previous&&null!=this.marker.validState&&this.previous.cell==this.marker.validState.cell&&this.graph.selectCellForEvent(this.marker.source,evt),0g||Math.abs(f)>g)null==this.div&&(this.div=this.createShape()),mxUtils.clearSelection(),this.update(d,c),b.consume()}};
-mxRubberband.prototype.createShape=function(){null==this.sharedDiv&&(this.sharedDiv=document.createElement("div"),this.sharedDiv.className="mxRubberband",mxUtils.setOpacity(this.sharedDiv,this.defaultOpacity));this.graph.container.appendChild(this.sharedDiv);var a=this.sharedDiv;mxClient.IS_SVG&&(!mxClient.IS_IE||10<=document.documentMode)&&this.fadeOut&&(this.sharedDiv=null);return a};mxRubberband.prototype.isActive=function(a,b){return null!=this.div&&"none"!=this.div.style.display};
-mxRubberband.prototype.mouseUp=function(a,b){var c=this.isActive();this.reset();c&&(this.execute(b.getEvent()),b.consume())};mxRubberband.prototype.execute=function(a){var b=new mxRectangle(this.x,this.y,this.width,this.height);this.graph.selectRegion(b,a)};
-mxRubberband.prototype.reset=function(){if(null!=this.div)if(mxClient.IS_SVG&&(!mxClient.IS_IE||10<=document.documentMode)&&this.fadeOut){var a=this.div;mxUtils.setPrefixedStyle(a.style,"transition","all 0.2s linear");a.style.pointerEvents="none";a.style.opacity=0;window.setTimeout(function(){a.parentNode.removeChild(a)},200)}else this.div.parentNode.removeChild(this.div);mxEvent.removeGestureListeners(document,null,this.dragHandler,this.dropHandler);this.dropHandler=this.dragHandler=null;this.currentY=
-this.currentX=0;this.div=this.first=null};mxRubberband.prototype.update=function(a,b){this.currentX=a;this.currentY=b;this.repaint()};
-mxRubberband.prototype.repaint=function(){if(null!=this.div){var a=this.currentX-this.graph.panDx,b=this.currentY-this.graph.panDy;this.x=Math.min(this.first.x,a);this.y=Math.min(this.first.y,b);this.width=Math.max(this.first.x,a)-this.x;this.height=Math.max(this.first.y,b)-this.y;a=mxClient.IS_VML?this.graph.panDy:0;this.div.style.left=this.x+(mxClient.IS_VML?this.graph.panDx:0)+"px";this.div.style.top=this.y+a+"px";this.div.style.width=Math.max(1,this.width)+"px";this.div.style.height=Math.max(1,
-this.height)+"px"}};mxRubberband.prototype.destroy=function(){this.destroyed||(this.destroyed=!0,this.graph.removeMouseListener(this),this.graph.removeListener(this.forceRubberbandHandler),this.graph.removeListener(this.panHandler),this.reset(),null!=this.sharedDiv&&(this.sharedDiv=null))};function mxHandle(a,b,c){this.graph=a.view.graph;this.state=a;this.cursor=null!=b?b:this.cursor;this.image=null!=c?c:this.image;this.init()}mxHandle.prototype.cursor="default";mxHandle.prototype.image=null;
-mxHandle.prototype.ignoreGrid=!1;mxHandle.prototype.getPosition=function(a){};mxHandle.prototype.setPosition=function(a,b,c){};mxHandle.prototype.execute=function(){};mxHandle.prototype.copyStyle=function(a){this.graph.setCellStyles(a,this.state.style[a],[this.state.cell])};
-mxHandle.prototype.processEvent=function(a){var b=this.graph.view.scale,c=this.graph.view.translate,c=new mxPoint(a.getGraphX()/b-c.x,a.getGraphY()/b-c.y);null!=this.shape&&null!=this.shape.bounds&&(c.x-=this.shape.bounds.width/b/4,c.y-=this.shape.bounds.height/b/4);var b=-mxUtils.toRadians(this.getRotation()),d=-mxUtils.toRadians(this.getTotalRotation())-b,c=this.flipPoint(this.rotatePoint(this.snapPoint(this.rotatePoint(c,b),this.ignoreGrid||!this.graph.isGridEnabledEvent(a.getEvent())),d));this.setPosition(this.state.getPaintBounds(),
-c,a);this.positionChanged();this.redraw()};mxHandle.prototype.positionChanged=function(){null!=this.state.text&&this.state.text.apply(this.state);null!=this.state.shape&&this.state.shape.apply(this.state);this.graph.cellRenderer.redraw(this.state,!0)};mxHandle.prototype.getRotation=function(){return null!=this.state.shape?this.state.shape.getRotation():0};mxHandle.prototype.getTotalRotation=function(){return null!=this.state.shape?this.state.shape.getShapeRotation():0};
-mxHandle.prototype.init=function(){var a=this.isHtmlRequired();null!=this.image?(this.shape=new mxImageShape(new mxRectangle(0,0,this.image.width,this.image.height),this.image.src),this.shape.preserveImageAspect=!1):this.shape=this.createShape(a);this.initShape(a)};mxHandle.prototype.createShape=function(a){a=new mxRectangle(0,0,mxConstants.HANDLE_SIZE,mxConstants.HANDLE_SIZE);return new mxRectangleShape(a,mxConstants.HANDLE_FILLCOLOR,mxConstants.HANDLE_STROKECOLOR)};
-mxHandle.prototype.initShape=function(a){a&&this.shape.isHtmlAllowed()?(this.shape.dialect=mxConstants.DIALECT_STRICTHTML,this.shape.init(this.graph.container)):(this.shape.dialect=this.graph.dialect!=mxConstants.DIALECT_SVG?mxConstants.DIALECT_MIXEDHTML:mxConstants.DIALECT_SVG,null!=this.cursor&&this.shape.init(this.graph.getView().getOverlayPane()));mxEvent.redirectMouseEvents(this.shape.node,this.graph,this.state);this.shape.node.style.cursor=this.cursor};
-mxHandle.prototype.redraw=function(){if(null!=this.shape&&null!=this.state.shape){var a=this.getPosition(this.state.getPaintBounds());if(null!=a){var b=mxUtils.toRadians(this.getTotalRotation()),a=this.rotatePoint(this.flipPoint(a),b),b=this.graph.view.scale,c=this.graph.view.translate;this.shape.bounds.x=Math.floor((a.x+c.x)*b-this.shape.bounds.width/2);this.shape.bounds.y=Math.floor((a.y+c.y)*b-this.shape.bounds.height/2);this.shape.redraw()}}};
-mxHandle.prototype.isHtmlRequired=function(){return null!=this.state.text&&this.state.text.node.parentNode==this.graph.container};mxHandle.prototype.rotatePoint=function(a,b){var c=this.state.getCellBounds(),c=new mxPoint(c.getCenterX(),c.getCenterY());return mxUtils.getRotatedPoint(a,Math.cos(b),Math.sin(b),c)};
-mxHandle.prototype.flipPoint=function(a){if(null!=this.state.shape){var b=this.state.getCellBounds();this.state.shape.flipH&&(a.x=2*b.x+b.width-a.x);this.state.shape.flipV&&(a.y=2*b.y+b.height-a.y)}return a};mxHandle.prototype.snapPoint=function(a,b){b||(a.x=this.graph.snap(a.x),a.y=this.graph.snap(a.y));return a};mxHandle.prototype.setVisible=function(a){null!=this.shape&&null!=this.shape.node&&(this.shape.node.style.display=a?"":"none")};
-mxHandle.prototype.reset=function(){this.setVisible(!0);this.state.style=this.graph.getCellStyle(this.state.cell);this.positionChanged()};mxHandle.prototype.destroy=function(){null!=this.shape&&(this.shape.destroy(),this.shape=null)};
-function mxVertexHandler(a){null!=a&&(this.state=a,this.init(),this.escapeHandler=mxUtils.bind(this,function(a,c){this.livePreview&&null!=this.index&&(this.state.view.graph.cellRenderer.redraw(this.state,!0),this.state.view.invalidate(this.state.cell),this.state.invalid=!1,this.state.view.validate());this.reset()}),this.state.view.graph.addListener(mxEvent.ESCAPE,this.escapeHandler))}mxVertexHandler.prototype.graph=null;mxVertexHandler.prototype.state=null;mxVertexHandler.prototype.singleSizer=!1;
-mxVertexHandler.prototype.index=null;mxVertexHandler.prototype.allowHandleBoundsCheck=!0;mxVertexHandler.prototype.handleImage=null;mxVertexHandler.prototype.tolerance=0;mxVertexHandler.prototype.rotationEnabled=!1;mxVertexHandler.prototype.parentHighlightEnabled=!1;mxVertexHandler.prototype.rotationRaster=!0;mxVertexHandler.prototype.rotationCursor="crosshair";mxVertexHandler.prototype.livePreview=!1;mxVertexHandler.prototype.manageSizers=!1;mxVertexHandler.prototype.constrainGroupByChildren=!1;
-mxVertexHandler.prototype.rotationHandleVSpacing=-16;mxVertexHandler.prototype.horizontalOffset=0;mxVertexHandler.prototype.verticalOffset=0;
-mxVertexHandler.prototype.init=function(){this.graph=this.state.view.graph;this.selectionBounds=this.getSelectionBounds(this.state);this.bounds=new mxRectangle(this.selectionBounds.x,this.selectionBounds.y,this.selectionBounds.width,this.selectionBounds.height);this.selectionBorder=this.createSelectionShape(this.bounds);this.selectionBorder.dialect=this.graph.dialect!=mxConstants.DIALECT_SVG?mxConstants.DIALECT_VML:mxConstants.DIALECT_SVG;this.selectionBorder.pointerEvents=!1;this.selectionBorder.rotation=
-Number(this.state.style[mxConstants.STYLE_ROTATION]||"0");this.selectionBorder.init(this.graph.getView().getOverlayPane());mxEvent.redirectMouseEvents(this.selectionBorder.node,this.graph,this.state);this.graph.isCellMovable(this.state.cell)&&this.selectionBorder.setCursor(mxConstants.CURSOR_MOVABLE_VERTEX);if(0>=mxGraphHandler.prototype.maxCells||this.graph.getSelectionCount()this.state.width&&2>this.state.height&&(this.labelShape=this.createSizer(mxConstants.CURSOR_MOVABLE_VERTEX,mxEvent.LABEL_HANDLE,
-null,mxConstants.LABEL_HANDLE_FILLCOLOR),this.sizers.push(this.labelShape))}this.isRotationHandleVisible()&&(this.rotationShape=this.createSizer(this.rotationCursor,mxEvent.ROTATION_HANDLE,mxConstants.HANDLE_SIZE+3,mxConstants.HANDLE_FILLCOLOR),this.sizers.push(this.rotationShape));this.customHandles=this.createCustomHandles();this.redraw();this.constrainGroupByChildren&&this.updateMinBounds()};
-mxVertexHandler.prototype.isRotationHandleVisible=function(){return this.graph.isEnabled()&&this.rotationEnabled&&this.graph.isCellRotatable(this.state.cell)&&(0>=mxGraphHandler.prototype.maxCells||this.graph.getSelectionCount()this.graph.tolerance||Math.abs(a.getGraphY()-this.startY)>this.graph.tolerance)&&(this.inTolerance=!1)};mxVertexHandler.prototype.updateHint=function(a){};mxVertexHandler.prototype.removeHint=function(){};mxVertexHandler.prototype.roundAngle=function(a){return Math.round(10*a)/10};
-mxVertexHandler.prototype.roundLength=function(a){return Math.round(a)};
-mxVertexHandler.prototype.mouseMove=function(a,b){b.isConsumed()||null==this.index?this.graph.isMouseDown||null==this.getHandleForEvent(b)||b.consume(!1):(this.checkTolerance(b),this.inTolerance||(this.index<=mxEvent.CUSTOM_HANDLE?null!=this.customHandles&&(this.customHandles[mxEvent.CUSTOM_HANDLE-this.index].processEvent(b),this.customHandles[mxEvent.CUSTOM_HANDLE-this.index].active=!0):this.index==mxEvent.LABEL_HANDLE?this.moveLabel(b):this.index==mxEvent.ROTATION_HANDLE?this.rotateVertex(b):this.resizeVertex(b),
-this.updateHint(b)),b.consume())};mxVertexHandler.prototype.moveLabel=function(a){var b=new mxPoint(a.getGraphX(),a.getGraphY()),c=this.graph.view.translate,d=this.graph.view.scale;this.graph.isGridEnabledEvent(a.getEvent())&&(b.x=(this.graph.snap(b.x/d-c.x)+c.x)*d,b.y=(this.graph.snap(b.y/d-c.y)+c.y)*d);this.moveSizerTo(this.sizers[null!=this.rotationShape?this.sizers.length-2:this.sizers.length-1],b.x,b.y)};
-mxVertexHandler.prototype.rotateVertex=function(a){var b=new mxPoint(a.getGraphX(),a.getGraphY()),c=this.state.x+this.state.width/2-b.x,d=this.state.y+this.state.height/2-b.y;this.currentAlpha=0!=c?180*Math.atan(d/c)/Math.PI+90:0>d?180:0;0k.x+k.width&&(this.unscaledBounds.width-=this.unscaledBounds.x+this.unscaledBounds.width-k.x-k.width),this.unscaledBounds.y+this.unscaledBounds.height>
-k.y+k.height&&(this.unscaledBounds.height-=this.unscaledBounds.y+this.unscaledBounds.height-k.y-k.height)));this.bounds=new mxRectangle((null!=this.parentState?this.parentState.x:e.x*f)+this.unscaledBounds.x*f,(null!=this.parentState?this.parentState.y:e.y*f)+this.unscaledBounds.y*f,this.unscaledBounds.width*f,this.unscaledBounds.height*f);g.relative&&null!=this.parentState&&(this.bounds.x+=this.state.x-this.parentState.x,this.bounds.y+=this.state.y-this.parentState.y);g=Math.cos(c);k=Math.sin(c);
-c=new mxPoint(this.bounds.getCenterX(),this.bounds.getCenterY());l=c.x-b.x;d=c.y-b.y;b=g*l-k*d-l;c=k*l+g*d-d;l=this.bounds.x-this.state.x;d=this.bounds.y-this.state.y;e=g*l-k*d;g=k*l+g*d;this.bounds.x+=b;this.bounds.y+=c;this.unscaledBounds.x=this.roundLength(this.unscaledBounds.x+b/f);this.unscaledBounds.y=this.roundLength(this.unscaledBounds.y+c/f);this.unscaledBounds.width=this.roundLength(this.unscaledBounds.width);this.unscaledBounds.height=this.roundLength(this.unscaledBounds.height);this.graph.isCellCollapsed(this.state.cell)||
-0==b&&0==c?this.childOffsetY=this.childOffsetX=0:(this.childOffsetX=this.state.x-this.bounds.x+e,this.childOffsetY=this.state.y-this.bounds.y+g);this.livePreview&&this.updateLivePreview(a);null!=this.preview&&this.drawPreview()};
-mxVertexHandler.prototype.updateLivePreview=function(a){var b=this.graph.view.scale,c=this.graph.view.translate;a=this.state.clone();this.state.x=this.bounds.x;this.state.y=this.bounds.y;this.state.origin=new mxPoint(this.state.x/b-c.x,this.state.y/b-c.y);this.state.width=this.bounds.width;this.state.height=this.bounds.height;this.state.unscaledWidth=null;b=this.state.absoluteOffset;new mxPoint(b.x,b.y);this.state.absoluteOffset.x=0;this.state.absoluteOffset.y=0;b=this.graph.getCellGeometry(this.state.cell);
-null!=b&&(c=b.offset||this.EMPTY_POINT,null==c||b.relative||(this.state.absoluteOffset.x=this.state.view.scale*c.x,this.state.absoluteOffset.y=this.state.view.scale*c.y),this.state.view.updateVertexLabelOffset(this.state));this.state.view.graph.cellRenderer.redraw(this.state,!0);this.state.view.invalidate(this.state.cell);this.state.invalid=!1;this.state.view.validate();this.redrawHandles();this.state.setState(a)};
-mxVertexHandler.prototype.mouseUp=function(a,b){if(null!=this.index&&null!=this.state){var c=new mxPoint(b.getGraphX(),b.getGraphY());this.graph.getModel().beginUpdate();try{if(this.index<=mxEvent.CUSTOM_HANDLE)null!=this.customHandles&&(this.customHandles[mxEvent.CUSTOM_HANDLE-this.index].active=!1,this.customHandles[mxEvent.CUSTOM_HANDLE-this.index].execute());else if(this.index==mxEvent.ROTATION_HANDLE)if(null!=this.currentAlpha){var d=this.currentAlpha-(this.state.style[mxConstants.STYLE_ROTATION]||
-0);0!=d&&this.rotateCell(this.state.cell,d)}else this.rotateClick();else{var e=this.graph.isGridEnabledEvent(b.getEvent()),f=mxUtils.toRadians(this.state.style[mxConstants.STYLE_ROTATION]||"0"),g=Math.cos(-f),k=Math.sin(-f),l=c.x-this.startX,m=c.y-this.startY,c=k*l+g*m,l=g*l-k*m,m=c,n=this.graph.view.scale,p=this.isRecursiveResize(this.state,b);this.resizeCell(this.state.cell,this.roundLength(l/n),this.roundLength(m/n),this.index,e,this.isConstrainedEvent(b),p)}}finally{this.graph.getModel().endUpdate()}b.consume();
-this.reset()}};mxVertexHandler.prototype.isRecursiveResize=function(a,b){return this.graph.isRecursiveResize(this.state)};mxVertexHandler.prototype.rotateClick=function(){};
-mxVertexHandler.prototype.rotateCell=function(a,b,c){if(0!=b){var d=this.graph.getModel();if(d.isVertex(a)||d.isEdge(a)){if(!d.isEdge(a)){var e=this.graph.view.getState(a),e=null!=e?e.style:this.graph.getCellStyle(a);null!=e&&this.graph.setCellStyles(mxConstants.STYLE_ROTATION,(e[mxConstants.STYLE_ROTATION]||0)+b,[a])}e=this.graph.getCellGeometry(a);if(null!=e){var f=this.graph.getCellGeometry(c);null==f||d.isEdge(c)||(e=e.clone(),e.rotate(b,new mxPoint(f.width/2,f.height/2)),d.setGeometry(a,e));
-if(d.isVertex(a)&&!e.relative||d.isEdge(a))for(c=d.getChildCount(a),e=0;ed&&(a+=c,e&&(a=this.graph.snap(a/f)*f));if(0==d||3==d||5==d)p+=b,e&&(p=this.graph.snap(p/f)*f);else if(2==d||4==d||7==d)q+=b,e&&(q=this.graph.snap(q/
-f)*f);e=q-p;c=r-a;k&&(k=this.graph.getCellGeometry(this.state.cell),null!=k&&(k=k.width/k.height,1==d||2==d||7==d||6==d?e=c*k:c=e/k,0==d&&(p=q-e,a=r-c)));l&&(e+=e-m,c+=c-n,p+=t-(p+e/2),a+=u-(a+c/2));0>e&&(p+=e,e=Math.abs(e));0>c&&(a+=c,c=Math.abs(c));d=new mxRectangle(p+g.x*f,a+g.y*f,e,c);null!=this.minBounds&&(d.width=Math.max(d.width,this.minBounds.x*f+this.minBounds.width*f+Math.max(0,this.x0*f-d.x)),d.height=Math.max(d.height,this.minBounds.y*f+this.minBounds.height*f+Math.max(0,this.y0*f-d.y)));
-return d};mxVertexHandler.prototype.redraw=function(){this.selectionBounds=this.getSelectionBounds(this.state);this.bounds=new mxRectangle(this.selectionBounds.x,this.selectionBounds.y,this.selectionBounds.width,this.selectionBounds.height);this.redrawHandles();this.drawPreview()};
-mxVertexHandler.prototype.getHandlePadding=function(){var a=new mxPoint(0,0),b=this.tolerance;null!=this.sizers&&0=mxGraphHandler.prototype.maxCells)this.bends=this.createBends(),this.isVirtualBendsEnabled()&&(this.virtualBends=this.createVirtualBends());this.label=new mxPoint(this.state.absoluteOffset.x,this.state.absoluteOffset.y);this.labelShape=this.createLabelHandleShape();this.initBend(this.labelShape);this.labelShape.setCursor(mxConstants.CURSOR_LABEL_HANDLE);this.customHandles=this.createCustomHandles();this.redraw()};mxEdgeHandler.prototype.createCustomHandles=function(){return null};
-mxEdgeHandler.prototype.isVirtualBendsEnabled=function(a){return this.virtualBendsEnabled&&(null==this.state.style[mxConstants.STYLE_EDGE]||this.state.style[mxConstants.STYLE_EDGE]==mxConstants.NONE||1==this.state.style[mxConstants.STYLE_NOEDGESTYLE])&&"arrow"!=mxUtils.getValue(this.state.style,mxConstants.STYLE_SHAPE,null)};mxEdgeHandler.prototype.isAddPointEvent=function(a){return mxEvent.isShiftDown(a)};mxEdgeHandler.prototype.isRemovePointEvent=function(a){return mxEvent.isShiftDown(a)};
-mxEdgeHandler.prototype.getSelectionPoints=function(a){return a.absolutePoints};mxEdgeHandler.prototype.createParentHighlightShape=function(a){a=new mxRectangleShape(a,null,this.getSelectionColor());a.strokewidth=this.getSelectionStrokeWidth();a.isDashed=this.isSelectionDashed();return a};mxEdgeHandler.prototype.createSelectionShape=function(a){a=new this.state.shape.constructor;a.outline=!0;a.apply(this.state);a.isDashed=this.isSelectionDashed();a.stroke=this.getSelectionColor();a.isShadow=!1;return a};
-mxEdgeHandler.prototype.getSelectionColor=function(){return mxConstants.EDGE_SELECTION_COLOR};mxEdgeHandler.prototype.getSelectionStrokeWidth=function(){return mxConstants.EDGE_SELECTION_STROKEWIDTH};mxEdgeHandler.prototype.isSelectionDashed=function(){return mxConstants.EDGE_SELECTION_DASHED};mxEdgeHandler.prototype.isConnectableCell=function(a){return!0};mxEdgeHandler.prototype.getCellAt=function(a,b){return this.outlineConnect?null:this.graph.getCellAt(a,b)};
-mxEdgeHandler.prototype.createMarker=function(){var a=new mxCellMarker(this.graph),b=this;a.getCell=function(a){var c=mxCellMarker.prototype.getCell.apply(this,arguments);c!=b.state.cell&&null!=c||null==b.currentPoint||(c=b.graph.getCellAt(b.currentPoint.x,b.currentPoint.y));if(null!=c&&!this.graph.isCellConnectable(c)){var e=this.graph.getModel().getParent(c);this.graph.getModel().isVertex(e)&&this.graph.isCellConnectable(e)&&(c=e)}e=b.graph.getModel();if(this.graph.isSwimlane(c)&&null!=b.currentPoint&&
-this.graph.hitsSwimlaneContent(c,b.currentPoint.x,b.currentPoint.y)||!b.isConnectableCell(c)||c==b.state.cell||null!=c&&!b.graph.connectableEdges&&e.isEdge(c)||e.isAncestor(b.state.cell,c))c=null;this.graph.isCellConnectable(c)||(c=null);return c};a.isValidState=function(a){var c=b.graph.getModel(),c=b.graph.view.getTerminalPort(a,b.graph.view.getState(c.getTerminal(b.state.cell,!b.isSource)),!b.isSource),c=null!=c?c.cell:null;b.error=b.validateConnection(b.isSource?a.cell:c,b.isSource?c:a.cell);
-return null==b.error};return a};mxEdgeHandler.prototype.validateConnection=function(a,b){return this.graph.getEdgeValidationError(this.state.cell,a,b)};
-mxEdgeHandler.prototype.createBends=function(){for(var a=this.state.cell,b=[],c=0;c
-mxEvent.VIRTUAL_HANDLE&&null!=this.customHandles)for(c=0;cmxEvent.VIRTUAL_HANDLE&&(c[this.index-1]=d)}return null!=e?e:c};
-mxEdgeHandler.prototype.isOutlineConnectEvent=function(a){var b=mxUtils.getOffset(this.graph.container),c=a.getEvent(),d=mxEvent.getClientX(c),c=mxEvent.getClientY(c),e=document.documentElement,f=this.currentPoint.x-this.graph.container.scrollLeft+b.x-((window.pageXOffset||e.scrollLeft)-(e.clientLeft||0)),b=this.currentPoint.y-this.graph.container.scrollTop+b.y-((window.pageYOffset||e.scrollTop)-(e.clientTop||0));return this.outlineConnect&&!mxEvent.isShiftDown(a.getEvent())&&(a.isSource(this.marker.highlight.shape)||
-mxEvent.isAltDown(a.getEvent())&&null!=a.getState()||this.marker.highlight.isHighlightAt(d,c)||(f!=d||b!=c)&&null==a.getState()&&this.marker.highlight.isHighlightAt(f,b))};
-mxEdgeHandler.prototype.updatePreviewState=function(a,b,c,d,e){var f=this.isSource?c:this.state.getVisibleTerminalState(!0),g=this.isTarget?c:this.state.getVisibleTerminalState(!1),k=this.graph.getConnectionConstraint(a,f,!0),l=this.graph.getConnectionConstraint(a,g,!1),m=this.constraintHandler.currentConstraint;null==m&&e&&(null!=c?(d.isSource(this.marker.highlight.shape)&&(b=new mxPoint(d.getGraphX(),d.getGraphY())),m=this.graph.getOutlineConstraint(b,c,d),this.constraintHandler.setFocus(d,c,this.isSource),
-this.constraintHandler.currentConstraint=m,this.constraintHandler.currentPoint=b):m=new mxConnectionConstraint);if(this.outlineConnect&&null!=this.marker.highlight&&null!=this.marker.highlight.shape){var n=this.graph.view.scale;null!=this.constraintHandler.currentConstraint&&null!=this.constraintHandler.currentFocus?(this.marker.highlight.shape.stroke=e?mxConstants.OUTLINE_HIGHLIGHT_COLOR:"transparent",this.marker.highlight.shape.strokewidth=mxConstants.OUTLINE_HIGHLIGHT_STROKEWIDTH/n/n,this.marker.highlight.repaint()):
-this.marker.hasValidState()&&(this.marker.highlight.shape.stroke=this.marker.getValidState()==d.getState()?mxConstants.DEFAULT_VALID_COLOR:"transparent",this.marker.highlight.shape.strokewidth=mxConstants.HIGHLIGHT_STROKEWIDTH/n/n,this.marker.highlight.repaint())}this.isSource?k=m:this.isTarget&&(l=m);if(this.isSource||this.isTarget)null!=m&&null!=m.point?(a.style[this.isSource?mxConstants.STYLE_EXIT_X:mxConstants.STYLE_ENTRY_X]=m.point.x,a.style[this.isSource?mxConstants.STYLE_EXIT_Y:mxConstants.STYLE_ENTRY_Y]=
-m.point.y):(delete a.style[this.isSource?mxConstants.STYLE_EXIT_X:mxConstants.STYLE_ENTRY_X],delete a.style[this.isSource?mxConstants.STYLE_EXIT_Y:mxConstants.STYLE_ENTRY_Y]);a.setVisibleTerminalState(f,!0);a.setVisibleTerminalState(g,!1);this.isSource&&null==f||a.view.updateFixedTerminalPoint(a,f,!0,k);this.isTarget&&null==g||a.view.updateFixedTerminalPoint(a,g,!1,l);(this.isSource||this.isTarget)&&null==c&&(a.setAbsoluteTerminalPoint(b,this.isSource),null==this.marker.getMarkedState()&&(this.error=
-this.graph.allowDanglingEdges?null:""));a.view.updatePoints(a,this.points,f,g);a.view.updateFloatingTerminalPoints(a,f,g)};
-mxEdgeHandler.prototype.mouseMove=function(a,b){if(null!=this.index&&null!=this.marker){this.currentPoint=this.getPointForEvent(b);this.error=null;!this.graph.isIgnoreTerminalEvent(b.getEvent())&&mxEvent.isShiftDown(b.getEvent())&&null!=this.snapPoint&&(Math.abs(this.snapPoint.x-this.currentPoint.x)mxEvent.VIRTUAL_HANDLE)null!=
-this.customHandles&&this.customHandles[mxEvent.CUSTOM_HANDLE-this.index].processEvent(b);else if(this.isLabel)this.label.x=this.currentPoint.x,this.label.y=this.currentPoint.y;else{this.points=this.getPreviewPoints(this.currentPoint,b);var c=this.isSource||this.isTarget?this.getPreviewTerminalState(b):null;if(null!=this.constraintHandler.currentConstraint&&null!=this.constraintHandler.currentFocus&&null!=this.constraintHandler.currentPoint)this.currentPoint=this.constraintHandler.currentPoint.clone();
-else if(this.outlineConnect){var d=this.isSource||this.isTarget?this.isOutlineConnectEvent(b):!1;d?c=this.marker.highlight.state:null!=c&&c!=b.getState()&&null!=this.marker.highlight.shape&&(this.marker.highlight.shape.stroke="transparent",this.marker.highlight.repaint(),c=null)}null!=c&&this.graph.isCellLocked(c.cell)&&(c=null,this.marker.reset());var e=this.clonePreviewState(this.currentPoint,null!=c?c.cell:null);this.updatePreviewState(e,this.currentPoint,c,b,d);this.setPreviewColor(null==this.error?
-this.marker.validColor:this.marker.invalidColor);this.abspoints=e.absolutePoints;this.active=!0}this.updateHint(b,this.currentPoint);this.drawPreview();mxEvent.consume(b.getEvent());b.consume()}else mxClient.IS_IE&&null!=this.getHandleForEvent(b)&&b.consume(!1)};
-mxEdgeHandler.prototype.mouseUp=function(a,b){if(null!=this.index&&null!=this.marker){var c=this.state.cell;if(b.getX()!=this.startX||b.getY()!=this.startY){var d=!this.graph.isIgnoreTerminalEvent(b.getEvent())&&this.graph.isCloneEvent(b.getEvent())&&this.cloneEnabled&&this.graph.isCellsCloneable();if(null!=this.error)0mxEvent.VIRTUAL_HANDLE){if(null!=this.customHandles){var e=this.graph.getModel();
-e.beginUpdate();try{this.customHandles[mxEvent.CUSTOM_HANDLE-this.index].execute()}finally{e.endUpdate()}}}else if(this.isLabel)this.moveLabel(this.state,this.label.x,this.label.y);else if(this.isSource||this.isTarget){var f=null;null!=this.constraintHandler.currentConstraint&&null!=this.constraintHandler.currentFocus&&(f=this.constraintHandler.currentFocus.cell);null==f&&this.marker.hasValidState()&&null!=this.marker.highlight&&null!=this.marker.highlight.shape&&"transparent"!=this.marker.highlight.shape.stroke&&
-"white"!=this.marker.highlight.shape.stroke&&(f=this.marker.validState.cell);if(null!=f){var e=this.graph.getModel(),g=e.getParent(c);e.beginUpdate();try{if(d){var k=e.getGeometry(c),d=this.graph.cloneCells([c])[0];e.add(g,d,e.getChildCount(g));null!=k&&(k=k.clone(),e.setGeometry(d,k));var l=e.getTerminal(c,!this.isSource);this.graph.connectCell(d,l,!this.isSource);c=d}c=this.connect(c,f,this.isSource,d,b)}finally{e.endUpdate()}}else this.graph.isAllowDanglingEdges()&&(e=this.abspoints[this.isSource?
-0:this.abspoints.length-1],e.x=this.roundLength(e.x/this.graph.view.scale-this.graph.view.translate.x),e.y=this.roundLength(e.y/this.graph.view.scale-this.graph.view.translate.y),f=this.graph.getView().getState(this.graph.getModel().getParent(c)),null!=f&&(e.x-=f.origin.x,e.y-=f.origin.y),e.x-=this.graph.panDx/this.graph.view.scale,e.y-=this.graph.panDy/this.graph.view.scale,c=this.changeTerminalPoint(c,e,this.isSource,d))}else this.active?c=this.changePoints(c,this.points,d):(this.graph.getView().invalidate(this.state.cell),
-this.graph.getView().validate(this.state.cell))}null!=this.marker&&(this.reset(),c!=this.state.cell&&this.graph.setSelectionCell(c));b.consume()}};
-mxEdgeHandler.prototype.reset=function(){this.active&&this.refresh();this.snapPoint=this.points=this.label=this.index=this.error=null;this.active=this.isTarget=this.isSource=this.isLabel=!1;if(this.livePreview&&null!=this.sizers)for(var a=0;a");this.div.style.visibility="";mxUtils.fit(this.div)}};
-mxTooltipHandler.prototype.destroy=function(){this.destroyed||(this.graph.removeMouseListener(this),mxEvent.release(this.div),null!=this.div&&null!=this.div.parentNode&&this.div.parentNode.removeChild(this.div),this.destroyed=!0,this.div=null)};function mxCellTracker(a,b,c){mxCellMarker.call(this,a,b);this.graph.addMouseListener(this);null!=c&&(this.getCell=c);mxClient.IS_IE&&mxEvent.addListener(window,"unload",mxUtils.bind(this,function(){this.destroy()}))}mxUtils.extend(mxCellTracker,mxCellMarker);
-mxCellTracker.prototype.mouseDown=function(a,b){};mxCellTracker.prototype.mouseMove=function(a,b){this.isEnabled()&&this.process(b)};mxCellTracker.prototype.mouseUp=function(a,b){};mxCellTracker.prototype.destroy=function(){this.destroyed||(this.destroyed=!0,this.graph.removeMouseListener(this),mxCellMarker.prototype.destroy.apply(this))};
-function mxCellHighlight(a,b,c,d){null!=a&&(this.graph=a,this.highlightColor=null!=b?b:mxConstants.DEFAULT_VALID_COLOR,this.strokeWidth=null!=c?c:mxConstants.HIGHLIGHT_STROKEWIDTH,this.dashed=null!=d?d:!1,this.opacity=mxConstants.HIGHLIGHT_OPACITY,this.repaintHandler=mxUtils.bind(this,function(){if(null!=this.state){var a=this.graph.view.getState(this.state.cell);null==a?this.hide():(this.state=a,this.repaint())}}),this.graph.getView().addListener(mxEvent.SCALE,this.repaintHandler),this.graph.getView().addListener(mxEvent.TRANSLATE,
-this.repaintHandler),this.graph.getView().addListener(mxEvent.SCALE_AND_TRANSLATE,this.repaintHandler),this.graph.getModel().addListener(mxEvent.CHANGE,this.repaintHandler),this.resetHandler=mxUtils.bind(this,function(){this.hide()}),this.graph.getView().addListener(mxEvent.DOWN,this.resetHandler),this.graph.getView().addListener(mxEvent.UP,this.resetHandler))}mxCellHighlight.prototype.keepOnTop=!1;mxCellHighlight.prototype.graph=!0;mxCellHighlight.prototype.state=null;
-mxCellHighlight.prototype.spacing=2;mxCellHighlight.prototype.resetHandler=null;mxCellHighlight.prototype.setHighlightColor=function(a){this.highlightColor=a;null!=this.shape&&(this.shape.stroke=a)};mxCellHighlight.prototype.drawHighlight=function(){this.shape=this.createShape();this.repaint();this.keepOnTop||this.shape.node.parentNode.firstChild==this.shape.node||this.shape.node.parentNode.insertBefore(this.shape.node,this.shape.node.parentNode.firstChild)};
-mxCellHighlight.prototype.createShape=function(){var a=this.graph.cellRenderer.createShape(this.state);a.svgStrokeTolerance=this.graph.tolerance;a.points=this.state.absolutePoints;a.apply(this.state);a.stroke=this.highlightColor;a.opacity=this.opacity;a.isDashed=this.dashed;a.isShadow=!1;a.dialect=this.graph.dialect!=mxConstants.DIALECT_SVG?mxConstants.DIALECT_VML:mxConstants.DIALECT_SVG;a.init(this.graph.getView().getOverlayPane());mxEvent.redirectMouseEvents(a.node,this.graph,this.state);this.graph.dialect!=
-mxConstants.DIALECT_SVG?a.pointerEvents=!1:a.svgPointerEvents="stroke";return a};mxCellHighlight.prototype.getStrokeWidth=function(a){return this.strokeWidth};
-mxCellHighlight.prototype.repaint=function(){if(null!=this.state&&null!=this.shape){this.shape.scale=this.state.view.scale;this.graph.model.isEdge(this.state.cell)?(this.shape.strokewidth=this.getStrokeWidth(),this.shape.points=this.state.absolutePoints,this.shape.outline=!1):(this.shape.bounds=new mxRectangle(this.state.x-this.spacing,this.state.y-this.spacing,this.state.width+2*this.spacing,this.state.height+2*this.spacing),this.shape.rotation=Number(this.state.style[mxConstants.STYLE_ROTATION]||
-"0"),this.shape.strokewidth=this.getStrokeWidth()/this.state.view.scale,this.shape.outline=!0);null!=this.state.shape&&this.shape.setCursor(this.state.shape.getCursor());if(mxClient.IS_QUIRKS||8==document.documentMode)"transparent"==this.shape.stroke?(this.shape.stroke="white",this.shape.opacity=1):this.shape.opacity=this.opacity;this.shape.redraw()}};mxCellHighlight.prototype.hide=function(){this.highlight(null)};
-mxCellHighlight.prototype.highlight=function(a){this.state!=a&&(null!=this.shape&&(this.shape.destroy(),this.shape=null),this.state=a,null!=this.state&&this.drawHighlight())};mxCellHighlight.prototype.isHighlightAt=function(a,b){var c=!1;if(null!=this.shape&&null!=document.elementFromPoint&&!mxClient.IS_QUIRKS)for(var d=document.elementFromPoint(a,b);null!=d;){if(d==this.shape.node){c=!0;break}d=d.parentNode}return c};
-mxCellHighlight.prototype.destroy=function(){this.graph.getView().removeListener(this.resetHandler);this.graph.getView().removeListener(this.repaintHandler);this.graph.getModel().removeListener(this.repaintHandler);null!=this.shape&&(this.shape.destroy(),this.shape=null)};
-function mxDefaultKeyHandler(a){if(null!=a){this.editor=a;this.handler=new mxKeyHandler(a.graph);var b=this.handler.escape;this.handler.escape=function(c){b.apply(this,arguments);a.hideProperties();a.fireEvent(new mxEventObject(mxEvent.ESCAPE,"event",c))}}}mxDefaultKeyHandler.prototype.editor=null;mxDefaultKeyHandler.prototype.handler=null;
-mxDefaultKeyHandler.prototype.bindAction=function(a,b,c){var d=mxUtils.bind(this,function(){this.editor.execute(b)});c?this.handler.bindControlKey(a,d):this.handler.bindKey(a,d)};mxDefaultKeyHandler.prototype.destroy=function(){this.handler.destroy();this.handler=null};function mxDefaultPopupMenu(a){this.config=a}mxDefaultPopupMenu.prototype.imageBasePath=null;mxDefaultPopupMenu.prototype.config=null;
-mxDefaultPopupMenu.prototype.createMenu=function(a,b,c,d){if(null!=this.config){var e=this.createConditions(a,c,d);this.addItems(a,b,c,d,e,this.config.firstChild,null)}};
-mxDefaultPopupMenu.prototype.addItems=function(a,b,c,d,e,f,g){for(var k=!1;null!=f;){if("add"==f.nodeName){var l=f.getAttribute("if");if(null==l||e[l]){var l=f.getAttribute("as"),l=mxResources.get(l)||l,m=mxUtils.eval(mxUtils.getTextContent(f)),n=f.getAttribute("action"),p=f.getAttribute("icon"),q=f.getAttribute("iconCls"),r=f.getAttribute("enabled-if"),r=null==r||e[r];k&&(b.addSeparator(g),k=!1);null!=p&&this.imageBasePath&&(p=this.imageBasePath+p);l=this.addAction(b,a,l,p,m,n,c,g,q,r);this.addItems(a,
-b,c,d,e,f.firstChild,l)}}else"separator"==f.nodeName&&(k=!0);f=f.nextSibling}};mxDefaultPopupMenu.prototype.addAction=function(a,b,c,d,e,f,g,k,l,m){return a.addItem(c,d,function(a){"function"==typeof e&&e.call(b,b,g,a);null!=f&&b.execute(f,g,a)},k,l,m)};
-mxDefaultPopupMenu.prototype.createConditions=function(a,b,c){var d=a.graph.getModel(),e=d.getChildCount(b),f=[];f.nocell=null==b;f.ncells=1 "+b.convertValueToString(c)+a),c=b.getModel().getParent(c);return this.getRootTitle()+a};mxEditor.prototype.getRootTitle=function(){var a=this.graph.getModel().getRoot();return this.graph.convertValueToString(a)};mxEditor.prototype.undo=function(){this.undoManager.undo()};mxEditor.prototype.redo=function(){this.undoManager.redo()};
-mxEditor.prototype.groupCells=function(){var a=null!=this.groupBorderSize?this.groupBorderSize:this.graph.gridSize;return this.graph.groupCells(this.createGroup(),a)};mxEditor.prototype.createGroup=function(){return this.graph.getModel().cloneCell(this.defaultGroup)};mxEditor.prototype.open=function(a){if(null!=a){var b=mxUtils.load(a).getXml();this.readGraphModel(b.documentElement);this.filename=a;this.fireEvent(new mxEventObject(mxEvent.OPEN,"filename",a))}};
-mxEditor.prototype.readGraphModel=function(a){(new mxCodec(a.ownerDocument)).decode(a,this.graph.getModel());this.resetHistory()};mxEditor.prototype.save=function(a,b){a=a||this.getUrlPost();if(null!=a&&0n&&(c-=c+k-n);n=l.y+l.height;d+m>n&&(d-=d+m-n)}}else null!=k&&(c-=k.x*f,d-=k.y*f)}}g=g.clone();g.x=this.graph.snap(c/f-this.graph.getView().translate.x-this.graph.gridSize/2);g.y=this.graph.snap(d/f-this.graph.getView().translate.y-this.graph.gridSize/2);b.setGeometry(g);null==a&&(a=this.graph.getDefaultParent());this.cycleAttribute(b);this.fireEvent(new mxEventObject(mxEvent.BEFORE_ADD_VERTEX,"vertex",b,"parent",a));e.beginUpdate();try{b=this.graph.addCell(b,
-a),null!=b&&(this.graph.constrainChild(b),this.fireEvent(new mxEventObject(mxEvent.ADD_VERTEX,"vertex",b)))}finally{e.endUpdate()}null!=b&&(this.graph.setSelectionCell(b),this.graph.scrollCellToVisible(b),this.fireEvent(new mxEventObject(mxEvent.AFTER_ADD_VERTEX,"vertex",b)));return b};
-mxEditor.prototype.destroy=function(){this.destroyed||(this.destroyed=!0,null!=this.tasks&&this.tasks.destroy(),null!=this.outline&&this.outline.destroy(),null!=this.properties&&this.properties.destroy(),null!=this.keyHandler&&this.keyHandler.destroy(),null!=this.rubberband&&this.rubberband.destroy(),null!=this.toolbar&&this.toolbar.destroy(),null!=this.graph&&this.graph.destroy(),this.templates=this.status=null)};
-var mxCodecRegistry={codecs:[],aliases:[],register:function(a){if(null!=a){var b=a.getName();mxCodecRegistry.codecs[b]=a;var c=mxUtils.getFunctionName(a.template.constructor);c!=b&&mxCodecRegistry.addAlias(c,b)}return a},addAlias:function(a,b){mxCodecRegistry.aliases[a]=b},getCodec:function(a){var b=null;if(null!=a){var b=mxUtils.getFunctionName(a),c=mxCodecRegistry.aliases[b];null!=c&&(b=c);b=mxCodecRegistry.codecs[b];if(null==b)try{b=new mxObjectCodec(new a),mxCodecRegistry.register(b)}catch(d){}}return b}};
-function mxCodec(a){this.document=a||mxUtils.createXmlDocument();this.objects=[]}mxCodec.prototype.document=null;mxCodec.prototype.objects=null;mxCodec.prototype.elements=null;mxCodec.prototype.encodeDefaults=!1;mxCodec.prototype.putObject=function(a,b){return this.objects[a]=b};mxCodec.prototype.getObject=function(a){var b=null;null!=a&&(b=this.objects[a],null==b&&(b=this.lookup(a),null==b&&(a=this.getElementById(a),null!=a&&(b=this.decode(a)))));return b};mxCodec.prototype.lookup=function(a){return null};
-mxCodec.prototype.getElementById=function(a){if(null==this.elements){if(null==this.document.documentElement)throw Error("mxCodec constructor needs document parameter");this.elements={};this.addElement(this.document.documentElement)}return this.elements[a]};mxCodec.prototype.addElement=function(a){if(a.nodeType==mxConstants.NODETYPE_ELEMENT){var b=a.getAttribute("id");null!=b&&null==this.elements[b]&&(this.elements[b]=a)}for(a=a.firstChild;null!=a;)this.addElement(a),a=a.nextSibling};
-mxCodec.prototype.getId=function(a){var b=null;null!=a&&(b=this.reference(a),null==b&&a instanceof mxCell&&(b=a.getId(),null==b&&(b=mxCellPath.create(a),0==b.length&&(b="root"))));return b};mxCodec.prototype.reference=function(a){return null};mxCodec.prototype.encode=function(a){var b=null;if(null!=a&&null!=a.constructor){var c=mxCodecRegistry.getCodec(a.constructor);null!=c?b=c.encode(this,a):mxUtils.isNode(a)?b=mxUtils.importNode(this.document,a,!0):mxLog.warn("mxCodec.encode: No codec for "+mxUtils.getFunctionName(a.constructor))}return b};
-mxCodec.prototype.decode=function(a,b){var c=null;if(null!=a&&a.nodeType==mxConstants.NODETYPE_ELEMENT){c=null;try{c=window[a.nodeName]}catch(d){}c=mxCodecRegistry.getCodec(c);null!=c?c=c.decode(this,a,b):(c=a.cloneNode(!0),c.removeAttribute("as"))}return c};mxCodec.prototype.encodeCell=function(a,b,c){b.appendChild(this.encode(a));if(null==c||c){c=a.getChildCount();for(var d=0;dNote that not all labs host every kind of machine.
-As you make your selections, labs and hosts that are not compatible
-with your current configuration will become unavailable.
-NOTE: Only PTL's are able to create multi-node PODs. See
- here
- for more details
-
-{% endblock content %}
diff --git a/src/templates/base/resource/steps/host_info.html b/src/templates/base/resource/steps/host_info.html
deleted file mode 100644
index 3230d8f..0000000
--- a/src/templates/base/resource/steps/host_info.html
+++ /dev/null
@@ -1,34 +0,0 @@
-{% extends "workflow/viewport-element.html" %}
-{% load staticfiles %}
-
-{% load bootstrap4 %}
-
-{% block content %}
-
-{% if error %}
-{{error}}
-{% else %}
-
-
-
-{% endif %}
-{% endblock content %}
diff --git a/src/templates/base/resource/steps/meta_info.html b/src/templates/base/resource/steps/meta_info.html
deleted file mode 100644
index 6fef065..0000000
--- a/src/templates/base/resource/steps/meta_info.html
+++ /dev/null
@@ -1,14 +0,0 @@
-{% extends "workflow/viewport-element.html" %}
-{% load staticfiles %}
-
-{% load bootstrap4 %}
-
-{% block content %}
-
-
-{% endblock content %}
diff --git a/src/templates/base/resource/steps/pod_definition.html b/src/templates/base/resource/steps/pod_definition.html
deleted file mode 100644
index 233d995..0000000
--- a/src/templates/base/resource/steps/pod_definition.html
+++ /dev/null
@@ -1,72 +0,0 @@
-{% extends "workflow/viewport-element.html" %}
-{% block extrahead %}
-Pod Definition Prototype
-
-
-
-{% endblock extrahead %}
-
-
-{% block content %}
-
-
-
-
-
-
-
Hold right click to drag
-
-
-
-
-
-
-
-
-
Add Network
-
-
Submit
-
-
-
-
-
-
-{% endblock content %}
-{% block onleave %}
-network_step.submitForm();
-{% endblock %}
diff --git a/src/templates/base/resource/uncommon.css b/src/templates/base/resource/uncommon.css
deleted file mode 100644
index 1ea9f35..0000000
--- a/src/templates/base/resource/uncommon.css
+++ /dev/null
@@ -1,162 +0,0 @@
-div.mxRubberband {
- position: absolute;
- overflow: hidden;
- border-style: solid;
- border-width: 1px;
- border-color: #0000FF;
- background: #0077FF;
-}
-.mxCellEditor {
- background: url(data:image/gif;base64,R0lGODlhMAAwAIAAAP///wAAACH5BAEAAAAALAAAAAAwADAAAAIxhI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8egpAAA7);
- _background: url('static/img/mxgraph/transparent.gif');
- border-color: transparent;
- border-style: solid;
- display: inline-block;
- position: absolute;
- overflow: visible;
- word-wrap: normal;
- border-width: 0;
- min-width: 1px;
- resize: none;
- padding: 0px;
- margin: 0px;
-}
-.mxPlainTextEditor * {
- padding: 0px;
- margin: 0px;
-}
-div.mxWindow {
- -webkit-box-shadow: 3px 3px 12px #C0C0C0;
- -moz-box-shadow: 3px 3px 12px #C0C0C0;
- box-shadow: 3px 3px 12px #C0C0C0;
- background: url('static/img/mxgraph/window.gif');
- border:1px solid #c3c3c3;
- position: absolute;
- overflow: hidden;
- z-index: 3;
-}
-table.mxWindow {
- border-collapse: collapse;
- table-layout: fixed;
- font-family: Arial;
- font-size: 8pt;
-}
-td.mxWindowTitle {
- background: url('static/img/mxgraph/window-title.gif') repeat-x;
- text-overflow: ellipsis;
- white-space: nowrap;
- text-align: center;
- font-weight: bold;
- overflow: hidden;
- height: 13px;
- padding: 2px;
- padding-top: 4px;
- padding-bottom: 6px;
- color: black;
-}
-td.mxWindowPane {
- vertical-align: top;
- padding: 0px;
-}
-div.mxWindowPane {
- overflow: hidden;
- position: relative;
-}
-td.mxWindowPane td {
- font-family: Arial;
- font-size: 8pt;
-}
-td.mxWindowPane input, td.mxWindowPane select, td.mxWindowPane textarea, td.mxWindowPane radio {
- border-color: #8C8C8C;
- border-style: solid;
- border-width: 1px;
- font-family: Arial;
- font-size: 8pt;
- padding: 1px;
-}
-td.mxWindowPane button {
- background: url('static/img/mxgraph/button.gif') repeat-x;
- font-family: Arial;
- font-size: 8pt;
- padding: 2px;
- float: left;
-}
-img.mxToolbarItem {
- margin-right: 6px;
- margin-bottom: 6px;
- border-width: 1px;
-}
-select.mxToolbarCombo {
- vertical-align: top;
- border-style: inset;
- border-width: 2px;
-}
-div.mxToolbarComboContainer {
- padding: 2px;
-}
-img.mxToolbarMode {
- margin: 2px;
- margin-right: 4px;
- margin-bottom: 4px;
- border-width: 0px;
-}
-img.mxToolbarModeSelected {
- margin: 0px;
- margin-right: 2px;
- margin-bottom: 2px;
- border-width: 2px;
- border-style: inset;
-}
-div.mxTooltip {
- -webkit-box-shadow: 3px 3px 12px #C0C0C0;
- -moz-box-shadow: 3px 3px 12px #C0C0C0;
- box-shadow: 3px 3px 12px #C0C0C0;
- background: #FFFFCC;
- border-style: solid;
- border-width: 1px;
- border-color: black;
- font-family: Arial;
- font-size: 8pt;
- position: absolute;
- cursor: default;
- padding: 4px;
- color: black;
-}
-div.mxPopupMenu {
- -webkit-box-shadow: 3px 3px 12px #C0C0C0;
- -moz-box-shadow: 3px 3px 12px #C0C0C0;
- box-shadow: 3px 3px 12px #C0C0C0;
- background: url('static/img/mxgraph/window.gif');
- position: absolute;
- border-style: solid;
- border-width: 1px;
- border-color: black;
-}
-table.mxPopupMenu {
- border-collapse: collapse;
- margin-top: 1px;
- margin-bottom: 1px;
-}
-tr.mxPopupMenuItem {
- color: black;
- cursor: pointer;
-}
-tr.mxPopupMenuItemHover {
- background-color: #000066;
- color: #FFFFFF;
- cursor: pointer;
-}
-td.mxPopupMenuItem {
- padding: 2px 30px 2px 10px;
- white-space: nowrap;
- font-family: Arial;
- font-size: 8pt;
-}
-td.mxPopupMenuIcon {
- background-color: #D0D0D0;
- padding: 2px 4px 2px 4px;
-}
-.mxDisabled {
- opacity: 0.2 !important;
- cursor:default !important;
-}
diff --git a/src/templates/base/rest_framework/api.html b/src/templates/base/rest_framework/api.html
deleted file mode 100644
index a62c8f5..0000000
--- a/src/templates/base/rest_framework/api.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% extends "rest_framework/base.html" %}
-
-{% block title %}Laas Dashboard API{% endblock %}
-
-{% block branding %}
-
- Laas Dashboard API
-
-{% endblock %}
\ No newline at end of file
diff --git a/src/templates/base/snapshot_workflow/steps/meta.html b/src/templates/base/snapshot_workflow/steps/meta.html
deleted file mode 100644
index 88136d2..0000000
--- a/src/templates/base/snapshot_workflow/steps/meta.html
+++ /dev/null
@@ -1,17 +0,0 @@
-{% extends "workflow/viewport-element.html" %}
-{% load staticfiles %}
-
-{% load bootstrap4 %}
-
-{% block content %}
-{% bootstrap_form_errors form type='non_fields' %}
-
-{% endblock content %}
diff --git a/src/templates/base/snapshot_workflow/steps/select_host.html b/src/templates/base/snapshot_workflow/steps/select_host.html
deleted file mode 100644
index 4243145..0000000
--- a/src/templates/base/snapshot_workflow/steps/select_host.html
+++ /dev/null
@@ -1,83 +0,0 @@
-{% extends "workflow/viewport-element.html" %}
-{% load staticfiles %}
-
-{% load bootstrap4 %}
-
-{% block content %}
-
-{% bootstrap_form_errors form type='non_fields' %}
-
-
-
-{% endblock content %}
diff --git a/src/templates/base/workflow/confirm.html b/src/templates/base/workflow/confirm.html
deleted file mode 100644
index bc8e4e3..0000000
--- a/src/templates/base/workflow/confirm.html
+++ /dev/null
@@ -1,56 +0,0 @@
-{% extends "workflow/viewport-element.html" %}
-{% load staticfiles %}
-
-{% load bootstrap4 %}
-
-{% block content %}
-
-
-
Confirm Session
-
-
-
-
-
{{confirmation_info|escape}}
-
-
-
-
-
-
-
- Confirm
- Cancel
-
-
-
-
-
-
-
-
-
-{% block element_messages %}
-
-{% endblock element_messages %}
-{% endblock content %}
diff --git a/src/templates/base/workflow/no_workflow.html b/src/templates/base/workflow/no_workflow.html
deleted file mode 100644
index 0ac6549..0000000
--- a/src/templates/base/workflow/no_workflow.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/src/templates/base/workflow/viewport-base.html b/src/templates/base/workflow/viewport-base.html
deleted file mode 100644
index 88229ca..0000000
--- a/src/templates/base/workflow/viewport-base.html
+++ /dev/null
@@ -1,82 +0,0 @@
-{% extends "base.html" %}
-{% load staticfiles %}
-
-{% load bootstrap4 %}
-
-{% block content %}
-
-
-
-
-
- Is something not working right? Let us know
here!
-
-
-
-
-
-{% csrf_token %}
-
-
-
-
-
-
-
-{% endblock content %}
diff --git a/src/templates/base/workflow/viewport-element.html b/src/templates/base/workflow/viewport-element.html
deleted file mode 100644
index db4da54..0000000
--- a/src/templates/base/workflow/viewport-element.html
+++ /dev/null
@@ -1,17 +0,0 @@
-{% load bootstrap4 %}
-{% load staticfiles %}
-
-{% block basecontent %}
-
- {% block content %}
- {% endblock content %}
-
-
- {% block element_messages %}
- {% bootstrap_messages %}
- {% endblock %}
-
-{% endblock basecontent %}
-
-{% block extrajs %}
-{% endblock extrajs %}
diff --git a/src/templates/laas/base.html b/src/templates/laas/base.html
deleted file mode 100644
index f980268..0000000
--- a/src/templates/laas/base.html
+++ /dev/null
@@ -1,89 +0,0 @@
-{% extends "base/base.html" %}
-{% load staticfiles %}
-{% block logo %}
-
-
-
-
-{% endblock logo %}
-
diff --git a/src/templates/laas/dashboard/landing.html b/src/templates/laas/dashboard/landing.html
deleted file mode 100644
index 12d8924..0000000
--- a/src/templates/laas/dashboard/landing.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% extends "base/dashboard/landing.html" %}
-
-{% block about_us %}
-The Lab as a Service (LaaS) project aims to help in the development and testing of LFN projects such as
- Anuket
- by hosting hardware and providing access to the community. Currently, the only participating lab is the
- University of New Hampshire Interoperability Lab (UNH-IOL).
-To get started, you can request access to a server at the right. PTL's have the ability to design and
- book a
- whole block of servers with customized layer2 networks (e.g. a Pharos Pod). Read more here:
- LaaS Wiki
-{% endblock %}
\ No newline at end of file
diff --git a/src/templates/laas/layout.html b/src/templates/laas/layout.html
deleted file mode 100644
index f9b1d99..0000000
--- a/src/templates/laas/layout.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% extends "base/layout.html" %}
-
-{% block head-title %}
-LaaS Dashboard
-{% endblock head-title %}
diff --git a/src/templates/lfedge/base.html b/src/templates/lfedge/base.html
deleted file mode 100644
index 4413340..0000000
--- a/src/templates/lfedge/base.html
+++ /dev/null
@@ -1,31 +0,0 @@
-{% extends "base/base.html" %}
-{% load staticfiles %}
-{% block bgColor %}
-
-
-
-{% endblock bgColor %}
-
-{% block logo %}
-
-{% endblock logo %}
-{% block dropDown %}
-{% endblock dropDown %}
-{% block userDropDownText %}
-
- {% if request.user.username %}
- {{request.user.username}}
- {% else %}
-
- {% endif %}
-
-
-{% endblock userDropDownText %}
diff --git a/src/templates/lfedge/booking/booking_table.html b/src/templates/lfedge/booking/booking_table.html
deleted file mode 100644
index 4020b5e..0000000
--- a/src/templates/lfedge/booking/booking_table.html
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
- Owner
- Purpose
- Project
- Start
- End
- Operating System
- Pod
-
-
-
-{% for booking in bookings %}
-
-
- {{ booking.owner.username }}
-
-
- {{ booking.purpose }}
-
-
- {{ booking.project }}
-
-
- {{ booking.start }}
-
-
- {{ booking.end }}
-
-
- {{ booking.resource.get_head_node.config.image.os.name }}
-
-
- {{ booking.resource.get_template_name }}
-
-
-{% endfor %}
-
diff --git a/src/templates/lfedge/booking/quick_deploy.html b/src/templates/lfedge/booking/quick_deploy.html
deleted file mode 100644
index ccafd90..0000000
--- a/src/templates/lfedge/booking/quick_deploy.html
+++ /dev/null
@@ -1,28 +0,0 @@
-{% extends "base/booking/quick_deploy.html" %}
-{% block opnfv %}
-{% endblock opnfv %}
-{% block form-text %}
-
- Please select a host type you wish to book.
- Only available types are shown.
- More information can be found here:
- LF Edge Wiki .
- If something isn't working right, let us know here!
-
-{% endblock form-text %}
-{% block collab %}
-
-
- Collaborators
- {{ form.users }}
-
-
-{% endblock collab %}
-
-{% block image_script %}
-
-{% endblock image_script %}
diff --git a/src/templates/lfedge/dashboard/landing.html b/src/templates/lfedge/dashboard/landing.html
deleted file mode 100644
index 9a776dc..0000000
--- a/src/templates/lfedge/dashboard/landing.html
+++ /dev/null
@@ -1,23 +0,0 @@
-{% extends "base/dashboard/landing.html" %}
-{% block about_us %}
- The Shared Community Lab at the IOL aims to help development and testing of LF Edge projects by hosting hardware and providing access to the community.
- To get started, you can request access to a pod at the right.
-{% endblock about_us %}
-
-{% block btnGrp %}
-
-To get started, book a pod below:
-Book a Pod
-{% endblock btnGrp %}
-
-{% block returningUsers %}
-{% endblock returningUsers %}
diff --git a/src/templates/lfedge/layout.html b/src/templates/lfedge/layout.html
deleted file mode 100644
index 217060c..0000000
--- a/src/templates/lfedge/layout.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% extends "base/layout.html" %}
-
-{% block head-title %}
-LF Edge Dashboard
-{% endblock head-title %}
diff --git a/src/workflow/README b/src/workflow/README
deleted file mode 100644
index fb4b949..0000000
--- a/src/workflow/README
+++ /dev/null
@@ -1,31 +0,0 @@
-This app creates "workflows", which are long and complex interactions from the user.
-Workflows are composed of multiple steps. At each step the user inputs some information.
-The content of one step may impact following steps.
-
-The WorkflowStep object is the abstract type for all the workflow steps.
-Important attributes and methods:
-
-template - the django template to use when rendering this step
-valid - the status code from WorkflowStepStatus
-
-get_context() - returns a dictionary that is used when rendering this step's template
- You should always call super's get_context and add / overwrite any data into that
- dictionary
-
-post(data, user) - this method is called when the step is POST'd to.
- data is from the request object, suitable for a Form's constructor
-
-
-Repository
-Each step has a reference to a shared repository (self.repo).
-The repo is a key-value store that allows the steps to share data
-
-Steps render based on the current state of the repo. For example, a step
-may get information about each host the user said they want and ask for additional
-input for each machine.
-Because the steps render based on what is in the repo, a user can easily go back to
-a previous step and change some data. This data will change in the repo and
-affect later steps accordingly.
-
-Everything stored in the repo is temporary. After a workflow has been completed, the repo
-is translated into Django models and saved to the database.
diff --git a/src/workflow/__init__.py b/src/workflow/__init__.py
deleted file mode 100644
index e0408fa..0000000
--- a/src/workflow/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
diff --git a/src/workflow/apps.py b/src/workflow/apps.py
deleted file mode 100644
index adc2738..0000000
--- a/src/workflow/apps.py
+++ /dev/null
@@ -1,15 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-
-from django.apps import AppConfig
-
-
-class WorkflowConfig(AppConfig):
- name = 'workflow'
diff --git a/src/workflow/booking_workflow.py b/src/workflow/booking_workflow.py
deleted file mode 100644
index ef89804..0000000
--- a/src/workflow/booking_workflow.py
+++ /dev/null
@@ -1,182 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others.
-# Copyright (c) 2020 Sawyer Bergeron, Sean Smith, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-from django.utils import timezone
-
-from datetime import timedelta
-
-from booking.models import Booking
-from workflow.models import WorkflowStep, AbstractSelectOrCreate
-from workflow.forms import ResourceSelectorForm, BookingMetaForm, OPNFVSelectForm
-from resource_inventory.models import OPNFVConfig, ResourceTemplate
-from django.db.models import Q
-
-
-"""
-subclassing notes:
- subclasses have to define the following class attributes:
- self.repo_key: main output of step, where the selected/created single selector
- result is placed at the end
- self.confirm_key:
-"""
-
-
-class Abstract_Resource_Select(AbstractSelectOrCreate):
- form = ResourceSelectorForm
- template = 'dashboard/genericselect.html'
- title = "Select Resource"
- description = "Select a resource template to use for your deployment"
- short_title = "pod select"
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.select_repo_key = self.repo.SELECTED_RESOURCE_TEMPLATE
- self.confirm_key = self.workflow_type
-
- def alert_bundle_missing(self):
- self.set_invalid("Please select a valid resource template")
-
- def get_form_queryset(self):
- user = self.repo_get(self.repo.SESSION_USER)
- return ResourceTemplate.objects.filter((Q(owner=user) | Q(public=True)))
-
- def get_page_context(self):
- return {
- 'select_type': 'resource',
- 'select_type_title': 'Resource template',
- 'addable_type_num': 1
- }
-
- def put_confirm_info(self, bundle):
- confirm_dict = self.repo_get(self.repo.CONFIRMATION)
- if self.confirm_key not in confirm_dict:
- confirm_dict[self.confirm_key] = {}
- confirm_dict[self.confirm_key]["Resource Template"] = bundle.name
- self.repo_put(self.repo.CONFIRMATION, confirm_dict)
-
-
-class Booking_Resource_Select(Abstract_Resource_Select):
- workflow_type = "booking"
-
-
-class OPNFV_EnablePicker(object):
- pass
-
-
-class OPNFV_Select(AbstractSelectOrCreate, OPNFV_EnablePicker):
- title = "Choose an OPNFV Config"
- description = "Choose or create a description of how you want to deploy OPNFV"
- short_title = "opnfv config"
- form = OPNFVSelectForm
- enabled = False
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.select_repo_key = self.repo.SELECTED_OPNFV_CONFIG
- self.confirm_key = "booking"
-
- def alert_bundle_missing(self):
- self.set_invalid("Please select a valid OPNFV config")
-
- def get_form_queryset(self):
- cb = self.repo_get(self.repo.SELECTED_CONFIG_BUNDLE)
- qs = OPNFVConfig.objects.filter(bundle=cb)
- return qs
-
- def put_confirm_info(self, config):
- confirm_dict = self.repo_get(self.repo.CONFIRMATION)
- if self.confirm_key not in confirm_dict:
- confirm_dict[self.confirm_key] = {}
- confirm_dict[self.confirm_key]["OPNFV Configuration"] = config.name
- self.repo_put(self.repo.CONFIRMATION, confirm_dict)
-
- def get_page_context(self):
- return {
- 'select_type': 'opnfv',
- 'select_type_title': 'OPNFV Config',
- 'addable_type_num': 4
- }
-
-
-class Booking_Meta(WorkflowStep):
- template = 'booking/steps/booking_meta.html'
- title = "Extra Info"
- description = "Tell us how long you want your booking, what it is for, and who else should have access to it"
- short_title = "booking info"
-
- def get_context(self):
- context = super(Booking_Meta, self).get_context()
- initial = {}
- default = []
- try:
- models = self.repo_get(self.repo.BOOKING_MODELS, {})
- booking = models.get("booking")
- if booking:
- initial['purpose'] = booking.purpose
- initial['project'] = booking.project
- initial['length'] = (booking.end - booking.start).days
- info = self.repo_get(self.repo.BOOKING_INFO_FILE, False)
- if info:
- initial['info_file'] = info
- users = models.get("collaborators", [])
- for user in users:
- default.append(user.userprofile)
- except Exception:
- pass
-
- owner = self.repo_get(self.repo.SESSION_USER)
-
- context['form'] = BookingMetaForm(initial=initial, user_initial=default, owner=owner)
- return context
-
- def post(self, post_data, user):
- form = BookingMetaForm(data=post_data, owner=user)
-
- forms = self.repo_get(self.repo.BOOKING_FORMS, {})
-
- forms["meta_form"] = form
- self.repo_put(self.repo.BOOKING_FORMS, forms)
-
- if form.is_valid():
- models = self.repo_get(self.repo.BOOKING_MODELS, {})
- if "booking" not in models:
- models['booking'] = Booking()
- models['collaborators'] = []
- confirm = self.repo_get(self.repo.CONFIRMATION)
- if "booking" not in confirm:
- confirm['booking'] = {}
-
- models['booking'].start = timezone.now()
- models['booking'].end = timezone.now() + timedelta(days=int(form.cleaned_data['length']))
- models['booking'].purpose = form.cleaned_data['purpose']
- models['booking'].project = form.cleaned_data['project']
- for key in ['length', 'project', 'purpose']:
- confirm['booking'][key] = form.cleaned_data[key]
-
- if form.cleaned_data["deploy_opnfv"]:
- self.repo_get(self.repo.SESSION_MANAGER).set_step_statuses(OPNFV_EnablePicker, desired_enabled=True)
- else:
- self.repo_get(self.repo.SESSION_MANAGER).set_step_statuses(OPNFV_EnablePicker, desired_enabled=False)
-
- userprofile_list = form.cleaned_data['users']
- confirm['booking']['collaborators'] = []
- for userprofile in userprofile_list:
- models['collaborators'].append(userprofile.user)
- confirm['booking']['collaborators'].append(userprofile.user.username)
-
- info_file = form.cleaned_data.get("info_file", False)
- if info_file:
- self.repo_put(self.repo.BOOKING_INFO_FILE, info_file)
-
- self.repo_put(self.repo.BOOKING_MODELS, models)
- self.repo_put(self.repo.CONFIRMATION, confirm)
- self.set_valid("Step Completed")
- else:
- self.set_invalid("Please complete the fields highlighted in red to continue")
diff --git a/src/workflow/forms.py b/src/workflow/forms.py
deleted file mode 100644
index 62abad6..0000000
--- a/src/workflow/forms.py
+++ /dev/null
@@ -1,489 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others.
-# Copyright (c) 2020 Sawyer Bergeron, Sean Smith, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-
-import django.forms as forms
-from django.forms import widgets, ValidationError
-from django.utils.safestring import mark_safe
-from django.template.loader import render_to_string
-from django.forms.widgets import NumberInput
-
-import json
-import urllib
-
-from account.models import Lab
-from account.models import UserProfile
-from resource_inventory.models import (
- OPNFVRole,
- Installer,
- Scenario
-)
-from resource_inventory.resource_manager import ResourceManager
-from booking.lib import get_user_items, get_user_field_opts
-
-
-class SearchableSelectMultipleWidget(widgets.SelectMultiple):
- template_name = 'dashboard/searchable_select_multiple.html'
-
- def __init__(self, attrs=None):
- self.items = attrs['items']
- self.show_from_noentry = attrs['show_from_noentry']
- self.show_x_results = attrs['show_x_results']
- self.results_scrollable = attrs['results_scrollable']
- self.selectable_limit = attrs['selectable_limit']
- self.placeholder = attrs['placeholder']
- self.name = attrs['name']
- self.initial = attrs.get("initial", [])
-
- super(SearchableSelectMultipleWidget, self).__init__()
-
- def render(self, name, value, attrs=None, renderer=None):
-
- context = self.get_context(attrs)
- return mark_safe(render_to_string(self.template_name, context))
-
- def get_context(self, attrs):
- return {
- 'items': self.items,
- 'name': self.name,
- 'show_from_noentry': self.show_from_noentry,
- 'show_x_results': self.show_x_results,
- 'results_scrollable': self.results_scrollable,
- 'selectable_limit': self.selectable_limit,
- 'placeholder': self.placeholder,
- 'initial': self.initial,
- }
-
-
-class SearchableSelectMultipleField(forms.Field):
- def __init__(self, *args, required=True, widget=None, label=None, disabled=False,
- items=None, queryset=None, show_from_noentry=True, show_x_results=-1,
- results_scrollable=False, selectable_limit=-1, placeholder="search here",
- name="searchable_select", initial=[], **kwargs):
- """
- From the documentation.
-
- # required -- Boolean that specifies whether the field is required.
- # True by default.
- # widget -- A Widget class, or instance of a Widget class, that should
- # be used for this Field when displaying it. Each Field has a
- # default Widget that it'll use if you don't specify this. In
- # most cases, the default widget is TextInput.
- # label -- A verbose name for this field, for use in displaying this
- # field in a form. By default, Django will use a "pretty"
- # version of the form field name, if the Field is part of a
- # Form.
- # initial -- A value to use in this Field's initial display. This value
- # is *not* used as a fallback if data isn't given.
- # help_text -- An optional string to use as "help text" for this Field.
- # error_messages -- An optional dictionary to override the default
- # messages that the field will raise.
- # show_hidden_initial -- Boolean that specifies if it is needed to render a
- # hidden widget with initial value after widget.
- # validators -- List of additional validators to use
- # localize -- Boolean that specifies if the field should be localized.
- # disabled -- Boolean that specifies whether the field is disabled, that
- # is its widget is shown in the form but not editable.
- # label_suffix -- Suffix to be added to the label. Overrides
- # form's label_suffix.
- """
- self.widget = widget
- if self.widget is None:
- self.widget = SearchableSelectMultipleWidget(
- attrs={
- 'items': items,
- 'initial': [obj.id for obj in initial],
- 'show_from_noentry': show_from_noentry,
- 'show_x_results': show_x_results,
- 'results_scrollable': results_scrollable,
- 'selectable_limit': selectable_limit,
- 'placeholder': placeholder,
- 'name': name,
- 'disabled': disabled
- }
- )
- self.disabled = disabled
- self.queryset = queryset
- self.selectable_limit = selectable_limit
-
- super().__init__(disabled=disabled, **kwargs)
-
- self.required = required
-
- def clean(self, data):
- data = data[0]
- if not data:
- if self.required:
- raise ValidationError("Nothing was selected")
- else:
- return []
- try:
- data_as_list = json.loads(data)
- except json.decoder.JSONDecodeError:
- data_as_list = None
- if not data_as_list:
- raise ValidationError("Contents Not JSON")
- if self.selectable_limit != -1:
- if len(data_as_list) > self.selectable_limit:
- raise ValidationError("Too many items were selected")
-
- items = []
- for elem in data_as_list:
- items.append(self.queryset.get(id=elem))
-
- return items
-
-
-class SearchableSelectAbstractForm(forms.Form):
- def __init__(self, *args, queryset=None, initial=[], **kwargs):
- self.queryset = queryset
- items = self.generate_items(self.queryset)
- options = self.generate_options()
-
- super(SearchableSelectAbstractForm, self).__init__(*args, **kwargs)
- self.fields['searchable_select'] = SearchableSelectMultipleField(
- initial=initial,
- items=items,
- queryset=self.queryset,
- **options
- )
-
- def get_validated_bundle(self):
- bundles = self.cleaned_data['searchable_select']
- if len(bundles) < 1: # don't need to check for >1, as field does that for us
- raise ValidationError("No bundle was selected")
- return bundles[0]
-
- def generate_items(self, queryset):
- raise Exception("SearchableSelectAbstractForm does not implement concrete generate_items()")
-
- def generate_options(self, disabled=False):
- return {
- 'show_from_noentry': True,
- 'show_x_results': -1,
- 'results_scrollable': True,
- 'selectable_limit': 1,
- 'placeholder': 'Search for a Bundle',
- 'name': 'searchable_select',
- 'disabled': False
- }
-
-
-class SWConfigSelectorForm(SearchableSelectAbstractForm):
- def generate_items(self, queryset):
- items = {}
-
- for bundle in queryset:
- items[bundle.id] = {
- 'expanded_name': bundle.name,
- 'small_name': bundle.owner.username,
- 'string': bundle.description,
- 'id': bundle.id
- }
-
- return items
-
-
-class OPNFVSelectForm(SearchableSelectAbstractForm):
- def generate_items(self, queryset):
- items = {}
-
- for config in queryset:
- items[config.id] = {
- 'expanded_name': config.name,
- 'small_name': config.bundle.owner.username,
- 'string': config.description,
- 'id': config.id
- }
-
- return items
-
-
-class ResourceSelectorForm(SearchableSelectAbstractForm):
- def generate_items(self, queryset):
- items = {}
-
- for bundle in queryset:
- items[bundle.id] = {
- 'expanded_name': bundle.name,
- 'small_name': bundle.owner.username,
- 'string': bundle.description,
- 'id': bundle.id
- }
-
- return items
-
-
-class BookingMetaForm(forms.Form):
- # Django Form class for Book a Pod
- length = forms.IntegerField(
- widget=NumberInput(
- attrs={
- "type": "range",
- 'min': "1",
- "max": "21",
- "value": "1"
- }
- )
- )
- purpose = forms.CharField(max_length=1000)
- project = forms.CharField(max_length=400)
- info_file = forms.CharField(max_length=1000, required=False)
- deploy_opnfv = forms.BooleanField(required=False)
-
- def __init__(self, *args, user_initial=[], owner=None, **kwargs):
- super(BookingMetaForm, self).__init__(**kwargs)
-
- self.fields['users'] = SearchableSelectMultipleField(
- queryset=UserProfile.objects.select_related('user').exclude(user=owner),
- initial=user_initial,
- items=get_user_items(exclude=owner),
- required=False,
- **get_user_field_opts()
- )
-
-
-class MultipleSelectFilterWidget(forms.Widget):
- def __init__(self, *args, display_objects=None, filter_items=None, neighbors=None, **kwargs):
- super(MultipleSelectFilterWidget, self).__init__(*args, **kwargs)
- self.display_objects = display_objects
- self.filter_items = filter_items
- self.neighbors = neighbors
- self.template_name = "dashboard/multiple_select_filter_widget.html"
-
- def render(self, name, value, attrs=None, renderer=None):
- context = self.get_context(name, value, attrs)
- html = render_to_string(self.template_name, context=context)
- return mark_safe(html)
-
- def get_context(self, name, value, attrs):
- return {
- 'display_objects': self.display_objects,
- 'neighbors': self.neighbors,
- 'filter_items': self.filter_items,
- 'initial_value': value
- }
-
-
-class MultipleSelectFilterField(forms.Field):
-
- def __init__(self, **kwargs):
- self.initial = kwargs.get("initial")
- super().__init__(**kwargs)
-
- def to_python(self, value):
- try:
- return json.loads(value)
- except json.decoder.JSONDecodeError:
- pass
- raise ValidationError("content is not valid JSON")
-
-
-class FormUtils:
- @staticmethod
- def getLabData(multiple_hosts=False, user=None):
- """
- Get all labs and thier host profiles, returns a serialized version the form can understand.
-
- Could be rewritten with a related query to make it faster
- """
- # javascript truthy variables
- true = 1
- false = 0
- if multiple_hosts:
- multiple_hosts = true
- else:
- multiple_hosts = false
- labs = {}
- resources = {}
- items = {}
- neighbors = {}
- for lab in Lab.objects.all():
- lab_node = {
- 'id': "lab_" + str(lab.lab_user.id),
- 'model_id': lab.lab_user.id,
- 'name': lab.name,
- 'description': lab.description,
- 'selected': false,
- 'selectable': true,
- 'follow': multiple_hosts,
- 'multiple': false,
- 'class': 'lab',
- 'available_resources': json.dumps(lab.get_available_resources())
- }
-
- items[lab_node['id']] = lab_node
- neighbors[lab_node['id']] = []
- labs[lab_node['id']] = lab_node
-
- for template in ResourceManager.getInstance().getAvailableResourceTemplates(lab, user):
- resource_node = {
- 'form': {"name": "host_name", "type": "text", "placeholder": "hostname"},
- 'id': "resource_" + str(template.id),
- 'model_id': template.id,
- 'name': template.name,
- 'description': template.description,
- 'selected': false,
- 'selectable': true,
- 'follow': false,
- 'multiple': multiple_hosts,
- 'class': 'resource',
- 'required_resources': json.dumps(template.get_required_resources())
- }
-
- if multiple_hosts:
- resource_node['values'] = [] # place to store multiple values
-
- items[resource_node['id']] = resource_node
- neighbors[lab_node['id']].append(resource_node['id'])
-
- if resource_node['id'] not in neighbors:
- neighbors[resource_node['id']] = []
-
- neighbors[resource_node['id']].append(lab_node['id'])
- resources[resource_node['id']] = resource_node
-
- display_objects = [("lab", labs.values()), ("resource", resources.values())]
-
- context = {
- 'display_objects': display_objects,
- 'neighbors': neighbors,
- 'filter_items': items
- }
-
- return context
-
-
-class HardwareDefinitionForm(forms.Form):
-
- def __init__(self, user, *args, **kwargs):
- super(HardwareDefinitionForm, self).__init__(*args, **kwargs)
- attrs = FormUtils.getLabData(multiple_hosts=True, user=user)
- self.fields['filter_field'] = MultipleSelectFilterField(
- widget=MultipleSelectFilterWidget(**attrs)
- )
-
-
-class PodDefinitionForm(forms.Form):
-
- fields = ["xml"]
- xml = forms.CharField()
-
-
-class ResourceMetaForm(forms.Form):
-
- bundle_name = forms.CharField(label="POD Name")
- bundle_description = forms.CharField(label="POD Description", widget=forms.Textarea, max_length=1000)
-
-
-class GenericHostMetaForm(forms.Form):
-
- host_profile = forms.CharField(label="Host Type", disabled=True, required=False)
- host_name = forms.CharField(label="Host Name")
-
-
-class NetworkDefinitionForm(forms.Form):
- def __init__(self, *args, **kwargs):
- super(NetworkDefinitionForm, self).__init__(**kwargs)
-
-
-class NetworkConfigurationForm(forms.Form):
- def __init__(self, *args, **kwargs):
- super(NetworkConfigurationForm).__init__(**kwargs)
-
-
-class HostSoftwareDefinitionForm(forms.Form):
- # Django Form class for Design a Pod
- host_name = forms.CharField(
- max_length=200,
- disabled=False,
- required=True
- )
- headnode = forms.BooleanField(required=False, widget=forms.HiddenInput)
-
- def __init__(self, *args, **kwargs):
- imageQS = kwargs.pop("imageQS")
- super(HostSoftwareDefinitionForm, self).__init__(*args, **kwargs)
- self.fields['image'] = forms.ModelChoiceField(queryset=imageQS)
-
-
-class WorkflowSelectionForm(forms.Form):
- fields = ['workflow']
-
- empty_permitted = False
-
- workflow = forms.ChoiceField(
- choices=(
- (0, 'Booking'),
- (1, 'Resource Bundle'),
- (2, 'Software Configuration')
- ),
- label="Choose Workflow",
- initial='booking',
- required=True
- )
-
-
-class SnapshotHostSelectForm(forms.Form):
- host = forms.CharField()
-
-
-class BasicMetaForm(forms.Form):
- name = forms.CharField()
- description = forms.CharField(widget=forms.Textarea)
-
-
-class ConfirmationForm(forms.Form):
- fields = ['confirm']
-
- confirm = forms.ChoiceField(
- choices=(
- (False, "Cancel"),
- (True, "Confirm")
- )
- )
-
-
-def validate_step(value):
- if value not in ["prev", "next", "current"]:
- raise ValidationError(str(value) + " is not allowed")
-
-
-def validate_step_form(value):
- try:
- urllib.parse.unquote_plus(value)
- except Exception:
- raise ValidationError("Value is not url encoded data")
-
-
-class ManagerForm(forms.Form):
- step = forms.CharField(widget=forms.widgets.HiddenInput, validators=[validate_step])
- step_form = forms.CharField(widget=forms.widgets.HiddenInput, validators=[validate_step_form])
- # other fields?
-
-
-class OPNFVSelectionForm(forms.Form):
- installer = forms.ModelChoiceField(queryset=Installer.objects.all(), required=True)
- scenario = forms.ModelChoiceField(queryset=Scenario.objects.all(), required=True)
-
-
-class OPNFVNetworkRoleForm(forms.Form):
- role = forms.CharField(max_length=200, disabled=True, required=False)
-
- def __init__(self, *args, config_bundle, **kwargs):
- super(OPNFVNetworkRoleForm, self).__init__(*args, **kwargs)
- self.fields['network'] = forms.ModelChoiceField(
- queryset=config_bundle.bundle.networks.all()
- )
-
-
-class OPNFVHostRoleForm(forms.Form):
- host_name = forms.CharField(max_length=200, disabled=True, required=False)
- role = forms.ModelChoiceField(queryset=OPNFVRole.objects.all().order_by("name").distinct("name"))
diff --git a/src/workflow/models.py b/src/workflow/models.py
deleted file mode 100644
index e065202..0000000
--- a/src/workflow/models.py
+++ /dev/null
@@ -1,693 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-
-from django.template.loader import get_template
-from django.http import HttpResponse
-from django.utils import timezone
-from django.db import transaction
-
-import yaml
-import requests
-
-from workflow.forms import ConfirmationForm
-from api.models import JobFactory
-from dashboard.exceptions import ResourceAvailabilityException, ModelValidationException
-from resource_inventory.models import Image, OPNFVConfig, ResourceOPNFVConfig, NetworkRole
-from resource_inventory.resource_manager import ResourceManager
-from resource_inventory.pdf_templater import PDFTemplater
-from notifier.manager import NotificationHandler
-from booking.models import Booking
-
-
-class BookingAuthManager():
- """
- Verifies Booking Authorization.
-
- Class to verify that the user is allowed to book the requested resource
- The user must input a url to the INFO.yaml file to prove that they are the ptl of
- an approved project if they are booking a multi-node pod.
- This class parses the url and checks the logged in user against the info file.
- """
-
- LFN_PROJECTS = ["opnfv"] # TODO
-
- def parse_github_url(self, url):
- project_leads = []
- try:
- parts = url.split("/")
- if "http" in parts[0]: # the url include http(s)://
- parts = parts[2:]
- if parts[-1] != "INFO.yaml":
- return None
- if parts[0] not in ["github.com", "raw.githubusercontent.com"]:
- return None
- if parts[1] not in self.LFN_PROJECTS:
- return None
- # now to download and parse file
- if parts[3] == "blob":
- parts[3] = "raw"
- url = "https://" + "/".join(parts)
- info_file = requests.get(url, timeout=15).text
- info_parsed = yaml.load(info_file)
- ptl = info_parsed.get('project_lead')
- if ptl:
- project_leads.append(ptl)
- sub_ptl = info_parsed.get("subproject_lead")
- if sub_ptl:
- project_leads.append(sub_ptl)
-
- except Exception:
- pass
-
- return project_leads
-
- def parse_gerrit_url(self, url):
- project_leads = []
- try:
- halfs = url.split("?")
- parts = halfs[0].split("/")
- args = halfs[1].split(";")
- if "http" in parts[0]: # the url include http(s)://
- parts = parts[2:]
- if "f=INFO.yaml" not in args:
- return None
- if "gerrit.opnfv.org" not in parts[0]:
- return None
- try:
- i = args.index("a=blob")
- args[i] = "a=blob_plain"
- except ValueError:
- pass
- # recreate url
- halfs[1] = ";".join(args)
- halfs[0] = "/".join(parts)
- # now to download and parse file
- url = "https://" + "?".join(halfs)
- info_file = requests.get(url, timeout=15).text
- info_parsed = yaml.load(info_file)
- ptl = info_parsed.get('project_lead')
- if ptl:
- project_leads.append(ptl)
- sub_ptl = info_parsed.get("subproject_lead")
- if sub_ptl:
- project_leads.append(sub_ptl)
-
- except Exception:
- return None
-
- return project_leads
-
- def parse_opnfv_git_url(self, url):
- project_leads = []
- try:
- parts = url.split("/")
- if "http" in parts[0]: # the url include http(s)://
- parts = parts[2:]
- if "INFO.yaml" not in parts[-1]:
- return None
- if "git.opnfv.org" not in parts[0]:
- return None
- if parts[-2] == "tree":
- parts[-2] = "plain"
- # now to download and parse file
- url = "https://" + "/".join(parts)
- info_file = requests.get(url, timeout=15).text
- info_parsed = yaml.load(info_file)
- ptl = info_parsed.get('project_lead')
- if ptl:
- project_leads.append(ptl)
- sub_ptl = info_parsed.get("subproject_lead")
- if sub_ptl:
- project_leads.append(sub_ptl)
-
- except Exception:
- return None
-
- return project_leads
-
- def parse_url(self, info_url):
- """
- Parse the project URL.
-
- Gets the INFO.yaml file from the project and returns the PTL info.
- """
- if "github" in info_url:
- return self.parse_github_url(info_url)
-
- if "gerrit.opnfv.org" in info_url:
- return self.parse_gerrit_url(info_url)
-
- if "git.opnfv.org" in info_url:
- return self.parse_opnfv_git_url(info_url)
-
- def booking_allowed(self, booking, repo):
- """
- Assert the current Booking Policy.
-
- This is the method that will have to change whenever the booking policy changes in the Infra
- group / LFN. This is a nice isolation of that administration crap
- currently checks if the booking uses multiple servers. if it does, then the owner must be a PTL,
- which is checked using the provided info file
- """
- if booking.owner.userprofile.booking_privledge:
- return True # admin override for this user
- if Booking.objects.filter(owner=booking.owner, end__gt=timezone.now()).count() >= 3:
- return False
- if len(booking.resource.template.get_required_resources()) < 2:
- return True # if they only have one server, we dont care
- if repo.BOOKING_INFO_FILE not in repo.el:
- return False # INFO file not provided
- ptl_info = self.parse_url(repo.el.get(repo.BOOKING_INFO_FILE))
- for ptl in ptl_info:
- if ptl['email'] == booking.owner.userprofile.email_addr:
- return True
- return False
-
-
-class WorkflowStepStatus(object):
- """
- Poor man's enum for the status of a workflow step.
-
- The steps in a workflow are not completed (UNTOUCHED)
- or they have been completed correctly (VALID) or they were filled out
- incorrectly (INVALID)
- """
-
- UNTOUCHED = 0
- INVALID = 100
- VALID = 200
-
-
-class WorkflowStep(object):
- template = 'bad_request.html'
- title = "Generic Step"
- description = "You were led here by mistake"
- short_title = "error"
- metastep = None
- # phasing out metastep:
-
- valid = WorkflowStepStatus.UNTOUCHED
- message = ""
-
- enabled = True
-
- def cleanup(self):
- raise Exception("WorkflowStep subclass of type " + str(type(self)) + " has no concrete implemented cleanup() method")
-
- def enable(self):
- if not self.enabled:
- self.enabled = True
-
- def disable(self):
- if self.enabled:
- self.cleanup()
- self.enabled = False
-
- def set_invalid(self, message, code=WorkflowStepStatus.INVALID):
- self.valid = code
- self.message = message
-
- def set_valid(self, message, code=WorkflowStepStatus.VALID):
- self.valid = code
- self.message = message
-
- def to_json(self):
- return {
- 'title': self.short_title,
- 'enabled': self.enabled,
- 'valid': self.valid,
- 'message': self.message,
- }
-
- def __init__(self, id, repo=None):
- self.repo = repo
- self.id = id
-
- def get_context(self):
- context = {}
- context['step_number'] = self.repo_get('steps')
- context['active_step'] = self.repo_get('active_step')
- context['render_correct'] = "true"
- context['step_title'] = self.title
- context['description'] = self.description
- return context
-
- def render(self, request):
- return HttpResponse(self.render_to_string(request))
-
- def render_to_string(self, request):
- template = get_template(self.template)
- return template.render(self.get_context(), request)
-
- def post(self, post_content, user):
- raise Exception("WorkflowStep subclass of type " + str(type(self)) + " has no concrete post() method")
-
- def validate(self, request):
- pass
-
- def repo_get(self, key, default=None):
- return self.repo.get(key, default, self.id)
-
- def repo_put(self, key, value):
- return self.repo.put(key, value, self.id)
-
-
-"""
-subclassing notes:
- subclasses have to define the following class attributes:
- self.select_repo_key: where the selected "object" or "bundle" is to be placed in the repo
- self.form: the form to be used
- alert_bundle_missing(): what message to display if a user does not select/selects an invalid object
- get_form_queryset(): generate a queryset to be used to filter available items for the field
- get_page_context(): return simple context such as page header and other info
-"""
-
-
-class AbstractSelectOrCreate(WorkflowStep):
- template = 'dashboard/genericselect.html'
- title = "Select a Bundle"
- short_title = "select"
- description = "Generic bundle selector step"
-
- select_repo_key = None
- form = None # subclasses are expected to use a form that is a subclass of SearchableSelectGenericForm
-
- def alert_bundle_missing(self): # override in subclasses to change message if field isn't filled out
- self.set_invalid("Please select a valid bundle")
-
- def post(self, post_data, user):
- form = self.form(post_data, queryset=self.get_form_queryset())
- if form.is_valid():
- bundle = form.get_validated_bundle()
- if not bundle:
- self.alert_bundle_missing()
- return
- self.repo_put(self.select_repo_key, bundle)
- self.put_confirm_info(bundle)
- self.set_valid("Step Completed")
- else:
- self.alert_bundle_missing()
-
- def get_context(self):
- default = []
-
- bundle = self.repo_get(self.select_repo_key, False)
- if bundle:
- default.append(bundle)
-
- form = self.form(queryset=self.get_form_queryset(), initial=default)
-
- context = {'form': form, **self.get_page_context()}
- context.update(super().get_context())
-
- return context
-
- def get_page_context():
- return {
- 'select_type': 'generic',
- 'select_type_title': 'Generic Bundle'
- }
-
-
-class Confirmation_Step(WorkflowStep):
- template = 'workflow/confirm.html'
- title = "Confirm Changes"
- description = "Does this all look right?"
-
- short_title = "confirm"
-
- def get_context(self):
- context = super(Confirmation_Step, self).get_context()
- context['form'] = ConfirmationForm()
- # Summary of submitted form data shown on the 'confirm' step of the workflow
- confirm_details = "\nPod:\n Name: '{name}'\n Description: '{desc}'\nLab: '{lab}'".format(
- name=self.repo_get(self.repo.CONFIRMATION)['resource']['name'],
- desc=self.repo_get(self.repo.CONFIRMATION)['resource']['description'],
- lab=self.repo_get(self.repo.CONFIRMATION)['template']['lab'])
- confirm_details += "\nResources:"
- for i, device in enumerate(self.repo_get(self.repo.RESOURCE_TEMPLATE_MODELS)['resources']):
- confirm_details += "\n " + str(device) + ": " + str(self.repo_get(self.repo.CONFIRMATION)['template']['resources'][i]['profile'])
- context['confirmation_info'] = confirm_details
- if self.valid == WorkflowStepStatus.VALID:
- context["confirm_succeeded"] = "true"
-
- return context
-
- def flush_to_db(self):
- errors = self.repo.make_models()
- if errors:
- return errors
-
- def post(self, post_data, user):
- form = ConfirmationForm(post_data)
- if form.is_valid():
- data = form.cleaned_data['confirm']
- if data == "True":
- errors = self.flush_to_db()
- if errors:
- self.set_invalid("ERROR OCCURRED: " + errors)
- else:
- self.set_valid("Confirmed")
-
- elif data == "False":
- self.repo.cancel()
- self.set_valid("Canceled")
- else:
- self.set_invalid("Bad Form Contents")
-
- else:
- self.set_invalid("Bad Form Contents")
-
-
-class Repository():
-
- EDIT = "editing"
- MODELS = "models"
- RESOURCE_SELECT = "resource_select"
- CONFIRMATION = "confirmation"
- SELECTED_RESOURCE_TEMPLATE = "selected resource template pk"
- SELECTED_OPNFV_CONFIG = "selected opnfv deployment config"
- RESOURCE_TEMPLATE_MODELS = "generic_resource_template_models"
- RESOURCE_TEMPLATE_INFO = "generic_resource_template_info"
- BOOKING = "booking"
- LAB = "lab"
- RCONFIG_LAST_HOSTLIST = "resource_configuration_network_previous_hostlist"
- BOOKING_FORMS = "booking_forms"
- SWCONF_HOSTS = "swconf_hosts"
- BOOKING_MODELS = "booking models"
- CONFIG_MODELS = "configuration bundle models"
- OPNFV_MODELS = "opnfv configuration models"
- SESSION_USER = "session owner user account"
- SESSION_MANAGER = "session manager for current session"
- VALIDATED_MODEL_GRB = "valid grb config model instance in db"
- VALIDATED_MODEL_CONFIG = "valid config model instance in db"
- VALIDATED_MODEL_BOOKING = "valid booking model instance in db"
- VLANS = "a list of vlans"
- SNAPSHOT_MODELS = "the models for snapshotting"
- SNAPSHOT_BOOKING_ID = "the booking id for snapshotting"
- SNAPSHOT_NAME = "the name of the snapshot"
- SNAPSHOT_DESC = "description of the snapshot"
- BOOKING_INFO_FILE = "the INFO.yaml file for this user's booking"
-
- # new keys for migration to using ResourceTemplates:
- RESOURCE_TEMPLATE_MODELS = "current working model of resource template"
-
- # migratory elements of segmented workflow
- # each of these is the end result of a different workflow.
- HAS_RESULT = "whether or not workflow has a result"
- RESULT_KEY = "key for target index that result will be put into in parent"
- RESULT = "result object from workflow"
-
- def get_child_defaults(self):
- return_tuples = []
- for key in [self.SELECTED_RESOURCE_TEMPLATE, self.SESSION_USER]:
- return_tuples.append((key, self.el.get(key)))
- return return_tuples
-
- def set_defaults(self, defaults):
- for key, value in defaults:
- self.el[key] = value
-
- def get(self, key, default, id):
-
- self.add_get_history(key, id)
- return self.el.get(key, default)
-
- def put(self, key, val, id):
- self.add_put_history(key, id)
- self.el[key] = val
-
- def add_get_history(self, key, id):
- self.add_history(key, id, self.get_history)
-
- def add_put_history(self, key, id):
- self.add_history(key, id, self.put_history)
-
- def add_history(self, key, id, history):
- if key not in history:
- history[key] = [id]
- else:
- history[key].append(id)
-
- def cancel(self):
- if self.RESOURCE_TEMPLATE_MODELS in self.el:
- models = self.el[self.RESOURCE_TEMPLATE_MODELS]
- if models['template'].temporary:
- models['template'].delete()
- # deleting current template should cascade delete all
- # necessary related models
-
- def make_models(self):
- if self.SNAPSHOT_MODELS in self.el:
- errors = self.make_snapshot()
- if errors:
- return errors
-
- # if GRB WF, create it
- if self.RESOURCE_TEMPLATE_MODELS in self.el:
- errors = self.make_generic_resource_bundle()
- if errors:
- return errors
- else:
- self.el[self.HAS_RESULT] = True
- self.el[self.RESULT_KEY] = self.SELECTED_RESOURCE_TEMPLATE
- return
-
- if self.OPNFV_MODELS in self.el:
- errors = self.make_opnfv_config()
- if errors:
- return errors
- else:
- self.el[self.HAS_RESULT] = True
- self.el[self.RESULT_KEY] = self.SELECTED_OPNFV_CONFIG
-
- if self.BOOKING_MODELS in self.el:
- errors = self.make_booking()
- if errors:
- return errors
- # create notification
- booking = self.el[self.BOOKING_MODELS]['booking']
- NotificationHandler.notify_new_booking(booking)
-
- def make_snapshot(self):
- owner = self.el[self.SESSION_USER]
- models = self.el[self.SNAPSHOT_MODELS]
- image = models.get('snapshot', Image())
- booking_id = self.el.get(self.SNAPSHOT_BOOKING_ID)
- if not booking_id:
- return "SNAP, No booking ID provided"
- booking = Booking.objects.get(pk=booking_id)
- if booking.start > timezone.now() or booking.end < timezone.now():
- return "Booking is not active"
- name = self.el.get(self.SNAPSHOT_NAME)
- if not name:
- return "SNAP, no name provided"
- host = models.get('host')
- if not host:
- return "SNAP, no host provided"
- description = self.el.get(self.SNAPSHOT_DESC, "")
- image.from_lab = booking.lab
- image.name = name
- image.description = description
- image.public = False
- image.lab_id = -1
- image.owner = owner
- image.host_type = host.profile
- image.save()
- try:
- current_image = host.config.image
- image.os = current_image.os
- image.save()
- except Exception:
- pass
- JobFactory.makeSnapshotTask(image, booking, host)
-
- self.el[self.RESULT] = image
- self.el[self.HAS_RESULT] = True
-
- def make_generic_resource_bundle(self):
- owner = self.el[self.SESSION_USER]
- if self.RESOURCE_TEMPLATE_MODELS in self.el:
- models = self.el[self.RESOURCE_TEMPLATE_MODELS]
- models['template'].owner = owner
- models['template'].temporary = False
- models['template'].save()
- self.el[self.RESULT] = models['template']
- self.el[self.HAS_RESULT] = True
- return False
-
- else:
- return "GRB no models given. CODE:0x0001"
-
- def make_software_config_bundle(self):
- models = self.el[self.CONFIG_MODELS]
- if 'bundle' in models:
- bundle = models['bundle']
- bundle.bundle = self.el[self.SELECTED_RESOURCE_TEMPLATE]
- try:
- bundle.save()
- except Exception as e:
- return "SWC, saving bundle generated exception: " + str(e) + "CODE:0x0007"
-
- else:
- return "SWC, no bundle in models. CODE:0x0006"
- if 'host_configs' in models:
- host_configs = models['host_configs']
- for host_config in host_configs:
- host_config.template = host_config.template
- host_config.profile = host_config.profile
- try:
- host_config.save()
- except Exception as e:
- return "SWC, saving host configs generated exception: " + str(e) + "CODE:0x0009"
- else:
- return "SWC, no host configs in models. CODE:0x0008"
- if 'opnfv' in models:
- opnfvconfig = models['opnfv']
- opnfvconfig.bundle = opnfvconfig.bundle
- if opnfvconfig.scenario not in opnfvconfig.installer.sup_scenarios.all():
- return "SWC, scenario not supported by installer. CODE:0x000d"
- try:
- opnfvconfig.save()
- except Exception as e:
- return "SWC, saving opnfv config generated exception: " + str(e) + "CODE:0x000b"
- else:
- pass
-
- self.el[self.RESULT] = bundle
- return False
-
- @transaction.atomic # TODO: Rewrite transactions with savepoints at user level for all workflows
- def make_booking(self):
- models = self.el[self.BOOKING_MODELS]
- owner = self.el[self.SESSION_USER]
-
- if 'booking' in models:
- booking = models['booking']
- else:
- return "BOOK, no booking model exists. CODE:0x000f"
-
- selected_grb = None
-
- if self.SELECTED_RESOURCE_TEMPLATE in self.el:
- selected_grb = self.el[self.SELECTED_RESOURCE_TEMPLATE]
- else:
- return "BOOK, no selected resource. CODE:0x000e"
-
- if not booking.start:
- return "BOOK, booking has no start. CODE:0x0010"
- if not booking.end:
- return "BOOK, booking has no end. CODE:0x0011"
- if booking.end <= booking.start:
- return "BOOK, end before/same time as start. CODE:0x0012"
-
- if 'collaborators' in models:
- collaborators = models['collaborators']
- else:
- return "BOOK, collaborators not defined. CODE:0x0013"
- try:
- res_manager = ResourceManager.getInstance()
- resource_bundle = res_manager.instantiateTemplate(selected_grb)
- except ResourceAvailabilityException as e:
- return "BOOK, requested resources are not available. Exception: " + str(e) + " CODE:0x0014"
- except ModelValidationException as e:
- return "Error encountered when saving bundle. " + str(e) + " CODE: 0x001b"
-
- booking.resource = resource_bundle
- booking.owner = owner
- booking.lab = selected_grb.lab
-
- is_allowed = BookingAuthManager().booking_allowed(booking, self)
- if not is_allowed:
- return "BOOK, you are not allowed to book the requested resources"
-
- try:
- booking.save()
- except Exception as e:
- return "BOOK, saving booking generated exception: " + str(e) + " CODE:0x0015"
-
- for collaborator in collaborators:
- booking.collaborators.add(collaborator)
-
- try:
- booking.pdf = PDFTemplater.makePDF(booking)
- booking.save()
- except Exception as e:
- return "BOOK, failed to create Pod Desriptor File: " + str(e)
-
- try:
- JobFactory.makeCompleteJob(booking)
- except Exception as e:
- return "BOOK, serializing for api generated exception: " + str(e) + " CODE:0xFFFF"
-
- try:
- booking.save()
- except Exception as e:
- return "BOOK, saving booking generated exception: " + str(e) + " CODE:0x0016"
-
- self.el[self.RESULT] = booking
- self.el[self.HAS_RESULT] = True
-
- def make_opnfv_config(self):
- opnfv_models = self.el[self.OPNFV_MODELS]
- config_bundle = self.el[self.SELECTED_CONFIG_BUNDLE]
- if not config_bundle:
- return "No Configuration bundle selected"
- info = opnfv_models.get("meta", {})
- name = info.get("name", False)
- desc = info.get("description", False)
- if not (name and desc):
- return "No name or description given"
- installer = opnfv_models['installer_chosen']
- if not installer:
- return "No OPNFV Installer chosen"
- scenario = opnfv_models['scenario_chosen']
- if not scenario:
- return "No OPNFV Scenario chosen"
-
- opnfv_config = OPNFVConfig.objects.create(
- bundle=config_bundle,
- name=name,
- description=desc,
- installer=installer,
- scenario=scenario
- )
-
- network_roles = opnfv_models['network_roles']
- for net_role in network_roles:
- opnfv_config.networks.add(
- NetworkRole.objects.create(
- name=net_role['role'],
- network=net_role['network']
- )
- )
-
- host_roles = opnfv_models['host_roles']
- for host_role in host_roles:
- config = config_bundle.hostConfigurations.get(
- host__resource__name=host_role['host_name']
- )
- ResourceOPNFVConfig.objects.create(
- role=host_role['role'],
- host_config=config,
- opnfv_config=opnfv_config
- )
-
- self.el[self.RESULT] = opnfv_config
- self.el[self.HAS_RESULT] = True
-
- def __init__(self):
- self.el = {}
- self.el[self.CONFIRMATION] = {}
- self.el["active_step"] = 0
- self.el[self.HAS_RESULT] = False
- self.el[self.RESULT] = None
- self.get_history = {}
- self.put_history = {}
diff --git a/src/workflow/opnfv_workflow.py b/src/workflow/opnfv_workflow.py
deleted file mode 100644
index 6ffc91d..0000000
--- a/src/workflow/opnfv_workflow.py
+++ /dev/null
@@ -1,292 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-
-from django.forms import formset_factory
-
-from workflow.models import WorkflowStep, AbstractSelectOrCreate
-from resource_inventory.models import ResourceTemplate, OPNFV_SETTINGS
-from workflow.forms import OPNFVSelectionForm, OPNFVNetworkRoleForm, OPNFVHostRoleForm, SWConfigSelectorForm, BasicMetaForm
-
-
-class OPNFV_Resource_Select(AbstractSelectOrCreate):
- title = "Select Software Configuration"
- description = "Choose the software bundle you wish to use as a base for your OPNFV configuration"
- short_title = "software config"
- form = SWConfigSelectorForm
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.select_repo_key = self.repo.SELECTED_CONFIG_BUNDLE
-
- def get_form_queryset(self):
- user = self.repo_get(self.repo.SESSION_USER)
- qs = ResourceTemplate.objects.filter(owner=user)
- return qs
-
- def put_confirm_info(self, bundle):
- confirm_dict = self.repo_get(self.repo.CONFIRMATION)
- confirm_dict['software bundle'] = bundle.name
- confirm_dict['hardware POD'] = bundle.bundle.name
- self.repo_put(self.repo.CONFIRMATION, confirm_dict)
-
- def get_page_context(self):
- return {
- 'select_type': 'swconfig',
- 'select_type_title': 'Software Config',
- 'addable_type_num': 2
- }
-
-
-class Pick_Installer(WorkflowStep):
- template = 'config_bundle/steps/pick_installer.html'
- title = 'Pick OPNFV Installer'
- description = 'Choose which OPNFV installer to use'
- short_title = "opnfv installer"
- modified_key = "installer_step"
-
- def update_confirmation(self):
- confirm = self.repo_get(self.repo.CONFIRMATION, {})
- models = self.repo_get(self.repo.OPNFV_MODELS, {})
- installer = models.get("installer_chosen")
- scenario = models.get("scenario_chosen")
- if not (installer and scenario):
- return
- confirm['installer'] = installer.name
- confirm['scenario'] = scenario.name
- self.repo_put(self.repo.CONFIRMATION, confirm)
-
- def get_context(self):
- context = super(Pick_Installer, self).get_context()
-
- models = self.repo_get(self.repo.OPNFV_MODELS, {})
- initial = {
- "installer": models.get("installer_chosen"),
- "scenario": models.get("scenario_chosen")
- }
-
- context["form"] = OPNFVSelectionForm(initial=initial)
- return context
-
- def post(self, post_data, user):
- form = OPNFVSelectionForm(post_data)
- if form.is_valid():
- installer = form.cleaned_data['installer']
- scenario = form.cleaned_data['scenario']
- models = self.repo_get(self.repo.OPNFV_MODELS, {})
- models['installer_chosen'] = installer
- models['scenario_chosen'] = scenario
- self.repo_put(self.repo.OPNFV_MODELS, models)
- self.update_confirmation()
- self.set_valid("Step Completed")
- else:
- self.set_invalid("Please select an Installer and Scenario")
-
-
-class Assign_Network_Roles(WorkflowStep):
- template = 'config_bundle/steps/assign_network_roles.html'
- title = 'Pick Network Roles'
- description = 'Choose what role each network should get'
- short_title = "network roles"
- modified_key = "net_roles_step"
-
- """
- to do initial filling, repo should have a "network_roles" array with the following structure for each element:
- {
- "role": ,
- "network":
- }
- """
- def create_netformset(self, roles, config_bundle, data=None):
- roles_initial = []
- set_roles = self.repo_get(self.repo.OPNFV_MODELS, {}).get("network_roles")
- if set_roles:
- roles_initial = set_roles
- else:
- for role in OPNFV_SETTINGS.NETWORK_ROLES:
- roles_initial.append({"role": role})
-
- Formset = formset_factory(OPNFVNetworkRoleForm, extra=0)
- kwargs = {
- "initial": roles_initial,
- "form_kwargs": {"config_bundle": config_bundle}
- }
- formset = None
- if data:
- formset = Formset(data, **kwargs)
- else:
- formset = Formset(**kwargs)
- return formset
-
- def get_context(self):
- context = super(Assign_Network_Roles, self).get_context()
- config_bundle = self.repo_get(self.repo.SELECTED_CONFIG_BUNDLE)
- if config_bundle is None:
- context["unavailable"] = True
- return context
-
- roles = OPNFV_SETTINGS.NETWORK_ROLES
- formset = self.create_netformset(roles, config_bundle)
- context['formset'] = formset
-
- return context
-
- def update_confirmation(self):
- confirm = self.repo_get(self.repo.CONFIRMATION, {})
- models = self.repo_get(self.repo.OPNFV_MODELS, {})
- roles = models.get("network_roles")
- if not roles:
- return
- confirm['network roles'] = {}
- for role in roles:
- confirm['network roles'][role['role']] = role['network'].name
- self.repo_put(self.repo.CONFIRMATION, confirm)
-
- def post(self, post_data, user):
- models = self.repo_get(self.repo.OPNFV_MODELS, {})
- config_bundle = self.repo_get(self.repo.SELECTED_CONFIG_BUNDLE)
- roles = OPNFV_SETTINGS.NETWORK_ROLES
- net_role_formset = self.create_netformset(roles, config_bundle, data=post_data)
- if net_role_formset.is_valid():
- results = []
- for form in net_role_formset:
- results.append({
- "role": form.cleaned_data['role'],
- "network": form.cleaned_data['network']
- })
- models['network_roles'] = results
- self.set_valid("Completed")
- self.repo_put(self.repo.OPNFV_MODELS, models)
- self.update_confirmation()
- else:
- self.set_invalid("Please complete all fields")
-
-
-class Assign_Host_Roles(WorkflowStep): # taken verbatim from Define_Software in sw workflow, merge the two?
- template = 'config_bundle/steps/assign_host_roles.html'
- title = 'Pick Host Roles'
- description = "Choose the role each machine will have in your OPNFV pod"
- short_title = "host roles"
- modified_key = "host_roles_step"
-
- def create_host_role_formset(self, hostlist=[], data=None):
- models = self.repo_get(self.repo.OPNFV_MODELS, {})
- host_roles = models.get("host_roles", [])
- if not host_roles:
- for host in hostlist:
- initial = {"host_name": host.resource.name}
- host_roles.append(initial)
- models['host_roles'] = host_roles
- self.repo_put(self.repo.OPNFV_MODELS, models)
-
- HostFormset = formset_factory(OPNFVHostRoleForm, extra=0)
-
- kwargs = {"initial": host_roles}
- formset = None
- if data:
- formset = HostFormset(data, **kwargs)
- else:
- formset = HostFormset(**kwargs)
-
- return formset
-
- def get_context(self):
- context = super(Assign_Host_Roles, self).get_context()
- config = self.repo_get(self.repo.SELECTED_CONFIG_BUNDLE)
- if config is None:
- context['error'] = "Please select a Configuration on the first step"
-
- formset = self.create_host_role_formset(hostlist=config.bundle.getResources())
- context['formset'] = formset
-
- return context
-
- def get_host_role_mapping(self, host_roles, hostname):
- for obj in host_roles:
- if hostname == obj['host_name']:
- return obj
- return None
-
- def update_confirmation(self):
- confirm = self.repo_get(self.repo.CONFIRMATION, {})
- models = self.repo_get(self.repo.OPNFV_MODELS, {})
- roles = models.get("host_roles")
- if not roles:
- return
- confirm['host roles'] = {}
- for role in roles:
- confirm['host roles'][role['host_name']] = role['role'].name
- self.repo_put(self.repo.CONFIRMATION, confirm)
-
- def post(self, post_data, user):
- formset = self.create_host_role_formset(data=post_data)
-
- models = self.repo_get(self.repo.OPNFV_MODELS, {})
- host_roles = models.get("host_roles", [])
-
- has_jumphost = False
- if formset.is_valid():
- for form in formset:
- hostname = form.cleaned_data['host_name']
- role = form.cleaned_data['role']
- mapping = self.get_host_role_mapping(host_roles, hostname)
- mapping['role'] = role
- if "jumphost" in role.name.lower():
- has_jumphost = True
-
- models['host_roles'] = host_roles
- self.repo_put(self.repo.OPNFV_MODELS, models)
- self.update_confirmation()
-
- if not has_jumphost:
- self.set_invalid('Must have at least one "Jumphost" per POD')
- else:
- self.set_valid("Completed")
- else:
- self.set_invalid("Please complete all fields")
-
-
-class MetaInfo(WorkflowStep):
- template = 'config_bundle/steps/config_software.html'
- title = "Other Info"
- description = "Give your software config a name, description, and other stuff"
- short_title = "config info"
-
- def get_context(self):
- context = super(MetaInfo, self).get_context()
-
- initial = self.repo_get(self.repo.OPNFV_MODELS, {}).get("meta", {})
- context["form"] = BasicMetaForm(initial=initial)
- return context
-
- def update_confirmation(self):
- confirm = self.repo_get(self.repo.CONFIRMATION, {})
- models = self.repo_get(self.repo.OPNFV_MODELS, {})
- meta = models.get("meta")
- if not meta:
- return
- confirm['name'] = meta['name']
- confirm['description'] = meta['description']
- self.repo_put(self.repo.CONFIRMATION, confirm)
-
- def post(self, post_data, user):
- models = self.repo_get(self.repo.OPNFV_MODELS, {})
- info = models.get("meta", {})
-
- form = BasicMetaForm(post_data)
- if form.is_valid():
- info['name'] = form.cleaned_data['name']
- info['description'] = form.cleaned_data['description']
- models['meta'] = info
- self.repo_put(self.repo.OPNFV_MODELS, models)
- self.update_confirmation()
- self.set_valid("Complete")
- else:
- self.set_invalid("Please correct the errors shown below")
- self.repo_put(self.repo.OPNFV_MODELS, models)
diff --git a/src/workflow/resource_bundle_workflow.py b/src/workflow/resource_bundle_workflow.py
deleted file mode 100644
index 4e288b5..0000000
--- a/src/workflow/resource_bundle_workflow.py
+++ /dev/null
@@ -1,614 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-
-from django.conf import settings
-from django.forms import formset_factory
-from django.core.exceptions import ValidationError
-
-from typing import List
-
-import re
-import json
-from xml.dom import minidom
-import traceback
-
-from workflow.models import WorkflowStep
-from account.models import Lab
-from workflow.forms import (
- HardwareDefinitionForm,
- NetworkDefinitionForm,
- ResourceMetaForm,
- HostSoftwareDefinitionForm,
-)
-from resource_inventory.models import (
- ResourceTemplate,
- ResourceConfiguration,
- InterfaceConfiguration,
- Network,
- NetworkConnection,
- Image,
-)
-from dashboard.exceptions import (
- InvalidVlanConfigurationException,
- NetworkExistsException,
- ResourceAvailabilityException
-)
-
-import logging
-logger = logging.getLogger(__name__)
-
-
-class Define_Hardware(WorkflowStep):
-
- template = 'resource/steps/define_hardware.html'
- title = "Define Hardware"
- description = "Choose the type and amount of machines you want"
- short_title = "hosts"
-
- def __init__(self, *args, **kwargs):
- self.form = None
- super().__init__(*args, **kwargs)
-
- def get_context(self):
- context = super(Define_Hardware, self).get_context()
- user = self.repo_get(self.repo.SESSION_USER)
- context['form'] = self.form or HardwareDefinitionForm(user)
- return context
-
- def update_models(self, data):
- data = data['filter_field']
- models = self.repo_get(self.repo.RESOURCE_TEMPLATE_MODELS, {})
- models['resources'] = [] # This will always clear existing data when this step changes
- models['connections'] = []
- models['interfaces'] = {}
- if "template" not in models:
- template = ResourceTemplate.objects.create(temporary=True)
- models['template'] = template
-
- resource_data = data['resource']
-
- new_template = models['template']
-
- public_network = Network.objects.create(name="public", bundle=new_template, is_public=True)
-
- all_networks = {public_network.id: public_network}
-
- for resource_template_dict in resource_data.values():
- id = resource_template_dict['id']
- old_template = ResourceTemplate.objects.get(id=id)
-
- # instantiate genericHost and store in repo
- for _ in range(0, resource_template_dict['count']):
- resource_configs = old_template.resourceConfigurations.all()
- for config in resource_configs:
- # need to save now for connections to refer to it later
- new_config = ResourceConfiguration.objects.create(
- profile=config.profile,
- image=config.image,
- name=config.name,
- template=new_template)
-
- for interface_config in config.interface_configs.all():
- new_interface_config = InterfaceConfiguration.objects.create(
- profile=interface_config.profile,
- resource_config=new_config)
-
- for connection in interface_config.connections.all():
- network = None
- if connection.network.is_public:
- network = public_network
- else:
- # check if network is known
- if connection.network.id not in all_networks:
- # create matching one
- new_network = Network(
- name=connection.network.name + "_" + str(new_config.id),
- bundle=new_template,
- is_public=False)
- new_network.save()
-
- all_networks[connection.network.id] = new_network
-
- network = all_networks[connection.network.id]
-
- new_connection = NetworkConnection(
- network=network,
- vlan_is_tagged=connection.vlan_is_tagged)
-
- new_interface_config.save() # can't do later because M2M on next line
- new_connection.save()
-
- new_interface_config.connections.add(new_connection)
-
- unique_resource_ref = new_config.name + "_" + str(new_config.id)
- if unique_resource_ref not in models['interfaces']:
- models['interfaces'][unique_resource_ref] = []
- models['interfaces'][unique_resource_ref].append(interface_config)
-
- models['resources'].append(new_config)
-
- models['networks'] = all_networks
-
- # add selected lab to models
- for lab_dict in data['lab'].values():
- if lab_dict['selected']:
- models['template'].lab = Lab.objects.get(lab_user__id=lab_dict['id'])
- models['template'].save()
- break # if somehow we get two 'true' labs, we only use one
-
- # return to repo
- self.repo_put(self.repo.RESOURCE_TEMPLATE_MODELS, models)
-
- def update_confirmation(self):
- confirm = self.repo_get(self.repo.CONFIRMATION, {})
- if "template" not in confirm:
- confirm['template'] = {}
- confirm['template']['resources'] = []
- models = self.repo_get(self.repo.RESOURCE_TEMPLATE_MODELS, {})
- if 'template' in models:
- for resource in models['template'].getConfigs():
- host_dict = {"name": resource.name, "profile": resource.profile.name}
- confirm['template']['resources'].append(host_dict)
- if "template" in models:
- confirm['template']['lab'] = models['template'].lab.lab_user.username
- self.repo_put(self.repo.CONFIRMATION, confirm)
-
- def post(self, post_data, user):
- try:
- user = self.repo_get(self.repo.SESSION_USER)
- self.form = HardwareDefinitionForm(user, post_data)
- if self.form.is_valid():
- self.update_models(self.form.cleaned_data)
- self.update_confirmation()
- self.set_valid("Step Completed")
- else:
- self.set_invalid("Please complete the fields highlighted in red to continue")
- except Exception as e:
- print("Caught exception: " + str(e))
- traceback.print_exc()
- self.form = None
- self.set_invalid("Please select a lab.")
-
-
-class Define_Software(WorkflowStep):
- template = 'config_bundle/steps/define_software.html'
- title = "Pick Software"
- description = "Choose the opnfv and image of your machines"
- short_title = "host config"
-
- def build_filter_data(self, hosts_data):
- """
- Build list of Images to filter out.
-
- returns a 2D array of images to exclude
- based on the ordering of the passed
- hosts_data
- """
-
- filter_data = []
- user = self.repo_get(self.repo.SESSION_USER)
- lab = self.repo_get(self.repo.RESOURCE_TEMPLATE_MODELS)['template'].lab
- for i, host_data in enumerate(hosts_data):
- host = ResourceConfiguration.objects.get(pk=host_data['host_id'])
- wrong_owner = Image.objects.exclude(owner=user).exclude(public=True)
- wrong_host = Image.objects.exclude(architecture=host.profile.architecture)
- wrong_lab = Image.objects.exclude(from_lab=lab)
- excluded_images = wrong_owner | wrong_host | wrong_lab
- filter_data.append([])
- for image in excluded_images:
- filter_data[i].append(image.pk)
- return filter_data
-
- def create_hostformset(self, hostlist, data=None):
- hosts_initial = []
- configs = self.repo_get(self.repo.RESOURCE_TEMPLATE_MODELS, {}).get("resources")
- if configs:
- for i in range(len(configs)):
- default_name = 'laas-node'
- if i > 0:
- default_name = default_name + "-" + str(i + 1)
- hosts_initial.append({
- 'host_id': configs[i].id,
- 'host_name': default_name,
- 'headnode': False,
- 'image': configs[i].image
- })
- else:
- for host in hostlist:
- hosts_initial.append({
- 'host_id': host.id,
- 'host_name': host.name
- })
-
- HostFormset = formset_factory(HostSoftwareDefinitionForm, extra=0)
- filter_data = self.build_filter_data(hosts_initial)
-
- class SpecialHostFormset(HostFormset):
- def get_form_kwargs(self, index):
- kwargs = super(SpecialHostFormset, self).get_form_kwargs(index)
- if index is not None:
- kwargs['imageQS'] = Image.objects.exclude(pk__in=filter_data[index])
- return kwargs
-
- if data:
- return SpecialHostFormset(data, initial=hosts_initial)
- return SpecialHostFormset(initial=hosts_initial)
-
- def get_host_list(self, grb=None):
- return self.repo_get(self.repo.RESOURCE_TEMPLATE_MODELS).get("resources")
-
- def get_context(self):
- context = super(Define_Software, self).get_context()
-
- context["formset"] = self.create_hostformset(self.get_host_list())
-
- return context
-
- def post(self, post_data, user):
- hosts = self.get_host_list()
- formset = self.create_hostformset(hosts, data=post_data)
- has_headnode = False
- if formset.is_valid():
- for i, form in enumerate(formset):
- host = hosts[i]
- image = form.cleaned_data['image']
- hostname = form.cleaned_data['host_name']
- headnode = form.cleaned_data['headnode']
- if headnode:
- has_headnode = True
- host.is_head_node = headnode
- host.name = hostname
- host.image = image
- # RFC921: They must start with a letter, end with a letter or digit and have only letters or digits or hyphen as interior characters
- if bool(re.match("^[A-Za-z0-9-]*$", hostname)) is False:
- self.set_invalid("Device names must only contain alphanumeric characters and dashes.")
- return
- if not hostname[0].isalpha() or not hostname[-1].isalnum():
- self.set_invalid("Device names must start with a letter and end with a letter or digit.")
- return
- for j in range(i):
- if j != i and hostname == hosts[j].name:
- self.set_invalid("Devices must have unique names. Please try again.")
- return
- host.save()
-
- if not has_headnode and len(hosts) > 0:
- self.set_invalid("No headnode. Please set a headnode.")
- return
-
- self.set_valid("Completed")
- else:
- self.set_invalid("Please complete all fields.")
-
-
-class Define_Nets(WorkflowStep):
- template = 'resource/steps/pod_definition.html'
- title = "Define Networks"
- description = "Use the tool below to draw the network topology of your POD"
- short_title = "networking"
- form = NetworkDefinitionForm
-
- def get_vlans(self):
- vlans = self.repo_get(self.repo.VLANS)
- if vlans:
- return vlans
- # try to grab some vlans from lab
- models = self.repo_get(self.repo.RESOURCE_TEMPLATE_MODELS, {})
- if "bundle" not in models:
- return None
- lab = models['bundle'].lab
- if lab is None or lab.vlan_manager is None:
- return None
- try:
- vlans = lab.vlan_manager.get_vlans(count=lab.vlan_manager.block_size)
- self.repo_put(self.repo.VLANS, vlans)
- return vlans
- except Exception:
- return None
-
- def make_mx_network_dict(self, network):
- return {
- 'id': network.id,
- 'name': network.name,
- 'public': network.is_public
- }
-
- def make_mx_resource_dict(self, resource_config):
- resource_dict = {
- 'id': resource_config.id,
- 'interfaces': [],
- 'value': {
- 'name': resource_config.name,
- 'id': resource_config.id,
- 'description': resource_config.profile.description
- }
- }
-
- for interface_config in resource_config.interface_configs.all():
- connections = []
- for connection in interface_config.connections.all():
- connections.append({'tagged': connection.vlan_is_tagged, 'network': connection.network.id})
-
- interface_dict = {
- "id": interface_config.id,
- "name": interface_config.profile.name,
- "description": "speed: " + str(interface_config.profile.speed) + "M\ntype: " + interface_config.profile.nic_type,
- "connections": connections
- }
-
- resource_dict['interfaces'].append(interface_dict)
-
- return resource_dict
-
- def make_mx_host_dict(self, generic_host):
- host = {
- 'id': generic_host.profile.name,
- 'interfaces': [],
- 'value': {
- "name": generic_host.profile.name,
- "description": generic_host.profile.description
- }
- }
- for iface in generic_host.profile.interfaceprofile.all():
- host['interfaces'].append({
- "name": iface.name,
- "description": "speed: " + str(iface.speed) + "M\ntype: " + iface.nic_type
- })
- return host
-
- # first step guards this one, so can't get here without at least empty
- # models being populated by step one
- def get_context(self):
- context = super(Define_Nets, self).get_context()
- context.update({
- 'form': NetworkDefinitionForm(),
- 'debug': settings.DEBUG,
- 'resources': {},
- 'networks': {},
- 'vlans': [],
- # remove others
- 'hosts': [],
- 'added_hosts': [],
- 'removed_hosts': []
- })
-
- models = self.repo_get(self.repo.RESOURCE_TEMPLATE_MODELS) # infallible, guarded by prior step
- for resource in models['resources']:
- d = self.make_mx_resource_dict(resource)
- context['resources'][d['id']] = d
-
- for network in models['networks'].values():
- d = self.make_mx_network_dict(network)
- context['networks'][d['id']] = d
-
- return context
-
- def post(self, post_data, user):
- try:
- xmlData = post_data.get("xml")
- self.updateModels(xmlData)
- # update model with xml
- self.set_valid("Networks applied successfully")
- except ResourceAvailabilityException:
- self.set_invalid("Public network not availble")
- except Exception as e:
- traceback.print_exc()
- self.set_invalid("An error occurred when applying networks: " + str(e))
-
- def resetNetworks(self, networks: List[Network]): # potentially just pass template here?
- for network in networks:
- network.delete()
-
- def updateModels(self, xmlData):
- models = self.repo_get(self.repo.RESOURCE_TEMPLATE_MODELS, {})
- given_hosts = None
- interfaces = None
- networks = None
- try:
- given_hosts, interfaces, networks = self.parseXml(xmlData)
- except Exception as e:
- print("tried to parse Xml, got exception instead:")
- print(e)
-
- existing_rconfig_list = models.get("resources", [])
- existing_rconfigs = {} # maps id to host
- for rconfig in existing_rconfig_list:
- existing_rconfigs["host_" + str(rconfig.id)] = rconfig
-
- bundle = models.get("template") # hard fail if not in repo
-
- self.resetNetworks(models['networks'].values())
- models['networks'] = {}
-
- for net_id, net in networks.items():
- network = Network.objects.create(
- name=net['name'],
- bundle=bundle,
- is_public=net['public'])
-
- models['networks'][net_id] = network
- network.save()
-
- for hostid, given_host in given_hosts.items():
- for ifaceId in given_host['interfaces']:
- iface = interfaces[ifaceId]
-
- iface_config = InterfaceConfiguration.objects.get(id=iface['config_id'])
- if iface_config.resource_config.template.id != bundle.id:
- raise ValidationError("User does not own the template they are editing")
-
- for connection in iface['connections']:
- network_id = connection['network']
- net = models['networks'][network_id]
- connection = NetworkConnection(vlan_is_tagged=connection['tagged'], network=net)
- connection.save()
- iface_config.connections.add(connection)
- iface_config.save()
- self.repo_put(self.repo.RESOURCE_TEMPLATE_MODELS, models)
-
- def decomposeXml(self, xmlString):
- """
- Translate XML into useable data.
-
- This function takes in an xml doc from our front end
- and returns dictionaries that map cellIds to the xml
- nodes themselves. There is no unpacking of the
- xml objects, just grouping and organizing
- """
- connections = {}
- networks = {}
- hosts = {}
- interfaces = {}
- network_ports = {}
-
- xmlDom = minidom.parseString(xmlString)
- root = xmlDom.documentElement.firstChild
- for cell in root.childNodes:
- cellId = cell.getAttribute('id')
- group = cellId.split("_")[0]
- parentGroup = cell.getAttribute("parent").split("_")[0]
- # place cell into correct group
-
- if cell.getAttribute("edge"):
- connections[cellId] = cell
-
- elif "network" in group:
- networks[cellId] = cell
-
- elif "host" in group:
- hosts[cellId] = cell
-
- elif "host" in parentGroup:
- interfaces[cellId] = cell
-
- # make network ports also map to thier network
- elif "network" in parentGroup:
- network_ports[cellId] = cell.getAttribute("parent") # maps port ID to net ID
-
- return connections, networks, hosts, interfaces, network_ports
-
- # serialize and deserialize xml from mxGraph
- def parseXml(self, xmlString):
- networks = {} # maps net name to network object
- hosts = {} # cotains id -> hosts, each containing interfaces, referencing networks
- interfaces = {} # maps id -> interface
- untagged_ifaces = set() # used to check vlan config
- network_names = set() # used to check network names
- xml_connections, xml_nets, xml_hosts, xml_ifaces, xml_ports = self.decomposeXml(xmlString)
-
- # parse Hosts
- for cellId, cell in xml_hosts.items():
- cell_json_str = cell.getAttribute("value")
- cell_json = json.loads(cell_json_str)
- host = {"interfaces": [], "name": cellId, "hostname": cell_json['name']}
- hosts[cellId] = host
-
- # parse networks
- for cellId, cell in xml_nets.items():
- escaped_json_str = cell.getAttribute("value")
- json_str = escaped_json_str.replace('"', '"')
- net_info = json.loads(json_str)
- net_name = net_info['name']
- public = net_info['public']
- if net_name in network_names:
- raise NetworkExistsException("Non unique network name found")
- network = {"name": net_name, "public": public, "id": cellId}
- networks[cellId] = network
- network_names.add(net_name)
-
- # parse interfaces
- for cellId, cell in xml_ifaces.items():
- parentId = cell.getAttribute('parent')
- cell_json_str = cell.getAttribute("value")
- cell_json = json.loads(cell_json_str)
- iface = {"graph_id": cellId, "connections": [], "config_id": cell_json['id'], "profile_name": cell_json['name']}
- hosts[parentId]['interfaces'].append(cellId)
- interfaces[cellId] = iface
-
- # parse connections
- for cellId, cell in xml_connections.items():
- escaped_json_str = cell.getAttribute("value")
- json_str = escaped_json_str.replace('"', '"')
- attributes = json.loads(json_str)
- tagged = attributes['tagged']
- interface = None
- network = None
- src = cell.getAttribute("source")
- tgt = cell.getAttribute("target")
- if src in interfaces:
- interface = interfaces[src]
- network = networks[xml_ports[tgt]]
- else:
- interface = interfaces[tgt]
- network = networks[xml_ports[src]]
-
- if not tagged:
- if interface['config_id'] in untagged_ifaces:
- raise InvalidVlanConfigurationException("More than one untagged vlan on an interface")
- untagged_ifaces.add(interface['config_id'])
-
- # add connection to interface
- interface['connections'].append({"tagged": tagged, "network": network['id']})
-
- return hosts, interfaces, networks
-
-
-class Resource_Meta_Info(WorkflowStep):
- template = 'resource/steps/meta_info.html'
- title = "Extra Info"
- description = "Please fill out the rest of the information about your resource"
- short_title = "pod info"
-
- def update_confirmation(self):
- confirm = self.repo_get(self.repo.CONFIRMATION, {})
- if "template" not in confirm:
- confirm['template'] = {}
- models = self.repo_get(self.repo.RESOURCE_TEMPLATE_MODELS, {})
- if "template" in models:
- confirm['template']['description'] = models['template'].description
- confirm['template']['name'] = models['template'].name
- self.repo_put(self.repo.CONFIRMATION, confirm)
-
- def get_context(self):
- context = super(Resource_Meta_Info, self).get_context()
- name = ""
- desc = ""
- models = self.repo_get(self.repo.RESOURCE_TEMPLATE_MODELS, None)
- bundle = models['template']
- if bundle:
- name = bundle.name
- desc = bundle.description
- context['form'] = ResourceMetaForm(initial={"bundle_name": name, "bundle_description": desc})
- return context
-
- def post(self, post_data, user):
- form = ResourceMetaForm(post_data)
- if form.is_valid():
- models = self.repo_get(self.repo.RESOURCE_TEMPLATE_MODELS, {})
- name = form.cleaned_data['bundle_name']
- desc = form.cleaned_data['bundle_description']
- bundle = models['template'] # infallible
- bundle.name = name
- bundle.description = desc
- bundle.save()
- self.repo_put(self.repo.RESOURCE_TEMPLATE_MODELS, models)
- confirm = self.repo_get(self.repo.CONFIRMATION)
- if "resource" not in confirm:
- confirm['resource'] = {}
- confirm_info = confirm['resource']
- confirm_info["name"] = name
- tmp = desc
- if len(tmp) > 60:
- tmp = tmp[:60] + "..."
- confirm_info["description"] = tmp
- self.repo_put(self.repo.CONFIRMATION, confirm)
- self.set_valid("Step Completed")
- else:
- self.set_invalid("Please complete all fields.")
diff --git a/src/workflow/snapshot_workflow.py b/src/workflow/snapshot_workflow.py
deleted file mode 100644
index c0e2052..0000000
--- a/src/workflow/snapshot_workflow.py
+++ /dev/null
@@ -1,116 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-
-from django.utils import timezone
-import json
-
-from booking.models import Booking
-from resource_inventory.models import ResourceQuery, Image
-from workflow.models import WorkflowStep
-from workflow.forms import BasicMetaForm, SnapshotHostSelectForm
-
-
-class Select_Host_Step(WorkflowStep):
- template = "snapshot_workflow/steps/select_host.html"
- title = "Select Host"
- description = "Choose which machine you want to snapshot"
- short_title = "host"
-
- def get_context(self):
- context = super(Select_Host_Step, self).get_context()
- context['form'] = SnapshotHostSelectForm()
- booking_hosts = {}
- now = timezone.now()
- user = self.repo_get(self.repo.SESSION_USER)
- bookings = Booking.objects.filter(start__lt=now, end__gt=now, owner=user)
- for booking in bookings:
- booking_hosts[booking.id] = {}
- booking_hosts[booking.id]['purpose'] = booking.purpose
- booking_hosts[booking.id]['start'] = booking.start.strftime("%Y-%m-%d")
- booking_hosts[booking.id]['end'] = booking.end.strftime("%Y-%m-%d")
- booking_hosts[booking.id]['hosts'] = []
- for genericHost in booking.resource.template.getResources():
- booking_hosts[booking.id]['hosts'].append({"name": genericHost.resource.name})
-
- context['booking_hosts'] = booking_hosts
-
- chosen_host = self.repo_get(self.repo.SNAPSHOT_MODELS, {}).get("host")
- if chosen_host:
- chosen = {}
- chosen['booking_id'] = self.repo_get(self.repo.SNAPSHOT_BOOKING_ID)
- chosen['hostname'] = chosen_host.template.resource.name
- context['chosen'] = chosen
- return context
-
- def post(self, post_data, user):
- host_data = post_data.get("host")
- if not host_data:
- self.set_invalid("Please select a host")
- return
- host = json.loads(host_data)
- if 'name' not in host or 'booking' not in host:
- self.set_invalid("Invalid host selected")
- return
- name = host['name']
- booking_id = host['booking']
- booking = Booking.objects.get(pk=booking_id)
- host = ResourceQuery.get(bundle=booking.resource, template__resource__name=name)
- models = self.repo_get(self.repo.SNAPSHOT_MODELS, {})
- if "host" not in models:
- models['host'] = host
- if 'snapshot' not in models:
- models['snapshot'] = Image()
- self.repo_put(self.repo.SNAPSHOT_MODELS, models)
- self.repo_put(self.repo.SNAPSHOT_BOOKING_ID, booking_id)
-
- confirm = self.repo_get(self.repo.CONFIRMATION, {})
- snap_confirm = confirm.get("snapshot", {})
- snap_confirm['host'] = name
- confirm['snapshot'] = snap_confirm
- self.repo_put(self.repo.CONFIRMATION, confirm)
- self.set_valid("Success")
-
-
-class Image_Meta_Step(WorkflowStep):
- template = "snapshot_workflow/steps/meta.html"
- title = "Additional Information"
- description = "We need some more info"
- short_title = "info"
-
- def get_context(self):
- context = super(Image_Meta_Step, self).get_context()
- name = self.repo_get(self.repo.SNAPSHOT_NAME, False)
- desc = self.repo_get(self.repo.SNAPSHOT_DESC, False)
- form = None
- if name and desc:
- form = BasicMetaForm(initial={"name": name, "description": desc})
- else:
- form = BasicMetaForm()
- context['form'] = form
- return context
-
- def post(self, post_data, user):
- form = BasicMetaForm(post_data)
- if form.is_valid():
- name = form.cleaned_data['name']
- self.repo_put(self.repo.SNAPSHOT_NAME, name)
- description = form.cleaned_data['description']
- self.repo_put(self.repo.SNAPSHOT_DESC, description)
-
- confirm = self.repo_get(self.repo.CONFIRMATION, {})
- snap_confirm = confirm.get("snapshot", {})
- snap_confirm['name'] = name
- snap_confirm['description'] = description
- confirm['snapshot'] = snap_confirm
- self.repo_put(self.repo.CONFIRMATION, confirm)
-
- self.set_valid("Success")
- else:
- self.set_invalid("Please Fill out the Form")
diff --git a/src/workflow/tests/__init__.py b/src/workflow/tests/__init__.py
deleted file mode 100644
index 4f0437d..0000000
--- a/src/workflow/tests/__init__.py
+++ /dev/null
@@ -1,8 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
diff --git a/src/workflow/tests/constants.py b/src/workflow/tests/constants.py
deleted file mode 100644
index f94a949..0000000
--- a/src/workflow/tests/constants.py
+++ /dev/null
@@ -1,198 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-POD_XML = """
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-"""
diff --git a/src/workflow/tests/test_fixtures.py b/src/workflow/tests/test_fixtures.py
deleted file mode 100644
index fe16be7..0000000
--- a/src/workflow/tests/test_fixtures.py
+++ /dev/null
@@ -1,2 +0,0 @@
-
-MX_GRAPH_MODEL = ' '
diff --git a/src/workflow/tests/test_steps.py b/src/workflow/tests/test_steps.py
deleted file mode 100644
index ba27313..0000000
--- a/src/workflow/tests/test_steps.py
+++ /dev/null
@@ -1,269 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-"""
-This file tests basic functionality of each step class.
-
-More in depth case coverage of WorkflowStep.post() must happen elsewhere.
-"""
-
-import json
-from unittest import SkipTest, mock
-
-from django.test import TestCase, RequestFactory
-from dashboard.testing_utils import make_lab, make_user, make_os, \
- make_complete_host_profile, make_opnfv_role, make_image, make_grb, \
- make_config_bundle, make_host, make_user_profile, make_generic_host
-from workflow import resource_bundle_workflow
-from workflow import booking_workflow
-from workflow import sw_bundle_workflow
-from workflow.models import Repository
-from workflow.tests import test_fixtures
-
-
-class TestConfig:
- """
- Basic class to instantiate and hold reference.
-
- to models we will need often
- """
-
- def __init__(self, usr=None):
- self.lab = make_lab()
- self.user = usr or make_user()
- self.os = make_os()
- self.host_prof = make_complete_host_profile(self.lab)
- self.host = make_host(self.host_prof, self.lab, name="host1")
-
- # pod description as required by testing lib
- self.topology = {
- "host1": {
- "type": self.host_prof,
- "role": make_opnfv_role(),
- "image": make_image(self.lab, 3, self.user, self.os, self.host_prof),
- "nets": [
- [{"name": "public", "tagged": True, "public": True}]
- ]
- }
- }
- self.grb = make_grb(self.topology, self.user, self.lab)[0]
- self.generic_host = make_generic_host(self.grb, self.host_prof, "host1")
-
-
-class StepTestCase(TestCase):
-
- # after setUp is called, this should be an instance of a step
- step = None
-
- post_data = {} # subclasses will set this
-
- @classmethod
- def setUpTestData(cls):
- super().setUpTestData()
- cls.factory = RequestFactory()
- cls.user_prof = make_user_profile()
- cls.user = cls.user_prof.user
-
- def setUp(self):
- super().setUp()
- if self.step is None:
- raise SkipTest("Step instance not given")
- repo = Repository()
- self.add_to_repo(repo)
- self.step = self.step(1, repo)
-
- def assertCorrectPostBehavior(self, post_data):
- """
- Stub for validating step behavior on POST request.
-
- allows subclasses to override and make assertions about
- the side effects of self.step.post()
- post_data is the data passed into post()
- """
- return
-
- def add_to_repo(self, repo):
- """
- Stub for modifying the step's repo.
-
- This method is a hook that allows subclasses to modify
- the contents of the repo before the step is created.
- """
- return
-
- def assertValidHtml(self, html_str):
- """
- Assert that html_str is a valid html fragment.
-
- However, I know of no good way of doing this in python
- """
- self.assertTrue(isinstance(html_str, str))
- self.assertGreater(len(html_str), 0)
-
- def test_render_to_string(self):
- request = self.factory.get("/workflow/manager/")
- request.user = self.user
- response_html = self.step.render_to_string(request)
- self.assertValidHtml(response_html)
-
- def test_post(self, data=None):
- post_data = data or self.post_data
- self.step.post(post_data, self.user)
- self.assertCorrectPostBehavior(data)
-
-
-class SelectStepTestCase(StepTestCase):
- # ID of model to be sent to the step's form
- # can be an int or a list of ints
- obj_id = -1
-
- def setUp(self):
- super().setUp()
-
- try:
- iter(self.obj_id)
- except TypeError:
- self.obj_id = [self.obj_id]
-
- field_data = json.dumps(self.obj_id)
- self.post_data = {
- "searchable_select": [field_data]
- }
-
-
-class DefineHardwareTestCase(StepTestCase):
- step = resource_bundle_workflow.Define_Hardware
- post_data = {
- "filter_field": {
- "lab": {
- "lab_35": {"selected": True, "id": 35}},
- "host": {
- "host_1": {"selected": True, "id": 1}}
- }
- }
-
-
-class DefineNetworkTestCase(StepTestCase):
- step = resource_bundle_workflow.Define_Nets
- post_data = {"xml": test_fixtures.MX_GRAPH_MODEL}
-
-
-class ResourceMetaTestCase(StepTestCase):
- step = resource_bundle_workflow.Resource_Meta_Info
- post_data = {
- "bundle_name": "my_bundle",
- "bundle_description": "My Bundle"
- }
-
-
-class BookingResourceTestCase(SelectStepTestCase):
- step = booking_workflow.Booking_Resource_Select
-
- def add_to_repo(self, repo):
- repo.el[repo.SESSION_USER] = self.user
-
- @classmethod
- def setUpTestData(cls):
- super().setUpTestData()
- conf = TestConfig(usr=cls.user)
- cls.obj_id = conf.grb.id
-
-
-class SoftwareSelectTestCase(SelectStepTestCase):
- step = booking_workflow.SWConfig_Select
-
- def add_to_repo(self, repo):
- repo.el[repo.SESSION_USER] = self.user
- repo.el[repo.SELECTED_RESOURCE_TEMPLATE] = self.conf.grb
-
- @classmethod
- def setUpTestData(cls):
- super().setUpTestData()
- cls.conf = TestConfig(usr=cls.user)
- host_map = {"host1": cls.conf.generic_host}
- config_bundle = make_config_bundle(cls.conf.grb, cls.conf.user, cls.conf.topology, host_map)[0]
- cls.obj_id = config_bundle.id
-
-
-class OPNFVSelectTestCase(SelectStepTestCase):
- step = booking_workflow.OPNFV_Select
-
- def add_to_repo(self, repo):
- repo.el[repo.SELECTED_CONFIG_BUNDLE] = self.config_bundle
-
- @classmethod
- def setUpTestData(cls):
- super().setUpTestData()
- conf = TestConfig(usr=cls.user)
- host_map = {"host1": conf.generic_host}
- cls.config_bundle, opnfv_config = make_config_bundle(conf.grb, conf.user, conf.topology, host_map)
- cls.obj_id = opnfv_config.id
-
-
-class BookingMetaTestCase(StepTestCase):
- step = booking_workflow.Booking_Meta
- post_data = {
- "length": 14,
- "purpose": "Testing",
- "project": "Lab as a Service",
- "users": ["[-1]"]
- }
-
- def add_to_repo(self, repo):
- repo.el[repo.SESSION_MANAGER] = mock.MagicMock()
-
- @classmethod
- def setUpTestData(cls):
- super().setUpTestData()
- new_user = make_user(username="collaborator", email="different@mail.com")
- new_user_prof = make_user_profile(user=new_user)
- data = "[" + str(new_user_prof.id) + "]" # list of IDs
- cls.post_data['users'] = [data]
-
-
-class ConfigResourceSelectTestCase(SelectStepTestCase):
- step = sw_bundle_workflow.SWConf_Resource_Select
-
- def add_to_repo(self, repo):
- repo.el[repo.SESSION_USER] = self.user
-
- @classmethod
- def setUpTestData(cls):
- super().setUpTestData()
- conf = TestConfig(usr=cls.user)
- cls.obj_id = conf.grb.id
-
-
-class DefineSoftwareTestCase(StepTestCase):
- step = sw_bundle_workflow.Define_Software
- post_data = {
- "form-0-image": 1,
- "headnode": 1,
- "form-0-headnode": "",
- "form-TOTAL_FORMS": 1,
- "form-INITIAL_FORMS": 1,
- "form-MIN_NUM_FORMS": 0,
- "form-MAX_NUM_FORMS": 1000,
- }
-
- def add_to_repo(self, repo):
- repo.el[repo.SELECTED_RESOURCE_TEMPLATE] = self.conf.grb
-
- @classmethod
- def setUpTestData(cls):
- super().setUpTestData()
- cls.conf = TestConfig(usr=cls.user)
-
-
-class ConfigSoftwareTestCase(StepTestCase):
- step = sw_bundle_workflow.Config_Software
- post_data = {
- "name": "config_bundle",
- "description": "My Config Bundle"
- }
diff --git a/src/workflow/tests/test_workflows.py b/src/workflow/tests/test_workflows.py
deleted file mode 100644
index 995d699..0000000
--- a/src/workflow/tests/test_workflows.py
+++ /dev/null
@@ -1,99 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-from unittest import SkipTest
-from django.test import TestCase
-from workflow.workflow_factory import WorkflowFactory
-
-
-"""
-To start a workflow:
- POST to /wf/workflow {"add":
-
- types:
- 0 - Booking
- 1 - Resource
- 2 - Config
-
-To remove a workflow:
- POST to /wf/workflow {"cancel": ""}
-"""
-
-
-class WorkflowTestCase(TestCase):
-
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- raise SkipTest("These tests are no good")
-
- def setUp(self):
- self.clear_workflow()
- self.create_workflow(self.wf_type)
-
- def create_workflow(self, wf_type):
- self.clear_workflow()
-
- # creates workflow on backend
- self.client.post("/", {"create": int(wf_type)}) # TODO: verify content type, etc
-
- def clear_workflow(self):
- session = self.client.session
- for k in session.keys():
- del session[k]
- session.save()
-
- def render_steps(self):
- """Retrieve each step individually at /wf/workflow/step=."""
- for i in range(self.step_count):
- # renders the step itself, not in an iframe
- exception = None
- try:
- response = self.client.get("/wf/workflow/", {"step": str(i)})
- self.assertLess(response.status_code, 300)
- except Exception as e:
- exception = e
-
- self.assertIsNone(exception)
-
-
-class BookingWorkflowTestCase(WorkflowTestCase):
-
- @classmethod
- def setUpClass(cls):
- super(BookingWorkflowTestCase, cls).setUpClass()
- cls.step_count = len(WorkflowFactory.booking_steps)
- cls.wf_type = 0
-
- def test_steps_render(self):
- super(BookingWorkflowTestCase, self).render_steps()
-
-
-class ResourceWorkflowTestCase(WorkflowTestCase):
-
- @classmethod
- def setUpClass(cls):
- super(ResourceWorkflowTestCase, cls).setUpClass()
- cls.step_count = len(WorkflowFactory.resource_steps)
- cls.wf_type = 1
-
- def test_steps_render(self):
- super(ResourceWorkflowTestCase, self).render_steps()
-
-
-class ConfigWorkflowTestCase(WorkflowTestCase):
-
- @classmethod
- def setUpClass(cls):
- super(ConfigWorkflowTestCase, cls).setUpClass()
- cls.step_count = len(WorkflowFactory.config_steps)
- cls.wf_type = 2
-
- def test_steps_render(self):
- super(ConfigWorkflowTestCase, self).render_steps()
diff --git a/src/workflow/urls.py b/src/workflow/urls.py
deleted file mode 100644
index b1b95a7..0000000
--- a/src/workflow/urls.py
+++ /dev/null
@@ -1,23 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-
-from django.conf.urls import url
-
-from workflow.views import manager_view, viewport_view, add_workflow, remove_workflow, create_workflow
-
-app_name = 'workflow'
-urlpatterns = [
-
- url(r'^manager/$', manager_view, name='manager'),
- url(r'^add/$', add_workflow, name='add_workflow'),
- url(r'^create/$', create_workflow, name='create_workflow'),
- url(r'^pop/$', remove_workflow, name='remove_workflow'),
- url(r'^$', viewport_view, name='viewport')
-]
diff --git a/src/workflow/views.py b/src/workflow/views.py
deleted file mode 100644
index fb311b7..0000000
--- a/src/workflow/views.py
+++ /dev/null
@@ -1,112 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-
-from django.http import HttpResponse
-from django.shortcuts import render
-from account.models import Lab
-
-import uuid
-
-from workflow.workflow_manager import ManagerTracker, SessionManager
-
-import logging
-logger = logging.getLogger(__name__)
-
-
-def attempt_auth(request):
- try:
- manager = ManagerTracker.managers[request.session['manager_session']]
-
- return manager
-
- except KeyError:
- return None
-
-
-def remove_workflow(request):
- manager = attempt_auth(request)
-
- if not manager:
- return no_workflow(request)
-
- has_more_workflows, result = manager.pop_workflow(discard=True)
-
- if not has_more_workflows: # this was the last workflow, so delete the reference to it in the tracker
- del ManagerTracker.managers[request.session['manager_session']]
- return manager.render(request)
-
-
-def add_workflow(request):
- manager = attempt_auth(request)
- if not manager:
- return no_workflow(request)
- try:
- workflow_type = int(request.POST.get('workflow_type'))
- except ValueError:
- return HttpResponse(status=400)
-
- manager.add_workflow(workflow_type=workflow_type)
- return manager.render(request) # do we want this?
-
-
-def manager_view(request):
- manager = attempt_auth(request)
- if not manager:
- return no_workflow(request)
-
- return manager.handle_request(request)
-
-
-def viewport_view(request):
- if not request.user.is_authenticated:
- return login(request)
-
- manager = attempt_auth(request)
- if manager is None:
- return no_workflow(request)
-
- if request.method != 'GET':
- return HttpResponse(status=405)
-
- context = {
- 'contact_email': Lab.objects.get(name="UNH_IOL").contact_email
- }
-
- return render(request, 'workflow/viewport-base.html', context)
-
-
-def create_workflow(request):
- if request.method != 'POST':
- return HttpResponse(status=405)
- workflow_type = request.POST.get('workflow_type')
- try:
- workflow_type = int(workflow_type)
- except Exception:
- return HttpResponse(status=400)
- mgr_uuid = create_session(workflow_type, request=request,)
- request.session['manager_session'] = mgr_uuid
- return HttpResponse()
-
-
-def create_session(wf_type, request):
- smgr = SessionManager(request=request)
- smgr.add_workflow(workflow_type=wf_type, target_id=request.POST.get("target"))
- manager_uuid = uuid.uuid4().hex
- ManagerTracker.getInstance().managers[manager_uuid] = smgr
-
- return manager_uuid
-
-
-def no_workflow(request):
- return render(request, 'workflow/no_workflow.html', {'title': "Not Found"}, status=404)
-
-
-def login(request):
- return render(request, "dashboard/login.html", {'title': 'Authentication Required'})
diff --git a/src/workflow/workflow_factory.py b/src/workflow/workflow_factory.py
deleted file mode 100644
index e688510..0000000
--- a/src/workflow/workflow_factory.py
+++ /dev/null
@@ -1,126 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, Sean Smith, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-
-from workflow.booking_workflow import Booking_Resource_Select, Booking_Meta, OPNFV_Select
-from workflow.resource_bundle_workflow import Define_Hardware, Define_Nets, Resource_Meta_Info, Define_Software
-from workflow.snapshot_workflow import Select_Host_Step, Image_Meta_Step
-from workflow.opnfv_workflow import Pick_Installer, Assign_Network_Roles, Assign_Host_Roles, OPNFV_Resource_Select, MetaInfo
-from workflow.models import Confirmation_Step
-
-import uuid
-
-import logging
-logger = logging.getLogger(__name__)
-
-
-class MetaStep(object):
-
- UNTOUCHED = 0
- INVALID = 100
- VALID = 200
-
- def set_invalid(self, message, code=100):
- self.valid = code
- self.message = message
-
- def set_valid(self, message, code=200):
- self.valid = code
- self.message = message
-
- def __init__(self, *args, **kwargs):
- self.short_title = "error"
- self.skip_step = 0
- self.valid = 0
- self.hidden = False
- self.message = ""
- self.id = uuid.uuid4()
-
- def to_json(self):
- return {
- 'title': self.short_title,
- 'skip': self.skip_step,
- 'valid': self.valid,
- 'message': self.message,
- }
-
- def __str__(self):
- return "metastep: " + str(self.short_title)
-
- def __hash__(self):
- return hash(self.id)
-
- def __eq__(self, other):
- return self.id.int == other.id.int
-
- def __ne__(self, other):
- return self.id.int != other.id.int
-
-
-class Workflow(object):
- def __init__(self, steps, repository):
- self.repository = repository
- self.steps = steps
- self.active_index = 0
-
-
-class WorkflowFactory():
- booking_steps = [
- Booking_Resource_Select,
- Booking_Meta,
- OPNFV_Select,
- ]
-
- resource_steps = [
- Define_Hardware,
- Define_Software,
- Define_Nets,
- Resource_Meta_Info,
- ]
-
- snapshot_steps = [
- Select_Host_Step,
- Image_Meta_Step,
- ]
-
- opnfv_steps = [
- OPNFV_Resource_Select,
- Pick_Installer,
- Assign_Network_Roles,
- Assign_Host_Roles,
- MetaInfo
- ]
-
- def conjure(self, workflow_type=None, repo=None):
- workflow_types = [
- self.booking_steps,
- self.resource_steps,
- self.snapshot_steps,
- self.opnfv_steps,
- ]
-
- steps = self.make_steps(workflow_types[workflow_type], repository=repo)
- return steps
-
- def create_workflow(self, workflow_type=None, repo=None):
- steps = self.conjure(workflow_type, repo)
- c_step = self.make_step(Confirmation_Step, repo)
- steps.append(c_step)
- return Workflow(steps, repo)
-
- def make_steps(self, step_types, repository):
- steps = []
- for step_type in step_types:
- steps.append(self.make_step(step_type, repository))
-
- return steps
-
- def make_step(self, step_type, repository):
- iden = step_type.description + step_type.title + step_type.template
- return step_type(iden, repository)
diff --git a/src/workflow/workflow_manager.py b/src/workflow/workflow_manager.py
deleted file mode 100644
index 40be9d6..0000000
--- a/src/workflow/workflow_manager.py
+++ /dev/null
@@ -1,270 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Sawyer Bergeron, Parker Berberian, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-
-from django.http import JsonResponse
-from django.http.request import QueryDict
-from django.urls import reverse
-
-from booking.models import Booking
-from workflow.workflow_factory import WorkflowFactory
-from workflow.models import Repository
-from resource_inventory.models import (
- ResourceTemplate,
- ResourceConfiguration,
- OPNFVConfig
-)
-from workflow.forms import ManagerForm
-
-import logging
-logger = logging.getLogger(__name__)
-
-
-class SessionManager():
- def active_workflow(self):
- return self.workflows[-1]
-
- def __init__(self, request=None):
- self.workflows = []
- self.owner = request.user
- self.factory = WorkflowFactory()
- self.result = None
-
- def set_step_statuses(self, superclass_type, desired_enabled=True):
- workflow = self.active_workflow()
- steps = workflow.steps
- for step in steps:
- if isinstance(step, superclass_type):
- if desired_enabled:
- step.enable()
- else:
- step.disable()
-
- def add_workflow(self, workflow_type=None, **kwargs):
- repo = Repository()
- if (len(self.workflows) >= 1):
- defaults = self.workflows[-1].repository.get_child_defaults()
- repo.set_defaults(defaults)
- repo.el[repo.HAS_RESULT] = False
- repo.el[repo.SESSION_USER] = self.owner
- repo.el[repo.SESSION_MANAGER] = self
- self.workflows.append(
- self.factory.create_workflow(
- workflow_type=workflow_type,
- repo=repo
- )
- )
-
- def get_redirect(self):
- if isinstance(self.result, Booking):
- return reverse('booking:booking_detail', kwargs={'booking_id': self.result.id})
- return "/"
-
- def pop_workflow(self, discard=False):
- multiple_wfs = len(self.workflows) > 1
- if multiple_wfs:
- if self.workflows[-1].repository.el[Repository.RESULT]: # move result
- key = self.workflows[-1].repository.el[Repository.RESULT_KEY]
- result = self.workflows[-1].repository.el[Repository.RESULT]
- self.workflows[-2].repository.el[key] = result
- prev_workflow = self.workflows.pop()
- if self.workflows:
- current_repo = self.workflows[-1].repository
- else:
- current_repo = prev_workflow.repository
- self.result = current_repo.el[current_repo.RESULT]
- if discard:
- current_repo.cancel()
- return multiple_wfs, self.result
-
- def status(self, request):
- return {
- "steps": [step.to_json() for step in self.active_workflow().steps],
- "active": self.active_workflow().repository.el['active_step'],
- "workflow_count": len(self.workflows)
- }
-
- def handle_post(self, request):
- form = ManagerForm(request.POST)
- if form.is_valid():
- self.get_active_step().post(
- QueryDict(form.cleaned_data['step_form']),
- user=request.user
- )
- # change step
- if form.cleaned_data['step'] == 'prev':
- self.go_prev()
- if form.cleaned_data['step'] == 'next':
- self.go_next()
- else:
- pass # Exception?
-
- def handle_request(self, request):
- if request.method == 'POST':
- self.handle_post(request)
- return self.render(request)
-
- def render(self, request, **kwargs):
- if self.workflows:
- return JsonResponse({
- "meta": self.status(request),
- "content": self.get_active_step().render_to_string(request),
- })
- else:
- return JsonResponse({
- "redirect": self.get_redirect()
- })
-
- def post_render(self, request):
- return self.active_workflow().steps[self.active_workflow().active_index].post_render(request)
-
- def get_active_step(self):
- return self.active_workflow().steps[self.active_workflow().active_index]
-
- def go_next(self, **kwargs):
- # need to verify current step is valid to allow this
- if self.get_active_step().valid < 200:
- return
- next_step = self.active_workflow().active_index + 1
- if next_step >= len(self.active_workflow().steps):
- raise Exception("Out of bounds request for step")
- while not self.active_workflow().steps[next_step].enabled:
- next_step += 1
- self.active_workflow().repository.el['active_step'] = next_step
- self.active_workflow().active_index = next_step
-
- def go_prev(self, **kwargs):
- prev_step = self.active_workflow().active_index - 1
- if prev_step < 0:
- raise Exception("Out of bounds request for step")
- while not self.active_workflow().steps[prev_step].enabled:
- prev_step -= 1
- self.active_workflow().repository.el['active_step'] = prev_step
- self.active_workflow().active_index = prev_step
-
- def prefill_repo(self, target_id, workflow_type):
- self.repository.el[self.repository.EDIT] = True
- edit_object = None
- if workflow_type == 0:
- edit_object = Booking.objects.get(pk=target_id)
- self.prefill_booking(edit_object)
- elif workflow_type == 1:
- edit_object = ResourceTemplate.objects.get(pk=target_id)
- self.prefill_resource(edit_object)
- elif workflow_type == 2:
- edit_object = ResourceTemplate.objects.get(pk=target_id)
- self.prefill_config(edit_object)
-
- def prefill_booking(self, booking):
- models = self.make_booking_models(booking)
- confirmation = self.make_booking_confirm(booking)
- self.active_workflow().repository.el[self.active_workflow().repository.BOOKING_MODELS] = models
- self.active_workflow().repository.el[self.active_workflow().repository.CONFIRMATION] = confirmation
- self.active_workflow().repository.el[self.active_workflow().repository.RESOURCE_TEMPLATE_MODELS] = self.make_grb_models(booking.resource.template)
- self.active_workflow().repository.el[self.active_workflow().repository.SELECTED_RESOURCE_TEMPLATE] = self.make_grb_models(booking.resource.template)['bundle']
- self.active_workflow().repository.el[self.active_workflow().repository.CONFIG_MODELS] = self.make_config_models(booking.config_bundle)
-
- def prefill_resource(self, resource):
- models = self.make_grb_models(resource)
- confirm = self.make_grb_confirm(resource)
- self.active_workflow().repository.el[self.active_workflow().repository.RESOURCE_TEMPLATE_MODELS] = models
- self.active_workflow().repository.el[self.active_workflow().repository.CONFIRMATION] = confirm
-
- def prefill_config(self, config):
- models = self.make_config_models(config)
- confirm = self.make_config_confirm(config)
- self.active_workflow().repository.el[self.active_workflow().repository.CONFIG_MODELS] = models
- self.active_workflow().repository.el[self.active_workflow().repository.CONFIRMATION] = confirm
- grb_models = self.make_grb_models(config.bundle)
- self.active_workflow().repository.el[self.active_workflow().repository.RESOURCE_TEMPLATE_MODELS] = grb_models
-
- def make_grb_models(self, resource):
- models = self.active_workflow().repository.el.get(self.active_workflow().repository.RESOURCE_TEMPLATE_MODELS, {})
- models['hosts'] = []
- models['bundle'] = resource
- models['interfaces'] = {}
- models['vlans'] = {}
- for host in resource.getResources():
- models['hosts'].append(host)
- models['interfaces'][host.resource.name] = []
- models['vlans'][host.resource.name] = {}
- for interface in host.generic_interfaces.all():
- models['interfaces'][host.resource.name].append(interface)
- models['vlans'][host.resource.name][interface.profile.name] = []
- for vlan in interface.vlans.all():
- models['vlans'][host.resource.name][interface.profile.name].append(vlan)
- return models
-
- def make_grb_confirm(self, resource):
- confirm = self.active_workflow().repository.el.get(self.active_workflow().repository.CONFIRMATION, {})
- confirm['resource'] = {}
- confirm['resource']['hosts'] = []
- confirm['resource']['lab'] = resource.lab.lab_user.username
- for host in resource.getResources():
- confirm['resource']['hosts'].append({"name": host.resource.name, "profile": host.profile.name})
- return confirm
-
- def make_config_models(self, config):
- models = self.active_workflow().repository.el.get(self.active_workflow().repository.CONFIG_MODELS, {})
- models['bundle'] = config
- models['host_configs'] = []
- for host_conf in ResourceConfiguration.objects.filter(bundle=config):
- models['host_configs'].append(host_conf)
- models['opnfv'] = OPNFVConfig.objects.filter(bundle=config).last()
- return models
-
- def make_config_confirm(self, config):
- confirm = self.active_workflow().repository.el.get(self.active_workflow().repository.CONFIRMATION, {})
- confirm['configuration'] = {}
- confirm['configuration']['hosts'] = []
- confirm['configuration']['name'] = config.name
- confirm['configuration']['description'] = config.description
- opnfv = OPNFVConfig.objects.filter(bundle=config).last()
- confirm['configuration']['installer'] = opnfv.installer.name
- confirm['configuration']['scenario'] = opnfv.scenario.name
- for host_conf in ResourceConfiguration.objects.filter(bundle=config):
- h = {"name": host_conf.host.resource.name, "image": host_conf.image.name, "role": host_conf.opnfvRole.name}
- confirm['configuration']['hosts'].append(h)
- return confirm
-
- def make_booking_models(self, booking):
- models = self.active_workflow().repository.el.get(self.active_workflow().repository.BOOKING_MODELS, {})
- models['booking'] = booking
- models['collaborators'] = []
- for user in booking.collaborators.all():
- models['collaborators'].append(user)
- return models
-
- def make_booking_confirm(self, booking):
- confirm = self.active_workflow().repository.el.get(self.active_workflow().repository.CONFIRMATION, {})
- confirm['booking'] = {}
- confirm['booking']['length'] = (booking.end - booking.start).days
- confirm['booking']['project'] = booking.project
- confirm['booking']['purpose'] = booking.purpose
- confirm['booking']['resource name'] = booking.resource.template.name
- confirm['booking']['configuration name'] = booking.config_bundle.name
- confirm['booking']['collaborators'] = []
- for user in booking.collaborators.all():
- confirm['booking']['collaborators'].append(user.username)
- return confirm
-
-
-class ManagerTracker():
- instance = None
-
- managers = {}
-
- def __init__(self):
- pass
-
- @staticmethod
- def getInstance():
- if ManagerTracker.instance is None:
- ManagerTracker.instance = ManagerTracker()
- return ManagerTracker.instance
diff --git a/test.sh b/test.sh
deleted file mode 100755
index 91d0e4c..0000000
--- a/test.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-##############################################################################
-# Copyright (c) 2018 Parker Berberian, Sawyer Bergeron, and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-# first, basic lint with flake8
-find . -type f -name "*.py" -not -name "manage.py" -not -path "*/migrations/*" | xargs flake8 --count
-
-# this file should be executed from the dir it is in
-docker exec -it dg01 python manage.py test
diff --git a/tests/README.txt b/tests/README.txt
deleted file mode 100644
index 4085be7..0000000
--- a/tests/README.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-This folder contains the tools needed to unit test the frontend
-JavaScript files using Karma, Mocha, and Chai.
-
-
-Getting started:
-Install NPM if you haven't:
-https://nodejs.org/en/download/package-manager/
-
-Run 'npm install' to install all required dependencies in this
-folder.
-
-Run 'npm test' to run current unit tests.
-
-
-Adding tests:
-Tests are located in the tests/ folder, you can simply edit the
-existing ones or create a new one by making a file with the .js
-file extension.
-
-Karma is used for launching different browsers to run JavaScript.
-See Karma documentation at https://karma-runner.github.io/
-to add more browsers, files to test, or frameworks.
-
-Mocha is used for the structure of the JavaScript testing itself.
-See Mocha documentation at https://mochajs.org/ to see the syntax
-required to create/modify tests. Currently, the tests use the
-'TDD' interface from Mocha.
-
-Chai is used for the actual testing, with it being an assertion
-library. See Chai documentation at https://www.chaijs.com/ to see
-the available usages for assertion. The tests use the 'assert' API
-along with Mocha's TDD interface.
diff --git a/tests/karma.conf.js b/tests/karma.conf.js
deleted file mode 100644
index 3a577d4..0000000
--- a/tests/karma.conf.js
+++ /dev/null
@@ -1,87 +0,0 @@
-// Karma configuration
-// Generated on Mon Jul 08 2019 14:57:05 GMT-0400 (Eastern Daylight Time)
-
-module.exports = function(config) {
- config.set({
-
- // base path that will be used to resolve all patterns (eg. files, exclude)
- basePath: '',
-
-
- // frameworks to use
- // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
- frameworks: ['mocha', 'chai'],
-
-
- // list of files / patterns to load in the browser
- files: [
- 'https://code.jquery.com/jquery-3.4.1.min.js',
- '../src/static/js/dashboard.js',
- '../src/static/node_modules/mxgraph/javascript/mxClient.min.js',
- 'tests/*.js'
- ],
-
-
- // list of files / patterns to exclude
- exclude: [
- ],
-
-
- // preprocess matching files before serving them to the browser
- // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
- preprocessors: {
- },
-
-
- // test results reporter to use
- // possible values: 'dots', 'progress'
- // available reporters: https://npmjs.org/browse/keyword/karma-reporter
- reporters: ['dots'],
-
-
- // web server port
- port: 9876,
-
-
- // enable / disable colors in the output (reporters and logs)
- colors: true,
-
-
- // level of logging
- // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
- logLevel: config.LOG_ERROR,
-
-
- // enable / disable watching file and executing tests whenever any file changes
- autoWatch: false,
-
-
- // start these browsers
- // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
- browsers: ['ChromeHeadless', 'FirefoxHeadless'],
-
-
- // Continuous Integration mode
- // if true, Karma captures browsers, runs the tests and exits
- singleRun: true,
-
- // Concurrency level
- // how many browser should be started simultaneous
- concurrency: Infinity,
-
- // Custom web browsers
- customLaunchers: {
- FirefoxHeadless: {
- base: 'Firefox',
- flags: ['-headless']
- }
- },
-
- // Use TDD instead of BDD for Mocha
- client: {
- mocha: {
- ui: 'tdd'
- }
- }
- })
-}
diff --git a/tests/package-lock.json b/tests/package-lock.json
deleted file mode 100644
index a7ccbf5..0000000
--- a/tests/package-lock.json
+++ /dev/null
@@ -1,3443 +0,0 @@
-{
- "name": "tests",
- "version": "1.0.0",
- "lockfileVersion": 1,
- "requires": true,
- "dependencies": {
- "accepts": {
- "version": "1.3.7",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
- "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
- "requires": {
- "mime-types": "~2.1.24",
- "negotiator": "0.6.2"
- }
- },
- "after": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
- "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8="
- },
- "ansi-colors": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
- "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw=="
- },
- "ansi-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
- "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
- },
- "ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "anymatch": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
- "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
- "requires": {
- "micromatch": "^3.1.4",
- "normalize-path": "^2.1.1"
- },
- "dependencies": {
- "normalize-path": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
- "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
- "requires": {
- "remove-trailing-separator": "^1.0.1"
- }
- }
- }
- },
- "argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "requires": {
- "sprintf-js": "~1.0.2"
- }
- },
- "arr-diff": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
- "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA="
- },
- "arr-flatten": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
- "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg=="
- },
- "arr-union": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
- "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ="
- },
- "array-unique": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
- "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
- },
- "arraybuffer.slice": {
- "version": "0.0.7",
- "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
- "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog=="
- },
- "assertion-error": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
- "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw=="
- },
- "assign-symbols": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
- "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
- },
- "async": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz",
- "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==",
- "requires": {
- "lodash": "^4.17.11"
- }
- },
- "async-each": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
- "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ=="
- },
- "async-limiter": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
- "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
- },
- "atob": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
- "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
- },
- "backo2": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
- "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
- },
- "balanced-match": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
- "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
- },
- "base": {
- "version": "0.11.2",
- "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
- "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
- "requires": {
- "cache-base": "^1.0.1",
- "class-utils": "^0.3.5",
- "component-emitter": "^1.2.1",
- "define-property": "^1.0.0",
- "isobject": "^3.0.1",
- "mixin-deep": "^1.2.0",
- "pascalcase": "^0.1.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- },
- "kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
- }
- }
- },
- "base64-arraybuffer": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
- "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg="
- },
- "base64id": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
- "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY="
- },
- "better-assert": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
- "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
- "requires": {
- "callsite": "1.0.0"
- }
- },
- "binary-extensions": {
- "version": "1.13.1",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
- "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw=="
- },
- "blob": {
- "version": "0.0.5",
- "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
- "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig=="
- },
- "bluebird": {
- "version": "3.5.5",
- "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
- "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w=="
- },
- "body-parser": {
- "version": "1.19.0",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
- "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
- "requires": {
- "bytes": "3.1.0",
- "content-type": "~1.0.4",
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "http-errors": "1.7.2",
- "iconv-lite": "0.4.24",
- "on-finished": "~2.3.0",
- "qs": "6.7.0",
- "raw-body": "2.4.0",
- "type-is": "~1.6.17"
- }
- },
- "brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "braces": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
- "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
- "requires": {
- "arr-flatten": "^1.1.0",
- "array-unique": "^0.3.2",
- "extend-shallow": "^2.0.1",
- "fill-range": "^4.0.0",
- "isobject": "^3.0.1",
- "repeat-element": "^1.1.2",
- "snapdragon": "^0.8.1",
- "snapdragon-node": "^2.0.1",
- "split-string": "^3.0.2",
- "to-regex": "^3.0.1"
- }
- },
- "browser-stdout": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
- "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
- },
- "buffer-alloc": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
- "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
- "requires": {
- "buffer-alloc-unsafe": "^1.1.0",
- "buffer-fill": "^1.0.0"
- }
- },
- "buffer-alloc-unsafe": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
- "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
- },
- "buffer-fill": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
- "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw="
- },
- "bytes": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
- "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
- },
- "cache-base": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
- "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
- "requires": {
- "collection-visit": "^1.0.0",
- "component-emitter": "^1.2.1",
- "get-value": "^2.0.6",
- "has-value": "^1.0.0",
- "isobject": "^3.0.1",
- "set-value": "^2.0.0",
- "to-object-path": "^0.3.0",
- "union-value": "^1.0.0",
- "unset-value": "^1.0.0"
- }
- },
- "callsite": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
- "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA="
- },
- "camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
- },
- "chai": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
- "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
- "requires": {
- "assertion-error": "^1.1.0",
- "check-error": "^1.0.2",
- "deep-eql": "^3.0.1",
- "get-func-name": "^2.0.0",
- "pathval": "^1.1.0",
- "type-detect": "^4.0.5"
- }
- },
- "chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "dependencies": {
- "supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "requires": {
- "has-flag": "^3.0.0"
- }
- }
- }
- },
- "check-error": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
- "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
- },
- "chokidar": {
- "version": "2.1.6",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.6.tgz",
- "integrity": "sha512-V2jUo67OKkc6ySiRpJrjlpJKl9kDuG+Xb8VgsGzb+aEouhgS1D0weyPU4lEzdAcsCAvrih2J2BqyXqHWvVLw5g==",
- "requires": {
- "anymatch": "^2.0.0",
- "async-each": "^1.0.1",
- "braces": "^2.3.2",
- "fsevents": "^1.2.7",
- "glob-parent": "^3.1.0",
- "inherits": "^2.0.3",
- "is-binary-path": "^1.0.0",
- "is-glob": "^4.0.0",
- "normalize-path": "^3.0.0",
- "path-is-absolute": "^1.0.0",
- "readdirp": "^2.2.1",
- "upath": "^1.1.1"
- }
- },
- "class-utils": {
- "version": "0.3.6",
- "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
- "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
- "requires": {
- "arr-union": "^3.1.0",
- "define-property": "^0.2.5",
- "isobject": "^3.0.0",
- "static-extend": "^0.1.1"
- }
- },
- "cliui": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
- "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
- "requires": {
- "string-width": "^2.1.1",
- "strip-ansi": "^4.0.0",
- "wrap-ansi": "^2.0.0"
- }
- },
- "code-point-at": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
- "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
- },
- "collection-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
- "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
- "requires": {
- "map-visit": "^1.0.0",
- "object-visit": "^1.0.0"
- }
- },
- "color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "requires": {
- "color-name": "1.1.3"
- }
- },
- "color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
- },
- "colors": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz",
- "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg=="
- },
- "component-bind": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
- "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E="
- },
- "component-emitter": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
- "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
- },
- "component-inherit": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
- "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM="
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
- },
- "connect": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
- "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
- "requires": {
- "debug": "2.6.9",
- "finalhandler": "1.1.2",
- "parseurl": "~1.3.3",
- "utils-merge": "1.0.1"
- }
- },
- "content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
- },
- "cookie": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
- "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
- },
- "copy-descriptor": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
- "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40="
- },
- "core-js": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz",
- "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A=="
- },
- "core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
- },
- "cross-spawn": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
- "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
- "requires": {
- "nice-try": "^1.0.4",
- "path-key": "^2.0.1",
- "semver": "^5.5.0",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- }
- },
- "custom-event": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
- "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU="
- },
- "date-format": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.0.0.tgz",
- "integrity": "sha512-M6UqVvZVgFYqZL1SfHsRGIQSz3ZL+qgbsV5Lp1Vj61LZVYuEwcMXYay7DRDtYs2HQQBK5hQtQ0fD9aEJ89V0LA=="
- },
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "requires": {
- "ms": "2.0.0"
- }
- },
- "decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
- },
- "decode-uri-component": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
- "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
- },
- "deep-eql": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
- "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
- "requires": {
- "type-detect": "^4.0.0"
- }
- },
- "define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
- "requires": {
- "object-keys": "^1.0.12"
- }
- },
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "depd": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
- "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
- },
- "di": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz",
- "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw="
- },
- "diff": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
- "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA=="
- },
- "dom-serialize": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz",
- "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=",
- "requires": {
- "custom-event": "~1.0.0",
- "ent": "~2.2.0",
- "extend": "^3.0.0",
- "void-elements": "^2.0.0"
- }
- },
- "ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
- },
- "emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
- "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
- },
- "encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
- },
- "end-of-stream": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
- "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
- "requires": {
- "once": "^1.4.0"
- }
- },
- "engine.io": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz",
- "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==",
- "requires": {
- "accepts": "~1.3.4",
- "base64id": "1.0.0",
- "cookie": "0.3.1",
- "debug": "~3.1.0",
- "engine.io-parser": "~2.1.0",
- "ws": "~3.3.1"
- },
- "dependencies": {
- "debug": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
- "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
- "requires": {
- "ms": "2.0.0"
- }
- }
- }
- },
- "engine.io-client": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz",
- "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==",
- "requires": {
- "component-emitter": "1.2.1",
- "component-inherit": "0.0.3",
- "debug": "~3.1.0",
- "engine.io-parser": "~2.1.1",
- "has-cors": "1.1.0",
- "indexof": "0.0.1",
- "parseqs": "0.0.5",
- "parseuri": "0.0.5",
- "ws": "~3.3.1",
- "xmlhttprequest-ssl": "~1.5.4",
- "yeast": "0.1.2"
- },
- "dependencies": {
- "component-emitter": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
- "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
- },
- "debug": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
- "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
- "requires": {
- "ms": "2.0.0"
- }
- }
- }
- },
- "engine.io-parser": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
- "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
- "requires": {
- "after": "0.8.2",
- "arraybuffer.slice": "~0.0.7",
- "base64-arraybuffer": "0.1.5",
- "blob": "0.0.5",
- "has-binary2": "~1.0.2"
- }
- },
- "ent": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz",
- "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0="
- },
- "es-abstract": {
- "version": "1.13.0",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
- "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
- "requires": {
- "es-to-primitive": "^1.2.0",
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "is-callable": "^1.1.4",
- "is-regex": "^1.0.4",
- "object-keys": "^1.0.12"
- }
- },
- "es-to-primitive": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
- "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
- "requires": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- }
- },
- "escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
- },
- "escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
- },
- "esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
- },
- "eventemitter3": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
- "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="
- },
- "execa": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
- "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
- "requires": {
- "cross-spawn": "^6.0.0",
- "get-stream": "^4.0.0",
- "is-stream": "^1.1.0",
- "npm-run-path": "^2.0.0",
- "p-finally": "^1.0.0",
- "signal-exit": "^3.0.0",
- "strip-eof": "^1.0.0"
- }
- },
- "expand-brackets": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
- "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
- "requires": {
- "debug": "^2.3.3",
- "define-property": "^0.2.5",
- "extend-shallow": "^2.0.1",
- "posix-character-classes": "^0.1.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- }
- },
- "extend": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "extglob": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
- "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
- "requires": {
- "array-unique": "^0.3.2",
- "define-property": "^1.0.0",
- "expand-brackets": "^2.1.4",
- "extend-shallow": "^2.0.1",
- "fragment-cache": "^0.2.1",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- },
- "kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
- }
- }
- },
- "fill-range": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
- "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
- "requires": {
- "extend-shallow": "^2.0.1",
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1",
- "to-regex-range": "^2.1.0"
- }
- },
- "finalhandler": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
- "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
- "requires": {
- "debug": "2.6.9",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "on-finished": "~2.3.0",
- "parseurl": "~1.3.3",
- "statuses": "~1.5.0",
- "unpipe": "~1.0.0"
- }
- },
- "find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "requires": {
- "locate-path": "^3.0.0"
- }
- },
- "flat": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz",
- "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==",
- "requires": {
- "is-buffer": "~2.0.3"
- },
- "dependencies": {
- "is-buffer": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz",
- "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw=="
- }
- }
- },
- "flatted": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
- "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg=="
- },
- "follow-redirects": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz",
- "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==",
- "requires": {
- "debug": "^3.2.6"
- },
- "dependencies": {
- "debug": {
- "version": "3.2.6",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
- "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
- }
- }
- },
- "for-in": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
- "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
- },
- "fragment-cache": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
- "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
- "requires": {
- "map-cache": "^0.2.2"
- }
- },
- "fs-access": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz",
- "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=",
- "dev": true,
- "requires": {
- "null-check": "^1.0.0"
- }
- },
- "fs-extra": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
- "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
- "requires": {
- "graceful-fs": "^4.1.2",
- "jsonfile": "^4.0.0",
- "universalify": "^0.1.0"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
- },
- "fsevents": {
- "version": "1.2.9",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
- "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
- "optional": true,
- "requires": {
- "nan": "^2.12.1",
- "node-pre-gyp": "^0.12.0"
- },
- "dependencies": {
- "abbrev": {
- "version": "1.1.1",
- "bundled": true,
- "optional": true
- },
- "ansi-regex": {
- "version": "2.1.1",
- "bundled": true,
- "optional": true
- },
- "aproba": {
- "version": "1.2.0",
- "bundled": true,
- "optional": true
- },
- "are-we-there-yet": {
- "version": "1.1.5",
- "bundled": true,
- "optional": true,
- "requires": {
- "delegates": "^1.0.0",
- "readable-stream": "^2.0.6"
- }
- },
- "balanced-match": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true
- },
- "brace-expansion": {
- "version": "1.1.11",
- "bundled": true,
- "optional": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "chownr": {
- "version": "1.1.1",
- "bundled": true,
- "optional": true
- },
- "code-point-at": {
- "version": "1.1.0",
- "bundled": true,
- "optional": true
- },
- "concat-map": {
- "version": "0.0.1",
- "bundled": true,
- "optional": true
- },
- "console-control-strings": {
- "version": "1.1.0",
- "bundled": true,
- "optional": true
- },
- "core-util-is": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "debug": {
- "version": "4.1.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "deep-extend": {
- "version": "0.6.0",
- "bundled": true,
- "optional": true
- },
- "delegates": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true
- },
- "detect-libc": {
- "version": "1.0.3",
- "bundled": true,
- "optional": true
- },
- "fs-minipass": {
- "version": "1.2.5",
- "bundled": true,
- "optional": true,
- "requires": {
- "minipass": "^2.2.1"
- }
- },
- "fs.realpath": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true
- },
- "gauge": {
- "version": "2.7.4",
- "bundled": true,
- "optional": true,
- "requires": {
- "aproba": "^1.0.3",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.0",
- "object-assign": "^4.1.0",
- "signal-exit": "^3.0.0",
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wide-align": "^1.1.0"
- }
- },
- "glob": {
- "version": "7.1.3",
- "bundled": true,
- "optional": true,
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "has-unicode": {
- "version": "2.0.1",
- "bundled": true,
- "optional": true
- },
- "iconv-lite": {
- "version": "0.4.24",
- "bundled": true,
- "optional": true,
- "requires": {
- "safer-buffer": ">= 2.1.2 < 3"
- }
- },
- "ignore-walk": {
- "version": "3.0.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "minimatch": "^3.0.4"
- }
- },
- "inflight": {
- "version": "1.0.6",
- "bundled": true,
- "optional": true,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.3",
- "bundled": true,
- "optional": true
- },
- "ini": {
- "version": "1.3.5",
- "bundled": true,
- "optional": true
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "isarray": {
- "version": "1.0.0",
- "bundled": true,
- "optional": true
- },
- "minimatch": {
- "version": "3.0.4",
- "bundled": true,
- "optional": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "minimist": {
- "version": "0.0.8",
- "bundled": true,
- "optional": true
- },
- "minipass": {
- "version": "2.3.5",
- "bundled": true,
- "optional": true,
- "requires": {
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.0"
- }
- },
- "minizlib": {
- "version": "1.2.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "minipass": "^2.2.1"
- }
- },
- "mkdirp": {
- "version": "0.5.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "minimist": "0.0.8"
- }
- },
- "ms": {
- "version": "2.1.1",
- "bundled": true,
- "optional": true
- },
- "needle": {
- "version": "2.3.0",
- "bundled": true,
- "optional": true,
- "requires": {
- "debug": "^4.1.0",
- "iconv-lite": "^0.4.4",
- "sax": "^1.2.4"
- }
- },
- "node-pre-gyp": {
- "version": "0.12.0",
- "bundled": true,
- "optional": true,
- "requires": {
- "detect-libc": "^1.0.2",
- "mkdirp": "^0.5.1",
- "needle": "^2.2.1",
- "nopt": "^4.0.1",
- "npm-packlist": "^1.1.6",
- "npmlog": "^4.0.2",
- "rc": "^1.2.7",
- "rimraf": "^2.6.1",
- "semver": "^5.3.0",
- "tar": "^4"
- }
- },
- "nopt": {
- "version": "4.0.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "abbrev": "1",
- "osenv": "^0.1.4"
- }
- },
- "npm-bundled": {
- "version": "1.0.6",
- "bundled": true,
- "optional": true
- },
- "npm-packlist": {
- "version": "1.4.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "ignore-walk": "^3.0.1",
- "npm-bundled": "^1.0.1"
- }
- },
- "npmlog": {
- "version": "4.1.2",
- "bundled": true,
- "optional": true,
- "requires": {
- "are-we-there-yet": "~1.1.2",
- "console-control-strings": "~1.1.0",
- "gauge": "~2.7.3",
- "set-blocking": "~2.0.0"
- }
- },
- "number-is-nan": {
- "version": "1.0.1",
- "bundled": true,
- "optional": true
- },
- "object-assign": {
- "version": "4.1.1",
- "bundled": true,
- "optional": true
- },
- "once": {
- "version": "1.4.0",
- "bundled": true,
- "optional": true,
- "requires": {
- "wrappy": "1"
- }
- },
- "os-homedir": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "os-tmpdir": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "osenv": {
- "version": "0.1.5",
- "bundled": true,
- "optional": true,
- "requires": {
- "os-homedir": "^1.0.0",
- "os-tmpdir": "^1.0.0"
- }
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "bundled": true,
- "optional": true
- },
- "process-nextick-args": {
- "version": "2.0.0",
- "bundled": true,
- "optional": true
- },
- "rc": {
- "version": "1.2.8",
- "bundled": true,
- "optional": true,
- "requires": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "dependencies": {
- "minimist": {
- "version": "1.2.0",
- "bundled": true,
- "optional": true
- }
- }
- },
- "readable-stream": {
- "version": "2.3.6",
- "bundled": true,
- "optional": true,
- "requires": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "rimraf": {
- "version": "2.6.3",
- "bundled": true,
- "optional": true,
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "safe-buffer": {
- "version": "5.1.2",
- "bundled": true,
- "optional": true
- },
- "safer-buffer": {
- "version": "2.1.2",
- "bundled": true,
- "optional": true
- },
- "sax": {
- "version": "1.2.4",
- "bundled": true,
- "optional": true
- },
- "semver": {
- "version": "5.7.0",
- "bundled": true,
- "optional": true
- },
- "set-blocking": {
- "version": "2.0.0",
- "bundled": true,
- "optional": true
- },
- "signal-exit": {
- "version": "3.0.2",
- "bundled": true,
- "optional": true
- },
- "string-width": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true,
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "string_decoder": {
- "version": "1.1.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "safe-buffer": "~5.1.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "bundled": true,
- "optional": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- },
- "strip-json-comments": {
- "version": "2.0.1",
- "bundled": true,
- "optional": true
- },
- "tar": {
- "version": "4.4.8",
- "bundled": true,
- "optional": true,
- "requires": {
- "chownr": "^1.1.1",
- "fs-minipass": "^1.2.5",
- "minipass": "^2.3.4",
- "minizlib": "^1.1.1",
- "mkdirp": "^0.5.0",
- "safe-buffer": "^5.1.2",
- "yallist": "^3.0.2"
- }
- },
- "util-deprecate": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "wide-align": {
- "version": "1.1.3",
- "bundled": true,
- "optional": true,
- "requires": {
- "string-width": "^1.0.2 || 2"
- }
- },
- "wrappy": {
- "version": "1.0.2",
- "bundled": true,
- "optional": true
- },
- "yallist": {
- "version": "3.0.3",
- "bundled": true,
- "optional": true
- }
- }
- },
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
- },
- "get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
- },
- "get-func-name": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
- "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE="
- },
- "get-stream": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
- "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
- "requires": {
- "pump": "^3.0.0"
- }
- },
- "get-value": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
- "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg="
- },
- "glob": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
- "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
- "requires": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
- },
- "dependencies": {
- "is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
- "requires": {
- "is-extglob": "^2.1.0"
- }
- }
- }
- },
- "graceful-fs": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.0.tgz",
- "integrity": "sha512-jpSvDPV4Cq/bgtpndIWbI5hmYxhQGHPC4d4cqBPb4DLniCfhJokdXhwhaDuLBGLQdvvRum/UiX6ECVIPvDXqdg=="
- },
- "growl": {
- "version": "1.10.5",
- "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
- "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA=="
- },
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "requires": {
- "function-bind": "^1.1.1"
- }
- },
- "has-binary2": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
- "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
- "requires": {
- "isarray": "2.0.1"
- },
- "dependencies": {
- "isarray": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
- "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
- }
- }
- },
- "has-cors": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
- "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
- },
- "has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
- },
- "has-symbols": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
- "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
- },
- "has-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
- "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
- "requires": {
- "get-value": "^2.0.6",
- "has-values": "^1.0.0",
- "isobject": "^3.0.0"
- }
- },
- "has-values": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
- "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
- "requires": {
- "is-number": "^3.0.0",
- "kind-of": "^4.0.0"
- },
- "dependencies": {
- "kind-of": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
- "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "he": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
- "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
- },
- "http-errors": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
- "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
- "requires": {
- "depd": "~1.1.2",
- "inherits": "2.0.3",
- "setprototypeof": "1.1.1",
- "statuses": ">= 1.5.0 < 2",
- "toidentifier": "1.0.0"
- }
- },
- "http-proxy": {
- "version": "1.17.0",
- "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
- "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
- "requires": {
- "eventemitter3": "^3.0.0",
- "follow-redirects": "^1.0.0",
- "requires-port": "^1.0.0"
- }
- },
- "iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "requires": {
- "safer-buffer": ">= 2.1.2 < 3"
- }
- },
- "indexof": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
- "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10="
- },
- "inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
- },
- "invert-kv": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
- "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA=="
- },
- "is-accessor-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
- "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
- "requires": {
- "kind-of": "^3.0.2"
- }
- },
- "is-binary-path": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
- "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
- "requires": {
- "binary-extensions": "^1.0.0"
- }
- },
- "is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
- },
- "is-callable": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
- "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
- },
- "is-data-descriptor": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
- "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
- "requires": {
- "kind-of": "^3.0.2"
- }
- },
- "is-date-object": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
- "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
- },
- "is-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
- "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
- "requires": {
- "is-accessor-descriptor": "^0.1.6",
- "is-data-descriptor": "^0.1.4",
- "kind-of": "^5.0.0"
- },
- "dependencies": {
- "kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw=="
- }
- }
- },
- "is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
- },
- "is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
- },
- "is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
- },
- "is-glob": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
- "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
- "requires": {
- "is-extglob": "^2.1.1"
- }
- },
- "is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
- "requires": {
- "kind-of": "^3.0.2"
- }
- },
- "is-plain-object": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
- "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
- "requires": {
- "isobject": "^3.0.1"
- }
- },
- "is-regex": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
- "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
- "requires": {
- "has": "^1.0.1"
- }
- },
- "is-stream": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
- "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
- },
- "is-symbol": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
- "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
- "requires": {
- "has-symbols": "^1.0.0"
- }
- },
- "is-windows": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
- "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="
- },
- "isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
- },
- "isbinaryfile": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz",
- "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==",
- "requires": {
- "buffer-alloc": "^1.2.0"
- }
- },
- "isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
- },
- "isobject": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
- },
- "js-yaml": {
- "version": "3.13.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
- "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
- "requires": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- }
- },
- "jsonfile": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
- "requires": {
- "graceful-fs": "^4.1.6"
- }
- },
- "karma": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/karma/-/karma-4.1.0.tgz",
- "integrity": "sha512-xckiDqyNi512U4dXGOOSyLKPwek6X/vUizSy2f3geYevbLj+UIdvNwbn7IwfUIL2g1GXEPWt/87qFD1fBbl/Uw==",
- "requires": {
- "bluebird": "^3.3.0",
- "body-parser": "^1.16.1",
- "braces": "^2.3.2",
- "chokidar": "^2.0.3",
- "colors": "^1.1.0",
- "connect": "^3.6.0",
- "core-js": "^2.2.0",
- "di": "^0.0.1",
- "dom-serialize": "^2.2.0",
- "flatted": "^2.0.0",
- "glob": "^7.1.1",
- "graceful-fs": "^4.1.2",
- "http-proxy": "^1.13.0",
- "isbinaryfile": "^3.0.0",
- "lodash": "^4.17.11",
- "log4js": "^4.0.0",
- "mime": "^2.3.1",
- "minimatch": "^3.0.2",
- "optimist": "^0.6.1",
- "qjobs": "^1.1.4",
- "range-parser": "^1.2.0",
- "rimraf": "^2.6.0",
- "safe-buffer": "^5.0.1",
- "socket.io": "2.1.1",
- "source-map": "^0.6.1",
- "tmp": "0.0.33",
- "useragent": "2.3.0"
- }
- },
- "karma-chai": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz",
- "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o="
- },
- "karma-chrome-launcher": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz",
- "integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==",
- "dev": true,
- "requires": {
- "fs-access": "^1.0.0",
- "which": "^1.2.1"
- }
- },
- "karma-firefox-launcher": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz",
- "integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==",
- "dev": true
- },
- "karma-mocha": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-1.3.0.tgz",
- "integrity": "sha1-7qrH/8DiAetjxGdEDStpx883eL8=",
- "dev": true,
- "requires": {
- "minimist": "1.2.0"
- },
- "dependencies": {
- "minimist": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
- "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
- "dev": true
- }
- }
- },
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "requires": {
- "is-buffer": "^1.1.5"
- }
- },
- "lcid": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
- "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
- "requires": {
- "invert-kv": "^2.0.0"
- }
- },
- "locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "requires": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- }
- },
- "lodash": {
- "version": "4.17.11",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
- "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
- },
- "log-symbols": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
- "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
- "requires": {
- "chalk": "^2.0.1"
- }
- },
- "log4js": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.4.0.tgz",
- "integrity": "sha512-xwRvmxFsq8Hb7YeS+XKfvCrsH114bXex6mIwJ2+KmYVi23pB3+hlzyGq1JPycSFTJWNLhD/7PCtM0RfPy6/2yg==",
- "requires": {
- "date-format": "^2.0.0",
- "debug": "^4.1.1",
- "flatted": "^2.0.0",
- "rfdc": "^1.1.4",
- "streamroller": "^1.0.5"
- },
- "dependencies": {
- "debug": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
- "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
- }
- }
- },
- "lru-cache": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
- "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
- "requires": {
- "pseudomap": "^1.0.2",
- "yallist": "^2.1.2"
- }
- },
- "map-age-cleaner": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
- "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
- "requires": {
- "p-defer": "^1.0.0"
- }
- },
- "map-cache": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
- "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
- },
- "map-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
- "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
- "requires": {
- "object-visit": "^1.0.0"
- }
- },
- "media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
- },
- "mem": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
- "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
- "requires": {
- "map-age-cleaner": "^0.1.1",
- "mimic-fn": "^2.0.0",
- "p-is-promise": "^2.0.0"
- }
- },
- "micromatch": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
- "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
- "requires": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "braces": "^2.3.1",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "extglob": "^2.0.4",
- "fragment-cache": "^0.2.1",
- "kind-of": "^6.0.2",
- "nanomatch": "^1.2.9",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.2"
- },
- "dependencies": {
- "define-property": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
- "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
- "requires": {
- "is-descriptor": "^1.0.2",
- "isobject": "^3.0.1"
- }
- },
- "extend-shallow": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
- "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
- "requires": {
- "assign-symbols": "^1.0.0",
- "is-extendable": "^1.0.1"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- },
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- },
- "kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
- }
- }
- },
- "mime": {
- "version": "2.4.4",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
- "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
- },
- "mime-db": {
- "version": "1.40.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
- "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
- },
- "mime-types": {
- "version": "2.1.24",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
- "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
- "requires": {
- "mime-db": "1.40.0"
- }
- },
- "mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
- },
- "minimatch": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "minimist": {
- "version": "0.0.10",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz",
- "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
- },
- "mixin-deep": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
- "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
- "requires": {
- "for-in": "^1.0.2",
- "is-extendable": "^1.0.1"
- },
- "dependencies": {
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
- }
- },
- "mkdirp": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
- "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
- "requires": {
- "minimist": "0.0.8"
- },
- "dependencies": {
- "minimist": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
- "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
- }
- }
- },
- "mocha": {
- "version": "6.1.4",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz",
- "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==",
- "requires": {
- "ansi-colors": "3.2.3",
- "browser-stdout": "1.3.1",
- "debug": "3.2.6",
- "diff": "3.5.0",
- "escape-string-regexp": "1.0.5",
- "find-up": "3.0.0",
- "glob": "7.1.3",
- "growl": "1.10.5",
- "he": "1.2.0",
- "js-yaml": "3.13.1",
- "log-symbols": "2.2.0",
- "minimatch": "3.0.4",
- "mkdirp": "0.5.1",
- "ms": "2.1.1",
- "node-environment-flags": "1.0.5",
- "object.assign": "4.1.0",
- "strip-json-comments": "2.0.1",
- "supports-color": "6.0.0",
- "which": "1.3.1",
- "wide-align": "1.1.3",
- "yargs": "13.2.2",
- "yargs-parser": "13.0.0",
- "yargs-unparser": "1.5.0"
- },
- "dependencies": {
- "debug": {
- "version": "3.2.6",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
- "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "glob": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
- "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
- "requires": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- }
- },
- "ms": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
- "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
- }
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
- },
- "nan": {
- "version": "2.14.0",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz",
- "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
- "optional": true
- },
- "nanomatch": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
- "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
- "requires": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "fragment-cache": "^0.2.1",
- "is-windows": "^1.0.2",
- "kind-of": "^6.0.2",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
- "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
- "requires": {
- "is-descriptor": "^1.0.2",
- "isobject": "^3.0.1"
- }
- },
- "extend-shallow": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
- "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
- "requires": {
- "assign-symbols": "^1.0.0",
- "is-extendable": "^1.0.1"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- },
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- },
- "kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
- }
- }
- },
- "negotiator": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
- "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
- },
- "nice-try": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
- "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
- },
- "node-environment-flags": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz",
- "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==",
- "requires": {
- "object.getownpropertydescriptors": "^2.0.3",
- "semver": "^5.7.0"
- }
- },
- "normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
- },
- "npm-run-path": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
- "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
- "requires": {
- "path-key": "^2.0.0"
- }
- },
- "null-check": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz",
- "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=",
- "dev": true
- },
- "number-is-nan": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
- "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
- },
- "object-component": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz",
- "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE="
- },
- "object-copy": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
- "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
- "requires": {
- "copy-descriptor": "^0.1.0",
- "define-property": "^0.2.5",
- "kind-of": "^3.0.3"
- }
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
- },
- "object-visit": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
- "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
- "requires": {
- "isobject": "^3.0.0"
- }
- },
- "object.assign": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
- "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
- "requires": {
- "define-properties": "^1.1.2",
- "function-bind": "^1.1.1",
- "has-symbols": "^1.0.0",
- "object-keys": "^1.0.11"
- }
- },
- "object.getownpropertydescriptors": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
- "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
- "requires": {
- "define-properties": "^1.1.2",
- "es-abstract": "^1.5.1"
- }
- },
- "object.pick": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
- "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
- "requires": {
- "isobject": "^3.0.1"
- }
- },
- "on-finished": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
- "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
- "requires": {
- "ee-first": "1.1.1"
- }
- },
- "once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
- "requires": {
- "wrappy": "1"
- }
- },
- "optimist": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
- "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
- "requires": {
- "minimist": "~0.0.1",
- "wordwrap": "~0.0.2"
- }
- },
- "os-locale": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
- "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
- "requires": {
- "execa": "^1.0.0",
- "lcid": "^2.0.0",
- "mem": "^4.0.0"
- }
- },
- "os-tmpdir": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
- "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
- },
- "p-defer": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
- "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww="
- },
- "p-finally": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
- "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
- },
- "p-is-promise": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
- "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg=="
- },
- "p-limit": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
- "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
- "requires": {
- "p-try": "^2.0.0"
- }
- },
- "p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "requires": {
- "p-limit": "^2.0.0"
- }
- },
- "p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
- },
- "parseqs": {
- "version": "0.0.5",
- "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz",
- "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=",
- "requires": {
- "better-assert": "~1.0.0"
- }
- },
- "parseuri": {
- "version": "0.0.5",
- "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz",
- "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=",
- "requires": {
- "better-assert": "~1.0.0"
- }
- },
- "parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
- },
- "pascalcase": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
- "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
- },
- "path-dirname": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
- "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA="
- },
- "path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
- },
- "path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
- },
- "path-key": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
- "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
- },
- "pathval": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
- "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA="
- },
- "posix-character-classes": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
- "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs="
- },
- "process-nextick-args": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
- },
- "pseudomap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
- "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
- },
- "pump": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
- "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
- "requires": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "qjobs": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz",
- "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg=="
- },
- "qs": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
- "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
- },
- "range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
- },
- "raw-body": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
- "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
- "requires": {
- "bytes": "3.1.0",
- "http-errors": "1.7.2",
- "iconv-lite": "0.4.24",
- "unpipe": "1.0.0"
- }
- },
- "readable-stream": {
- "version": "2.3.6",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
- "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
- "requires": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- },
- "dependencies": {
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
- }
- }
- },
- "readdirp": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
- "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
- "requires": {
- "graceful-fs": "^4.1.11",
- "micromatch": "^3.1.10",
- "readable-stream": "^2.0.2"
- }
- },
- "regex-not": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
- "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
- "requires": {
- "extend-shallow": "^3.0.2",
- "safe-regex": "^1.1.0"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
- "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
- "requires": {
- "assign-symbols": "^1.0.0",
- "is-extendable": "^1.0.1"
- }
- },
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
- }
- },
- "remove-trailing-separator": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
- "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
- },
- "repeat-element": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
- "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g=="
- },
- "repeat-string": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
- "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
- },
- "require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
- },
- "require-main-filename": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
- "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
- },
- "requires-port": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
- "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
- },
- "resolve-url": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
- "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
- },
- "ret": {
- "version": "0.1.15",
- "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
- "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="
- },
- "rfdc": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz",
- "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug=="
- },
- "rimraf": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
- "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "safe-buffer": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
- "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
- },
- "safe-regex": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
- "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
- "requires": {
- "ret": "~0.1.10"
- }
- },
- "safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
- },
- "semver": {
- "version": "5.7.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
- "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA=="
- },
- "set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
- },
- "set-value": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
- "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
- "requires": {
- "extend-shallow": "^2.0.1",
- "is-extendable": "^0.1.1",
- "is-plain-object": "^2.0.3",
- "split-string": "^3.0.1"
- }
- },
- "setprototypeof": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
- "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
- },
- "shebang-command": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
- "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
- "requires": {
- "shebang-regex": "^1.0.0"
- }
- },
- "shebang-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
- "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
- },
- "signal-exit": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
- "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
- },
- "snapdragon": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
- "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
- "requires": {
- "base": "^0.11.1",
- "debug": "^2.2.0",
- "define-property": "^0.2.5",
- "extend-shallow": "^2.0.1",
- "map-cache": "^0.2.2",
- "source-map": "^0.5.6",
- "source-map-resolve": "^0.5.0",
- "use": "^3.1.0"
- },
- "dependencies": {
- "source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
- }
- }
- },
- "snapdragon-node": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
- "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
- "requires": {
- "define-property": "^1.0.0",
- "isobject": "^3.0.0",
- "snapdragon-util": "^3.0.1"
- },
- "dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- },
- "kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
- }
- }
- },
- "snapdragon-util": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
- "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
- "requires": {
- "kind-of": "^3.2.0"
- }
- },
- "socket.io": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz",
- "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==",
- "requires": {
- "debug": "~3.1.0",
- "engine.io": "~3.2.0",
- "has-binary2": "~1.0.2",
- "socket.io-adapter": "~1.1.0",
- "socket.io-client": "2.1.1",
- "socket.io-parser": "~3.2.0"
- },
- "dependencies": {
- "debug": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
- "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
- "requires": {
- "ms": "2.0.0"
- }
- }
- }
- },
- "socket.io-adapter": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz",
- "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs="
- },
- "socket.io-client": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz",
- "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==",
- "requires": {
- "backo2": "1.0.2",
- "base64-arraybuffer": "0.1.5",
- "component-bind": "1.0.0",
- "component-emitter": "1.2.1",
- "debug": "~3.1.0",
- "engine.io-client": "~3.2.0",
- "has-binary2": "~1.0.2",
- "has-cors": "1.1.0",
- "indexof": "0.0.1",
- "object-component": "0.0.3",
- "parseqs": "0.0.5",
- "parseuri": "0.0.5",
- "socket.io-parser": "~3.2.0",
- "to-array": "0.1.4"
- },
- "dependencies": {
- "component-emitter": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
- "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
- },
- "debug": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
- "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
- "requires": {
- "ms": "2.0.0"
- }
- }
- }
- },
- "socket.io-parser": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz",
- "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==",
- "requires": {
- "component-emitter": "1.2.1",
- "debug": "~3.1.0",
- "isarray": "2.0.1"
- },
- "dependencies": {
- "component-emitter": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
- "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
- },
- "debug": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
- "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
- "requires": {
- "ms": "2.0.0"
- }
- },
- "isarray": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
- "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
- }
- }
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
- },
- "source-map-resolve": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz",
- "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==",
- "requires": {
- "atob": "^2.1.1",
- "decode-uri-component": "^0.2.0",
- "resolve-url": "^0.2.1",
- "source-map-url": "^0.4.0",
- "urix": "^0.1.0"
- }
- },
- "source-map-url": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
- "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="
- },
- "split-string": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
- "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
- "requires": {
- "extend-shallow": "^3.0.0"
- },
- "dependencies": {
- "extend-shallow": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
- "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
- "requires": {
- "assign-symbols": "^1.0.0",
- "is-extendable": "^1.0.1"
- }
- },
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
- }
- },
- "sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
- },
- "static-extend": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
- "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
- "requires": {
- "define-property": "^0.2.5",
- "object-copy": "^0.1.0"
- }
- },
- "statuses": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
- "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
- },
- "streamroller": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.5.tgz",
- "integrity": "sha512-iGVaMcyF5PcUY0cPbW3xFQUXnr9O4RZXNBBjhuLZgrjLO4XCLLGfx4T2sGqygSeylUjwgWRsnNbT9aV0Zb8AYw==",
- "requires": {
- "async": "^2.6.2",
- "date-format": "^2.0.0",
- "debug": "^3.2.6",
- "fs-extra": "^7.0.1",
- "lodash": "^4.17.11"
- },
- "dependencies": {
- "debug": {
- "version": "3.2.6",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
- "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
- }
- }
- },
- "string-width": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
- "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
- "requires": {
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^4.0.0"
- }
- },
- "string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "requires": {
- "safe-buffer": "~5.1.0"
- },
- "dependencies": {
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
- }
- }
- },
- "strip-ansi": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
- "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
- "requires": {
- "ansi-regex": "^3.0.0"
- }
- },
- "strip-eof": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
- "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
- },
- "strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
- },
- "supports-color": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz",
- "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==",
- "requires": {
- "has-flag": "^3.0.0"
- }
- },
- "tmp": {
- "version": "0.0.33",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
- "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
- "requires": {
- "os-tmpdir": "~1.0.2"
- }
- },
- "to-array": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
- "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA="
- },
- "to-object-path": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
- "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
- "requires": {
- "kind-of": "^3.0.2"
- }
- },
- "to-regex": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
- "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
- "requires": {
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "regex-not": "^1.0.2",
- "safe-regex": "^1.1.0"
- },
- "dependencies": {
- "define-property": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
- "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
- "requires": {
- "is-descriptor": "^1.0.2",
- "isobject": "^3.0.1"
- }
- },
- "extend-shallow": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
- "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
- "requires": {
- "assign-symbols": "^1.0.0",
- "is-extendable": "^1.0.1"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- },
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- },
- "kind-of": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
- "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
- }
- }
- },
- "to-regex-range": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
- "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
- "requires": {
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1"
- }
- },
- "toidentifier": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
- "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
- },
- "type-detect": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
- "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="
- },
- "type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "requires": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- }
- },
- "ultron": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz",
- "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og=="
- },
- "union-value": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
- "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
- "requires": {
- "arr-union": "^3.1.0",
- "get-value": "^2.0.6",
- "is-extendable": "^0.1.1",
- "set-value": "^2.0.1"
- }
- },
- "universalify": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
- "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
- },
- "unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
- },
- "unset-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
- "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
- "requires": {
- "has-value": "^0.3.1",
- "isobject": "^3.0.0"
- },
- "dependencies": {
- "has-value": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
- "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
- "requires": {
- "get-value": "^2.0.3",
- "has-values": "^0.1.4",
- "isobject": "^2.0.0"
- },
- "dependencies": {
- "isobject": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
- "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
- "requires": {
- "isarray": "1.0.0"
- }
- }
- }
- },
- "has-values": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
- "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E="
- }
- }
- },
- "upath": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz",
- "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q=="
- },
- "urix": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
- "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI="
- },
- "use": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
- "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
- },
- "useragent": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz",
- "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==",
- "requires": {
- "lru-cache": "4.1.x",
- "tmp": "0.0.x"
- }
- },
- "util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
- },
- "utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
- },
- "void-elements": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
- "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
- },
- "which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "requires": {
- "isexe": "^2.0.0"
- }
- },
- "which-module": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
- "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
- },
- "wide-align": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
- "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
- "requires": {
- "string-width": "^1.0.2 || 2"
- }
- },
- "wordwrap": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
- "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
- },
- "wrap-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
- "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
- "requires": {
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
- "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "string-width": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
- "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- }
- }
- },
- "wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
- },
- "ws": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz",
- "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==",
- "requires": {
- "async-limiter": "~1.0.0",
- "safe-buffer": "~5.1.0",
- "ultron": "~1.1.0"
- },
- "dependencies": {
- "safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
- }
- }
- },
- "xmlhttprequest-ssl": {
- "version": "1.5.5",
- "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz",
- "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4="
- },
- "y18n": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
- "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
- },
- "yallist": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
- "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
- },
- "yargs": {
- "version": "13.2.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz",
- "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==",
- "requires": {
- "cliui": "^4.0.0",
- "find-up": "^3.0.0",
- "get-caller-file": "^2.0.1",
- "os-locale": "^3.1.0",
- "require-directory": "^2.1.1",
- "require-main-filename": "^2.0.0",
- "set-blocking": "^2.0.0",
- "string-width": "^3.0.0",
- "which-module": "^2.0.0",
- "y18n": "^4.0.0",
- "yargs-parser": "^13.0.0"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
- },
- "string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "requires": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- }
- },
- "strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "requires": {
- "ansi-regex": "^4.1.0"
- }
- }
- }
- },
- "yargs-parser": {
- "version": "13.0.0",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz",
- "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==",
- "requires": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- }
- },
- "yargs-unparser": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz",
- "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==",
- "requires": {
- "flat": "^4.1.0",
- "lodash": "^4.17.11",
- "yargs": "^12.0.5"
- },
- "dependencies": {
- "get-caller-file": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
- "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
- },
- "require-main-filename": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
- "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
- },
- "yargs": {
- "version": "12.0.5",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
- "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
- "requires": {
- "cliui": "^4.0.0",
- "decamelize": "^1.2.0",
- "find-up": "^3.0.0",
- "get-caller-file": "^1.0.1",
- "os-locale": "^3.0.0",
- "require-directory": "^2.1.1",
- "require-main-filename": "^1.0.1",
- "set-blocking": "^2.0.0",
- "string-width": "^2.0.0",
- "which-module": "^2.0.0",
- "y18n": "^3.2.1 || ^4.0.0",
- "yargs-parser": "^11.1.1"
- }
- },
- "yargs-parser": {
- "version": "11.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
- "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
- "requires": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- }
- }
- }
- },
- "yeast": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
- "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
- }
- }
-}
diff --git a/tests/package.json b/tests/package.json
deleted file mode 100644
index 9584860..0000000
--- a/tests/package.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "scripts": {
- "test": "./node_modules/karma/bin/karma start"
- },
- "dependencies": {
- "chai": "^4.2.0",
- "karma": "^4.1.0",
- "karma-chai": "^0.1.0",
- "mocha": "^6.1.4"
- },
- "devDependencies": {
- "karma-chrome-launcher": "^2.2.0",
- "karma-firefox-launcher": "^1.1.0",
- "karma-mocha": "^1.3.0"
- }
-}
diff --git a/tests/tests/test.js b/tests/tests/test.js
deleted file mode 100644
index 93830eb..0000000
--- a/tests/tests/test.js
+++ /dev/null
@@ -1,484 +0,0 @@
-const body = document.getElementsByTagName('body')[0];
-
-suite('Dashboard', function() {
- suite('Global Functions', function() {
- let formContainer;
- let cancelButton;
- let backButton;
- let forwardButton;
- let viewMessage;
- let paginationControl;
- let topPagination;
- let viewTitle;
- let viewDesc;
- let response;
-
- setup(function() {
- body.innerHTML = '';
- response = {
- redirect: false,
- meta: {
- workflow_count: 0,
- active: 0,
- steps: [{
- title: 'title',
- valid: '299',
- message: 'testMessage',
- enabled: false
- }]
- },
- content: 'exampleContent'
- };
- // Override the functions for testing
- $.post = function(url, data, cb, type) {
- cb(response);
- return $.Deferred().resolve();
- }
- // Create all elements needed for the global functions
- formContainer = document.createElement('div');
- formContainer.id = 'formContainer';
- cancelButton = document.createElement('button');
- cancelButton.id = 'cancel_btn';
- backButton = document.createElement('button');
- backButton.id = 'gob';
- forwardButton = document.createElement('button');
- forwardButton.id = 'gof';
- viewMessage = document.createElement('p');
- viewMessage.id = 'view_message';
- paginationControl = document.createElement('li');
- paginationControl.classList.add('page-control');
- topPagination = document.createElement('ul');
- topPagination.id = 'topPagination';
- topPagination.appendChild(paginationControl);
- viewTitle = document.createElement('span');
- viewTitle.id = 'view_title';
- viewDesc = document.createElement('span');
- viewDesc.id = 'view_desc';
-
- // Update the elements on the page
- body.appendChild(formContainer);
- body.appendChild(backButton);
- body.appendChild(forwardButton);
- body.appendChild(viewMessage);
- body.appendChild(cancelButton);
- body.appendChild(topPagination);
- body.appendChild(viewTitle);
- body.appendChild(viewDesc);
- update_page(response);
- });
-
- // Testing all of these because they are all required to run
- // when running update_page(), and removing parts of it will break
- // document.body is different outside and inside the test() callback.
- test('update_page', function() {
- assert.equal(formContainer.innerHTML, 'exampleContent');
- });
- test('draw_breadcrumbs', function() {
- assert.isAbove(topPagination.childElementCount, 1);
- })
- test('create_step', function() {
- assert.equal(topPagination.firstChild.innerText, 'title');
- });
- test('update_exit_button', function() {
- assert.equal(cancelButton.innerText, 'Return to Parent');
- });
- test('update_side_buttons', function() {
- assert(forwardButton.disabled);
- assert(backButton.disabled);
- });
- test('update_description', function() {
- update_description('title', 'description');
-
- assert.equal(viewTitle.innerText, 'title');
- assert.equal(viewDesc.innerText, 'description');
- });
- test('update_message', function() {
- update_message('message', 999);
- assert.equal(viewMessage.innerText, 'message');
- assert(viewMessage.classList.contains('step_message'));
- assert(viewMessage.classList.contains('message_999'));
- });
- test('submitStepForm', function() {
- // Empty the container so that the function changes it
- formContainer.innerHTML = '';
- submitStepForm();
- assert.equal(formContainer.innerHTML, 'exampleContent');
- });
- test('run_form_callbacks', function() {
- form_submission_callbacks.push(function() {
- let testObject = document.createElement('span');
- testObject.id = 'testObject';
- body.appendChild(testObject);
- });
- run_form_callbacks();
- assert.isNotNull(document.getElementById('testObject'));
- });
- });
-
- suite('MultipleSelectFilterWidget', function() {
- let widget;
- let initialData;
- let lab1;
- let lab2;
- let host1;
- let host2;
- let graph_neighbors;
- let filter_items;
-
- setup(function() {
- body.innerHTML = '';
- // Create elements that represent these choices
- lab1 = document.createElement('div');
- lab1.id = 'lab_1';
- lab2 = document.createElement('div');
- lab2.id = 'lab_2';
- host1 = document.createElement('div');
- host1.id = 'host_1';
- host2 = document.createElement('div');
- host2.id = 'host_2';
-
- // Append elements to the page
- body.append(lab1);
- body.append(lab2);
- body.append(host1);
- body.append(host2);
- initialData = {
- host: {
- host_1: {
- selected: true
- }
- },
- lab: {
- lab_1: {
- selected: true
- }
- }
- };
- graph_neighbors = {
- host_1: ['lab_1'],
- host_2: ['lab_1'],
- lab_1: ['host_1', 'host_2']
- };
- filter_items = {
- host_1: {
- name: 'host 1',
- class: 'host',
- description: 'first host',
- id: 'host_1',
- form: {
- type: 'text',
- name: 'textInput'
- },
- selectable: true,
- multiple: false,
- selected: false
- },
- host_2: {
- name: 'host 2',
- class: 'host',
- description: 'second host',
- id: 'host_2',
- form: {
- type: 'text',
- name: 'textInput'
- },
- selectable: true,
- multiple: false,
- selected: false
- },
- lab_1: {
- name: 'lab 1',
- class: 'lab',
- description: 'first lab',
- id: 'lab_1',
- form: {
- type: 'text',
- name: 'textInput'
- },
- selectable: true,
- multiple: false,
- selected: false
- },
- lab_2: {
- name: 'lab 2',
- class: 'lab',
- description: 'second lab',
- id: 'lab_2',
- form: {
- type: 'text',
- name: 'textInput'
- },
- selectable: true,
- multiple: false,
- selected: false
- }
- };
- widget = new MultipleSelectFilterWidget(graph_neighbors, filter_items, {});
- });
-
- test('make_selection', function() {
- widget.make_selection(initialData);
- assert.isTrue(lab1.classList.contains('selected_node'));
- assert.isTrue(host1.classList.contains('selected_node'));
- });
-
- test('multiple selected items', function() {
- widget.processClick('lab_1');
- widget.processClick('host_1');
- assert.isTrue(lab1.classList.contains('selected_node'));
- assert.isTrue(host1.classList.contains('selected_node'));
-
- // Make sure clicking multiple hosts/labs doesn't work
- widget.processClick('host_2');
- widget.processClick('lab_2');
- assert.isFalse(host2.classList.contains('selected_node'));
- assert.isFalse(lab2.classList.contains('selected_node'));
-
- // Unselect host1 then try host2 again
- widget.processClick('host_1');
- widget.processClick('host_2');
- assert.isFalse(host1.classList.contains('selected_node'));
- assert.isTrue(host2.classList.contains('selected_node'));
- });
- });
-
- suite('NetworkStep', function() {
- let hosts;
- let graphContainer;
- let overviewContainer;
- let toolbarContainer;
- let networkList;
- let networkStep;
-
- setup(function() {
- body.innerHTML = '';
- hosts = [
- {
- id: 'host1',
- interfaces: [
- {
- name: 'interface1',
- description: 'description1'
- }
- ],
- value: {
- description: 'example host1',
- name: 'host1'
- }
- }
- ];
- graphContainer = document.createElement('div');
- overviewContainer = document.createElement('div');
- toolbarContainer = document.createElement('div');
- networkList = document.createElement('div');
- networkList.id = 'network_list';
-
- body.appendChild(graphContainer);
- body.appendChild(overviewContainer);
- body.appendChild(toolbarContainer);
- body.appendChild(networkList);
-
- networkStep = new NetworkStep(true, '', hosts, [], [], graphContainer, overviewContainer, toolbarContainer);
- });
-
- test('public network creation', function() {
- // Network list's first child should be the 'public' network div,
- // Public div has two children: the colored circle and the label
- // It does not have a delete button.
- assert.equal(networkList.childNodes[0].childNodes.length, 2);
- assert.equal(networkList.childNodes[0].childNodes[1].innerText, 'public');
- });
-
- test('duplicate network name', function() {
- networkStep.newNetworkWindow();
- let netInput = document.querySelector('input[name="net_name"]');
- netInput.value = 'public'
- document.querySelector('.mxWindowPane div button:first-of-type').click();
- let windowErrors = document.getElementById('current_window_errors');
- assert.equal(windowErrors.innerText, 'All network names must be unique');
- });
-
-
- test('new network creation', function() {
- networkStep.newNetworkWindow();
- let netInput = document.querySelector('input[name="net_name"]');
- netInput.value = 'testNetwork';
- document.querySelector('.mxWindowPane div button:first-of-type').click();
- assert.equal(networkList.childNodes[1].childNodes[1].innerText, 'testNetwork');
- });
- });
-
- suite('SearchableSelectMultipleWidget', function() {
- let formatVars = {
- placeholder: 'Example placeholder',
- results_scrollable: true,
- selectable_limit: -1,
- show_from_noentry: false,
- show_x_results: 5
- };
- let fieldDataset = {
- '1': {
- expanded_name: 'Test User',
- id: 1,
- small_name: 'small Test',
- string: 'email@test.com'
- }
- };
- let widget;
- let input;
- let dropdown;
- let scrollRestrictor;
- let userField;
- let addedNumber;
- let selector;
- let addedList;
-
- setup(function() {
- body.innerHTML = '';
- input = document.createElement('input');
- dropdown = document.createElement('div');
- scrollRestrictor = document.createElement('div');
- addedList = document.createElement('div');
- addedList.id = 'added_list';
- selector = document.createElement('div');
- selector.id = 'selector';
- addedNumber = document.createElement('div');
- addedNumber.id = 'added_number';
- userField = document.createElement('div');
- userField.id = 'user_field';
- scrollRestrictor.id = 'scroll_restrictor';
- dropdown.id = 'drop_results';
- input.type = 'text';
- input.value = 'Test ';
-
- body.appendChild(scrollRestrictor);
- body.appendChild(dropdown);
- body.appendChild(input);
- body.appendChild(userField);
- body.appendChild(addedNumber);
- body.appendChild(selector);
- body.appendChild(addedList);
-
- widget = new SearchableSelectMultipleWidget(formatVars, fieldDataset, []);
- });
-
- test('disable', function() {
- widget.disable();
- assert.equal(userField.disabled, 'True');
- assert.equal(dropdown.style.display, 'none');
- });
-
- test('search_field_init', function() {
- assert.isEmpty(addedNumber.innerText);
- assert.isUndefined(selector.value);
- assert.isEmpty(addedList.childNodes);
- widget.initial = [1];
- widget.search_field_init();
- assert.equal(addedNumber.innerText, '1');
- assert.equal(selector.value, '[1]');
- assert.equal(addedList.childNodes.length, 1);
- });
-
- test('build_all_tries', function() {
- let dict = {
- '1': {
- expanded_name: 'exnamea',
- small_name: 'smnamea',
- string: 'stra',
- id: 1
- },
- '2': {
- expanded_name: 'exnameb',
- small_name: 'smnameb',
- string: 'strb',
- id: 2
- }
- };
- widget.build_all_tries(dict);
- // since each subtree has keys of 1 character each, look for a nested
- // property using '.' after each letter for nesting
- assert.nestedProperty(widget.expanded_name_trie, 'e.x.n.a.m.e.a');
- assert.nestedProperty(widget.small_name_trie, 's.m.n.a.m.e.a');
- assert.nestedProperty(widget.string_trie, 's.t.r.a');
- assert.nestedProperty(widget.expanded_name_trie, 'e.x.n.a.m.e.b');
- assert.nestedProperty(widget.small_name_trie, 's.m.n.a.m.e.b');
- assert.nestedProperty(widget.string_trie, 's.t.r.b');
- });
-
- test('add_item', function() {
- let item = {
- id: 1,
- expanded_name: 'item',
- small_name: 'item',
- string: 'item'
- };
- widget.add_item(item);
- assert.nestedProperty(widget.expanded_name_trie, 'i.t.e.m');
- assert.nestedProperty(widget.small_name_trie, 'i.t.e.m');
- assert.nestedProperty(widget.string_trie, 'i.t.e.m');
- });
-
- test('add_to_tree', function() {
- widget.add_to_tree('addtotree', 0, widget.string_trie);
- assert.nestedProperty(widget.string_trie, 'a.d.d.t.o.t.r.e.e');
- });
-
- test('search', function() {
- widget.search('Test ');
- assert.equal(dropdown.childNodes[0].title, 'Test User (small Test, email@test.com)');
- // Search some random text that shouldn't resolve to any user
- widget.search('Empty');
- assert.equal(dropdown.childElementCount, 0);
- });
-
- test('getSubtree', function() {
- // 'email@test.com': search for 'email', next letter should be '@'
- assert.property(widget.getSubtree('email', widget.string_trie), '@');
- });
-
- test('serialize', function() {
- // object in string_trie has id 1, check if the array contains 1
- assert.include(widget.serialize(widget.string_trie), 1);
- });
-
- test('collate', function() {
- let trees = [widget.string_trie, widget.small_name_trie, widget.expanded_name_trie];
- let result = widget.collate(trees);
- assert.lengthOf(result, 2);
- });
-
- test('generate_element_text', function() {
- let obj = {
- expanded_name: '1',
- small_name: '2',
- string: '3'
- }
- assert.equal(widget.generate_element_text(obj), '1 (2, 3)');
- });
-
- test('dropdown', function() {
- // use undefined since dropdown doesn't use values, only keys
- widget.dropdown({'1': undefined});
- assert.lengthOf(dropdown.childNodes, 1);
- });
-
- test('select_item', function() {
- widget.select_item('1');
- assert.lengthOf(addedList.childNodes, 1);
- });
-
- test('remove_item', function() {
- widget.select_item('1');
- assert.isNotEmpty(addedList.childNodes);
- widget.remove_item('1');
- assert.isEmpty(addedList.childNodes);
- });
-
- test('update_selected_list', function() {
- widget.added_items.add('1');
- assert.lengthOf(addedList.childNodes, 0);
- widget.update_selected_list();
- assert.lengthOf(addedList.childNodes, 1);
- });
- });
-});
diff --git a/tox.ini b/tox.ini
deleted file mode 100644
index 3d01e10..0000000
--- a/tox.ini
+++ /dev/null
@@ -1,21 +0,0 @@
-[tox]
-envlist = flake8
-skipsdist = True
-
-[testenv]
-deps = -rrequirements.txt
-basepython = python3
-
-# Store flake8 config here intead of .flake8
-[flake8]
-ignore =
- # Ignore 'line-too-long' warnings
- E501
-exclude =
- src/manage.py
-
-[testenv:flake8]
-deps =
- -rrequirements.txt
- flake8
-commands = flake8 src/
diff --git a/web/Dockerfile b/web/Dockerfile
deleted file mode 100644
index c05193a..0000000
--- a/web/Dockerfile
+++ /dev/null
@@ -1,24 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Trevor Bramwell and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-FROM python:3.9
-ENV PYTHONUNBUFFERED 1
-
-RUN apt-get update && apt-get install -y npm
-
-ADD requirements.txt /requirements.txt
-RUN pip install -r /requirements.txt
-
-ADD web/init.sh /init.sh
-ADD src/ /laas_dashboard/
-
-ADD src/static/ laas_dashboard/static/
-RUN cd laas_dashboard/static/ && npm install
-
-WORKDIR /laas_dashboard/
-CMD ["/init.sh"]
diff --git a/web/init.sh b/web/init.sh
deleted file mode 100755
index 1545fc8..0000000
--- a/web/init.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash -e
-##############################################################################
-# Copyright (c) 2018 Trevor Bramwell and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-python manage.py migrate && \
-python manage.py collectstatic --no-input && \
-gunicorn laas_dashboard.wsgi -b 0.0.0.0:8000
diff --git a/worker/Dockerfile b/worker/Dockerfile
deleted file mode 100644
index edf86d1..0000000
--- a/worker/Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-##############################################################################
-# Copyright (c) 2018 Trevor Bramwell and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-FROM python:3.9
-ENV PYTHONUNBUFFERED 1
-
-ADD requirements.txt /requirements.txt
-RUN pip install -r /requirements.txt
-
-ADD worker/init.sh /init.sh
-ADD src/ /laas_dashboard/
-
-RUN useradd -ms /bin/bash celery
-USER celery
-
-WORKDIR /laas_dashboard/
-CMD ["/init.sh"]
diff --git a/worker/init.sh b/worker/init.sh
deleted file mode 100755
index d657c3c..0000000
--- a/worker/init.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash -e
-##############################################################################
-# Copyright (c) 2018 Trevor Bramwell and others.
-#
-# All rights reserved. This program and the accompanying materials
-# are made available under the terms of the Apache License, Version 2.0
-# which accompanies this distribution, and is available at
-# http://www.apache.org/licenses/LICENSE-2.0
-##############################################################################
-
-celery -A laas_dashboard worker -l info -B --schedule=/home/celery/schedule
--
cgit