From a1291c371695f41b92c1c3ccdbc3d45f71c0dd94 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Thu, 21 May 2015 22:54:44 +1000 Subject: [PATCH] Restyle Administrator pages --- modules/backend/assets/css/controls.css | 5 + .../backend/assets/js/vendor/vendor-min.js | 695 +----------------- modules/backend/assets/js/vendor/vendor.js | 1 + .../backend/assets/less/controls/forms.less | 27 + modules/backend/classes/AuthManager.php | 24 +- modules/backend/classes/NavigationManager.php | 2 +- modules/backend/controllers/UserGroups.php | 46 +- modules/backend/controllers/Users.php | 83 ++- modules/backend/lang/en/lang.php | 9 +- modules/backend/models/user/columns.yaml | 15 +- modules/backend/models/user/fields.yaml | 76 +- modules/backend/models/usergroup/fields.yaml | 7 +- .../widgets/form/assets/js/october.form.js | 24 +- modules/cms/ServiceProvider.php | 18 +- 14 files changed, 240 insertions(+), 792 deletions(-) diff --git a/modules/backend/assets/css/controls.css b/modules/backend/assets/css/controls.css index cfc372aa9..42d8c554d 100644 --- a/modules/backend/assets/css/controls.css +++ b/modules/backend/assets/css/controls.css @@ -45,7 +45,12 @@ label{font-size:12px} .input-with-icon.left-align > .icon{left:0} .input-with-icon.left-align input{padding-left:32px !important} .field-section{border-bottom:1px solid #e0e0e0;padding-top:3px;padding-bottom:7px} +.field-section > h4{color:rgba(0,0,0,0.6)} .field-section > p:first-child,.field-section > h4:first-child{margin:0} +.field-section.is-collapsible{cursor:pointer} +.field-section.is-collapsible > h4:before{display:inline-block;font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;vertical-align:baseline;content:"\f0d7";margin:0 8px;float:right;color:rgba(0,0,0,0.4)} +.field-section.is-collapsible:hover{border-bottom:1px solid #c7c7c7} +.field-section.is-collapsible:hover > h4:before{color:inherit} .field-textarea{resize:vertical} .field-textarea.size-tiny{min-height:50px} .field-textarea.size-small{min-height:100px} diff --git a/modules/backend/assets/js/vendor/vendor-min.js b/modules/backend/assets/js/vendor/vendor-min.js index 1012908e2..1b2b95e28 100644 --- a/modules/backend/assets/js/vendor/vendor-min.js +++ b/modules/backend/assets/js/vendor/vendor-min.js @@ -1416,697 +1416,4 @@ if(typeof option=='string')data[option].call($this)})} $.fn.dropdown.Constructor=Dropdown $.fn.dropdown.noConflict=function(){$.fn.dropdown=old return this} -$(document).on('click.bs.dropdown.data-api',clearMenus).on('click.bs.dropdown.data-api','.dropdown form',function(e){e.stopPropagation()}).on('click.bs.dropdown.data-api',toggle,Dropdown.prototype.toggle).on('keydown.bs.dropdown.data-api',toggle+', [role=menu], [role=listbox]',Dropdown.prototype.keydown)}(jQuery);(function(B){B.color={};B.color.make=function(F,E,C,D){var G={};G.r=F||0;G.g=E||0;G.b=C||0;G.a=D!=null?D:1;G.add=function(J,I){for(var H=0;H=1){return"rgb("+[G.r,G.g,G.b].join(",")+")"}else{return"rgba("+[G.r,G.g,G.b,G.a].join(",")+")"}};G.normalize=function(){function H(J,K,I){return KI?I:K)}G.r=H(0,parseInt(G.r),255);G.g=H(0,parseInt(G.g),255);G.b=H(0,parseInt(G.b),255);G.a=H(0,G.a,1);return G};G.clone=function(){return B.color.make(G.r,G.b,G.g,G.a)};return G.normalize()};B.color.extract=function(D,C){var E;do{E=D.css(C).toLowerCase();if(E!=""&&E!="transparent"){break}D=D.parent()}while(!B.nodeName(D.get(0),"body"));if(E=="rgba(0, 0, 0, 0)"){E="transparent"}return B.color.parse(E)};B.color.parse=function(F){var E,C=B.color.make;if(E=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10))}if(E=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10),parseFloat(E[4]))}if(E=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55)}if(E=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55,parseFloat(E[4]))}if(E=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(F)){return C(parseInt(E[1],16),parseInt(E[2],16),parseInt(E[3],16))}if(E=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(F)){return C(parseInt(E[1]+E[1],16),parseInt(E[2]+E[2],16),parseInt(E[3]+E[3],16))}var D=B.trim(F).toLowerCase();if(D=="transparent"){return C(255,255,255,0)}else{E=A[D]||[0,0,0];return C(E[0],E[1],E[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);(function($){var hasOwnProperty=Object.prototype.hasOwnProperty;function Canvas(cls,container){var element=container.children("."+cls)[0];if(element==null){element=document.createElement("canvas");element.className=cls;$(element).css({direction:"ltr",position:"absolute",left:0,top:0}).appendTo(container);if(!element.getContext){if(window.G_vmlCanvasManager){element=window.G_vmlCanvasManager.initElement(element);}else{throw new Error("Canvas is not available. If you're using IE with a fall-back such as Excanvas, then there's either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.");}}} -this.element=element;var context=this.context=element.getContext("2d");var devicePixelRatio=window.devicePixelRatio||1,backingStoreRatio=context.webkitBackingStorePixelRatio||context.mozBackingStorePixelRatio||context.msBackingStorePixelRatio||context.oBackingStorePixelRatio||context.backingStorePixelRatio||1;this.pixelRatio=devicePixelRatio/backingStoreRatio;this.resize(container.width(),container.height());this.textContainer=null;this.text={};this._textCache={};} -Canvas.prototype.resize=function(width,height){if(width<=0||height<=0){throw new Error("Invalid dimensions for plot, width = "+width+", height = "+height);} -var element=this.element,context=this.context,pixelRatio=this.pixelRatio;if(this.width!=width){element.width=width*pixelRatio;element.style.width=width+"px";this.width=width;} -if(this.height!=height){element.height=height*pixelRatio;element.style.height=height+"px";this.height=height;} -context.restore();context.save();context.scale(pixelRatio,pixelRatio);};Canvas.prototype.clear=function(){this.context.clearRect(0,0,this.width,this.height);};Canvas.prototype.render=function(){var cache=this._textCache;for(var layerKey in cache){if(hasOwnProperty.call(cache,layerKey)){var layer=this.getTextLayer(layerKey),layerCache=cache[layerKey];layer.hide();for(var styleKey in layerCache){if(hasOwnProperty.call(layerCache,styleKey)){var styleCache=layerCache[styleKey];for(var key in styleCache){if(hasOwnProperty.call(styleCache,key)){var positions=styleCache[key].positions;for(var i=0,position;position=positions[i];i++){if(position.active){if(!position.rendered){layer.append(position.element);position.rendered=true;}}else{positions.splice(i--,1);if(position.rendered){position.element.detach();}}} -if(positions.length==0){delete styleCache[key];}}}}} -layer.show();}}};Canvas.prototype.getTextLayer=function(classes){var layer=this.text[classes];if(layer==null){if(this.textContainer==null){this.textContainer=$("
").css({position:"absolute",top:0,left:0,bottom:0,right:0,'font-size':"smaller",color:"#545454"}).insertAfter(this.element);} -layer=this.text[classes]=$("
").addClass(classes).css({position:"absolute",top:0,left:0,bottom:0,right:0}).appendTo(this.textContainer);} -return layer;};Canvas.prototype.getTextInfo=function(layer,text,font,angle,width){var textStyle,layerCache,styleCache,info;text=""+text;if(typeof font==="object"){textStyle=font.style+" "+font.variant+" "+font.weight+" "+font.size+"px/"+font.lineHeight+"px "+font.family;}else{textStyle=font;} -layerCache=this._textCache[layer];if(layerCache==null){layerCache=this._textCache[layer]={};} -styleCache=layerCache[textStyle];if(styleCache==null){styleCache=layerCache[textStyle]={};} -info=styleCache[text];if(info==null){var element=$("
").html(text).css({position:"absolute",'max-width':width,top:-9999}).appendTo(this.getTextLayer(layer));if(typeof font==="object"){element.css({font:textStyle,color:font.color});}else if(typeof font==="string"){element.addClass(font);} -info=styleCache[text]={width:element.outerWidth(true),height:element.outerHeight(true),element:element,positions:[]};element.detach();} -return info;};Canvas.prototype.addText=function(layer,x,y,text,font,angle,width,halign,valign){var info=this.getTextInfo(layer,text,font,angle,width),positions=info.positions;if(halign=="center"){x-=info.width/2;}else if(halign=="right"){x-=info.width;} -if(valign=="middle"){y-=info.height/2;}else if(valign=="bottom"){y-=info.height;} -for(var i=0,position;position=positions[i];i++){if(position.x==x&&position.y==y){position.active=true;return;}} -position={active:true,rendered:false,element:positions.length?info.element.clone():info.element,x:x,y:y};positions.push(position);position.element.css({top:Math.round(y),left:Math.round(x),'text-align':halign});};Canvas.prototype.removeText=function(layer,x,y,text,font,angle){if(text==null){var layerCache=this._textCache[layer];if(layerCache!=null){for(var styleKey in layerCache){if(hasOwnProperty.call(layerCache,styleKey)){var styleCache=layerCache[styleKey];for(var key in styleCache){if(hasOwnProperty.call(styleCache,key)){var positions=styleCache[key].positions;for(var i=0,position;position=positions[i];i++){position.active=false;}}}}}}}else{var positions=this.getTextInfo(layer,text,font,angle).positions;for(var i=0,position;position=positions[i];i++){if(position.x==x&&position.y==y){position.active=false;}}}};function Plot(placeholder,data_,options_,plugins){var series=[],options={colors:["#edc240","#afd8f8","#cb4b4b","#4da74d","#9440ed"],legend:{show:true,noColumns:1,labelFormatter:null,labelBoxBorderColor:"#ccc",container:null,position:"ne",margin:5,backgroundColor:null,backgroundOpacity:0.85,sorted:null},xaxis:{show:null,position:"bottom",mode:null,font:null,color:null,tickColor:null,transform:null,inverseTransform:null,min:null,max:null,autoscaleMargin:null,ticks:null,tickFormatter:null,labelWidth:null,labelHeight:null,reserveSpace:null,tickLength:null,alignTicksWithAxis:null,tickDecimals:null,tickSize:null,minTickSize:null},yaxis:{autoscaleMargin:0.02,position:"left"},xaxes:[],yaxes:[],series:{points:{show:false,radius:3,lineWidth:2,fill:true,fillColor:"#ffffff",symbol:"circle"},lines:{lineWidth:2,fill:false,fillColor:null,steps:false},bars:{show:false,lineWidth:2,barWidth:1,fill:true,fillColor:null,align:"left",horizontal:false,zero:true},shadowSize:3,highlightColor:null},grid:{show:true,aboveData:false,color:"#545454",backgroundColor:null,borderColor:null,tickColor:null,margin:0,labelMargin:5,axisMargin:8,borderWidth:2,minBorderMargin:null,markings:null,markingsColor:"#f4f4f4",markingsLineWidth:2,clickable:false,hoverable:false,autoHighlight:true,mouseActiveRadius:10},interaction:{redrawOverlayInterval:1000/60},hooks:{}},surface=null,overlay=null,eventHolder=null,ctx=null,octx=null,xaxes=[],yaxes=[],plotOffset={left:0,right:0,top:0,bottom:0},plotWidth=0,plotHeight=0,hooks={processOptions:[],processRawData:[],processDatapoints:[],processOffset:[],drawBackground:[],drawSeries:[],draw:[],bindEvents:[],drawOverlay:[],shutdown:[]},plot=this;plot.setData=setData;plot.setupGrid=setupGrid;plot.draw=draw;plot.getPlaceholder=function(){return placeholder;};plot.getCanvas=function(){return surface.element;};plot.getPlotOffset=function(){return plotOffset;};plot.width=function(){return plotWidth;};plot.height=function(){return plotHeight;};plot.offset=function(){var o=eventHolder.offset();o.left+=plotOffset.left;o.top+=plotOffset.top;return o;};plot.getData=function(){return series;};plot.getAxes=function(){var res={},i;$.each(xaxes.concat(yaxes),function(_,axis){if(axis) -res[axis.direction+(axis.n!=1?axis.n:"")+"axis"]=axis;});return res;};plot.getXAxes=function(){return xaxes;};plot.getYAxes=function(){return yaxes;};plot.c2p=canvasToAxisCoords;plot.p2c=axisToCanvasCoords;plot.getOptions=function(){return options;};plot.highlight=highlight;plot.unhighlight=unhighlight;plot.triggerRedrawOverlay=triggerRedrawOverlay;plot.pointOffset=function(point){return{left:parseInt(xaxes[axisNumber(point,"x")-1].p2c(+point.x)+plotOffset.left,10),top:parseInt(yaxes[axisNumber(point,"y")-1].p2c(+point.y)+plotOffset.top,10)};};plot.shutdown=shutdown;plot.resize=function(){var width=placeholder.width(),height=placeholder.height();surface.resize(width,height);overlay.resize(width,height);};plot.hooks=hooks;initPlugins(plot);parseOptions(options_);setupCanvases();setData(data_);setupGrid();draw();bindEvents();function executeHooks(hook,args){args=[plot].concat(args);for(var i=0;imaxIndex){maxIndex=sc;}}} -if(neededColors<=maxIndex){neededColors=maxIndex+1;} -var c,colors=[],colorPool=options.colors,colorPoolSize=colorPool.length,variation=0;for(i=0;i=0){if(variation<0.5){variation=-variation-0.2;}else variation=0;}else variation=-variation;} -colors[i]=c.scale('rgb',1+variation);} -var colori=0,s;for(i=0;iaxis.datamax&&max!=fakeInfinity) -axis.datamax=max;} -$.each(allAxes(),function(_,axis){axis.datamin=topSentry;axis.datamax=bottomSentry;axis.used=false;});for(i=0;i0&&points[k-ps]!=null&&points[k-ps]!=points[k]&&points[k-ps+1]!=points[k+1]){for(m=0;mxmax) -xmax=val;} -if(f.y){if(valymax) -ymax=val;}}} -if(s.bars.show){var delta;switch(s.bars.align){case"left":delta=0;break;case"right":delta=-s.bars.barWidth;break;case"center":delta=-s.bars.barWidth/2;break;default:throw new Error("Invalid bar alignment: "+s.bars.align);} -if(s.bars.horizontal){ymin+=delta;ymax+=delta+s.bars.barWidth;} -else{xmin+=delta;xmax+=delta+s.bars.barWidth;}} -updateAxis(s.xaxis,xmin,xmax);updateAxis(s.yaxis,ymin,ymax);} -$.each(allAxes(),function(_,axis){if(axis.datamin==topSentry) -axis.datamin=null;if(axis.datamax==bottomSentry) -axis.datamax=null;});} -function setupCanvases(){placeholder.css("padding",0).children(":not(.flot-base,.flot-overlay)").remove();if(placeholder.css("position")=='static') -placeholder.css("position","relative");surface=new Canvas("flot-base",placeholder);overlay=new Canvas("flot-overlay",placeholder);ctx=surface.context;octx=overlay.context;eventHolder=$(overlay.element).unbind();var existing=placeholder.data("plot");if(existing){existing.shutdown();overlay.clear();} -placeholder.data("plot",plot);} -function bindEvents(){if(options.grid.hoverable){eventHolder.mousemove(onMouseMove);eventHolder.bind("mouseleave",onMouseLeave);} -if(options.grid.clickable) -eventHolder.click(onClick);executeHooks(hooks.bindEvents,[eventHolder]);} -function shutdown(){if(redrawTimeout) -clearTimeout(redrawTimeout);eventHolder.unbind("mousemove",onMouseMove);eventHolder.unbind("mouseleave",onMouseLeave);eventHolder.unbind("click",onClick);executeHooks(hooks.shutdown,[eventHolder]);} -function setTransformationHelpers(axis){function identity(x){return x;} -var s,m,t=axis.options.transform||identity,it=axis.options.inverseTransform;if(axis.direction=="x"){s=axis.scale=plotWidth/Math.abs(t(axis.max)-t(axis.min));m=Math.min(t(axis.max),t(axis.min));} -else{s=axis.scale=plotHeight/Math.abs(t(axis.max)-t(axis.min));s=-s;m=Math.max(t(axis.max),t(axis.min));} -if(t==identity) -axis.p2c=function(p){return(p-m)*s;};else -axis.p2c=function(p){return(t(p)-m)*s;};if(!it) -axis.c2p=function(c){return m+c/s;};else -axis.c2p=function(c){return it(m+c/s);};} -function measureTickLabels(axis){var opts=axis.options,ticks=axis.ticks||[],labelWidth=opts.labelWidth||0,labelHeight=opts.labelHeight||0,maxWidth=labelWidth||axis.direction=="x"?Math.floor(surface.width/(ticks.length||1)):null,legacyStyles=axis.direction+"Axis "+axis.direction+axis.n+"Axis",layer="flot-"+axis.direction+"-axis flot-"+axis.direction+axis.n+"-axis "+legacyStyles,font=opts.font||"flot-tick-label tickLabel";for(var i=0;i=0;--i) -allocateAxisBoxFirstPhase(allocatedAxes[i]);adjustLayoutForThingsStickingOut();$.each(allocatedAxes,function(_,axis){allocateAxisBoxSecondPhase(axis);});} -plotWidth=surface.width-plotOffset.left-plotOffset.right;plotHeight=surface.height-plotOffset.bottom-plotOffset.top;$.each(axes,function(_,axis){setTransformationHelpers(axis);});if(showGrid){drawAxisLabels();} -insertLegend();} -function setRange(axis){var opts=axis.options,min=+(opts.min!=null?opts.min:axis.datamin),max=+(opts.max!=null?opts.max:axis.datamax),delta=max-min;if(delta==0.0){var widen=max==0?1:0.01;if(opts.min==null) -min-=widen;if(opts.max==null||opts.min!=null) -max+=widen;} -else{var margin=opts.autoscaleMargin;if(margin!=null){if(opts.min==null){min-=delta*margin;if(min<0&&axis.datamin!=null&&axis.datamin>=0) -min=0;} -if(opts.max==null){max+=delta*margin;if(max>0&&axis.datamax!=null&&axis.datamax<=0) -max=0;}}} -axis.min=min;axis.max=max;} -function setupTickGeneration(axis){var opts=axis.options;var noTicks;if(typeof opts.ticks=="number"&&opts.ticks>0) -noTicks=opts.ticks;else -noTicks=0.3*Math.sqrt(axis.direction=="x"?surface.width:surface.height);var delta=(axis.max-axis.min)/noTicks,dec=-Math.floor(Math.log(delta)/Math.LN10),maxDec=opts.tickDecimals;if(maxDec!=null&&dec>maxDec){dec=maxDec;} -var magn=Math.pow(10,-dec),norm=delta/magn,size;if(norm<1.5){size=1;}else if(norm<3){size=2;if(norm>2.25&&(maxDec==null||dec+1<=maxDec)){size=2.5;++dec;}}else if(norm<7.5){size=5;}else{size=10;} -size*=magn;if(opts.minTickSize!=null&&size0){if(opts.min==null) -axis.min=Math.min(axis.min,niceTicks[0]);if(opts.max==null&&niceTicks.length>1) -axis.max=Math.max(axis.max,niceTicks[niceTicks.length-1]);} -axis.tickGenerator=function(axis){var ticks=[],v,i;for(i=0;i1&&/\..*0$/.test((ts[1]-ts[0]).toFixed(extraDec)))) -axis.tickDecimals=extraDec;}}}} -function setTicks(axis){var oticks=axis.options.ticks,ticks=[];if(oticks==null||(typeof oticks=="number"&&oticks>0)) -ticks=axis.tickGenerator(axis);else if(oticks){if($.isFunction(oticks)) -ticks=oticks(axis);else -ticks=oticks;} -var i,v;axis.ticks=[];for(i=0;i1) -label=t[1];} -else -v=+t;if(label==null) -label=axis.tickFormatter(v,axis);if(!isNaN(v)) -axis.ticks.push({v:v,label:label});}} -function snapRangeToTicks(axis,ticks){if(axis.options.autoscaleMargin&&ticks.length>0){if(axis.options.min==null) -axis.min=Math.min(axis.min,ticks[0].v);if(axis.options.max==null&&ticks.length>1) -axis.max=Math.max(axis.max,ticks[ticks.length-1].v);}} -function draw(){surface.clear();executeHooks(hooks.drawBackground,[ctx]);var grid=options.grid;if(grid.show&&grid.backgroundColor) -drawBackground();if(grid.show&&!grid.aboveData){drawGrid();} -for(var i=0;ito){var tmp=from;from=to;to=tmp;} -return{from:from,to:to,axis:axis};} -function drawBackground(){ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.fillStyle=getColorOrGradient(options.grid.backgroundColor,plotHeight,0,"rgba(255, 255, 255, 0)");ctx.fillRect(0,0,plotWidth,plotHeight);ctx.restore();} -function drawGrid(){var i,axes,bw,bc;ctx.save();ctx.translate(plotOffset.left,plotOffset.top);var markings=options.grid.markings;if(markings){if($.isFunction(markings)){axes=plot.getAxes();axes.xmin=axes.xaxis.min;axes.xmax=axes.xaxis.max;axes.ymin=axes.yaxis.min;axes.ymax=axes.yaxis.max;markings=markings(axes);} -for(i=0;ixrange.axis.max||yrange.toyrange.axis.max) -continue;xrange.from=Math.max(xrange.from,xrange.axis.min);xrange.to=Math.min(xrange.to,xrange.axis.max);yrange.from=Math.max(yrange.from,yrange.axis.min);yrange.to=Math.min(yrange.to,yrange.axis.max);if(xrange.from==xrange.to&&yrange.from==yrange.to) -continue;xrange.from=xrange.axis.p2c(xrange.from);xrange.to=xrange.axis.p2c(xrange.to);yrange.from=yrange.axis.p2c(yrange.from);yrange.to=yrange.axis.p2c(yrange.to);if(xrange.from==xrange.to||yrange.from==yrange.to){ctx.beginPath();ctx.strokeStyle=m.color||options.grid.markingsColor;ctx.lineWidth=m.lineWidth||options.grid.markingsLineWidth;ctx.moveTo(xrange.from,yrange.from);ctx.lineTo(xrange.to,yrange.to);ctx.stroke();} -else{ctx.fillStyle=m.color||options.grid.markingsColor;ctx.fillRect(xrange.from,yrange.to,xrange.to-xrange.from,yrange.from-yrange.to);}}} -axes=allAxes();bw=options.grid.borderWidth;for(var j=0;jaxis.max||(t=="full"&&((typeof bw=="object"&&bw[axis.position]>0)||bw>0)&&(v==axis.min||v==axis.max))) -continue;if(axis.direction=="x"){x=axis.p2c(v);yoff=t=="full"?-plotHeight:t;if(axis.position=="top") -yoff=-yoff;} -else{y=axis.p2c(v);xoff=t=="full"?-plotWidth:t;if(axis.position=="left") -xoff=-xoff;} -if(ctx.lineWidth==1){if(axis.direction=="x") -x=Math.floor(x)+0.5;else -y=Math.floor(y)+0.5;} -ctx.moveTo(x,y);ctx.lineTo(x+xoff,y+yoff);} -ctx.stroke();} -if(bw){bc=options.grid.borderColor;if(typeof bw=="object"||typeof bc=="object"){if(typeof bw!=="object"){bw={top:bw,right:bw,bottom:bw,left:bw};} -if(typeof bc!=="object"){bc={top:bc,right:bc,bottom:bc,left:bc};} -if(bw.top>0){ctx.strokeStyle=bc.top;ctx.lineWidth=bw.top;ctx.beginPath();ctx.moveTo(0-bw.left,0-bw.top/2);ctx.lineTo(plotWidth,0-bw.top/2);ctx.stroke();} -if(bw.right>0){ctx.strokeStyle=bc.right;ctx.lineWidth=bw.right;ctx.beginPath();ctx.moveTo(plotWidth+bw.right/2,0-bw.top);ctx.lineTo(plotWidth+bw.right/2,plotHeight);ctx.stroke();} -if(bw.bottom>0){ctx.strokeStyle=bc.bottom;ctx.lineWidth=bw.bottom;ctx.beginPath();ctx.moveTo(plotWidth+bw.right,plotHeight+bw.bottom/2);ctx.lineTo(0,plotHeight+bw.bottom/2);ctx.stroke();} -if(bw.left>0){ctx.strokeStyle=bc.left;ctx.lineWidth=bw.left;ctx.beginPath();ctx.moveTo(0-bw.left/2,plotHeight+bw.bottom);ctx.lineTo(0-bw.left/2,0);ctx.stroke();}} -else{ctx.lineWidth=bw;ctx.strokeStyle=options.grid.borderColor;ctx.strokeRect(-bw/2,-bw/2,plotWidth+bw,plotHeight+bw);}} -ctx.restore();} -function drawAxisLabels(){$.each(allAxes(),function(_,axis){if(!axis.show||axis.ticks.length==0) -return;var box=axis.box,legacyStyles=axis.direction+"Axis "+axis.direction+axis.n+"Axis",layer="flot-"+axis.direction+"-axis flot-"+axis.direction+axis.n+"-axis "+legacyStyles,font=axis.options.font||"flot-tick-label tickLabel",tick,x,y,halign,valign;surface.removeText(layer);for(var i=0;iaxis.max) -continue;if(axis.direction=="x"){halign="center";x=plotOffset.left+axis.p2c(tick.v);if(axis.position=="bottom"){y=box.top+box.padding;}else{y=box.top+box.height-box.padding;valign="bottom";}}else{valign="middle";y=plotOffset.top+axis.p2c(tick.v);if(axis.position=="left"){x=box.left+box.width-box.padding;halign="right";}else{x=box.left+box.padding;}} -surface.addText(layer,x,y,tick.label,font,null,null,halign,valign);}});} -function drawSeries(series){if(series.lines.show) -drawSeriesLines(series);if(series.bars.show) -drawSeriesBars(series);if(series.points.show) -drawSeriesPoints(series);} -function drawSeriesLines(series){function plotLine(datapoints,xoffset,yoffset,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize,prevx=null,prevy=null;ctx.beginPath();for(var i=ps;i=y2&&y1>axisy.max){if(y2>axisy.max) -continue;x1=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.max;} -else if(y2>=y1&&y2>axisy.max){if(y1>axisy.max) -continue;x2=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.max;} -if(x1<=x2&&x1=x2&&x1>axisx.max){if(x2>axisx.max) -continue;y1=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.max;} -else if(x2>=x1&&x2>axisx.max){if(x1>axisx.max) -continue;y2=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.max;} -if(x1!=prevx||y1!=prevy) -ctx.moveTo(axisx.p2c(x1)+xoffset,axisy.p2c(y1)+yoffset);prevx=x2;prevy=y2;ctx.lineTo(axisx.p2c(x2)+xoffset,axisy.p2c(y2)+yoffset);} -ctx.stroke();} -function plotLineArea(datapoints,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize,bottom=Math.min(Math.max(0,axisy.min),axisy.max),i=0,top,areaOpen=false,ypos=1,segmentStart=0,segmentEnd=0;while(true){if(ps>0&&i>points.length+ps) -break;i+=ps;var x1=points[i-ps],y1=points[i-ps+ypos],x2=points[i],y2=points[i+ypos];if(areaOpen){if(ps>0&&x1!=null&&x2==null){segmentEnd=i;ps=-ps;ypos=2;continue;} -if(ps<0&&i==segmentStart+ps){ctx.fill();areaOpen=false;ps=-ps;ypos=1;i=segmentStart=segmentEnd+ps;continue;}} -if(x1==null||x2==null) -continue;if(x1<=x2&&x1=x2&&x1>axisx.max){if(x2>axisx.max) -continue;y1=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x1=axisx.max;} -else if(x2>=x1&&x2>axisx.max){if(x1>axisx.max) -continue;y2=(axisx.max-x1)/(x2-x1)*(y2-y1)+y1;x2=axisx.max;} -if(!areaOpen){ctx.beginPath();ctx.moveTo(axisx.p2c(x1),axisy.p2c(bottom));areaOpen=true;} -if(y1>=axisy.max&&y2>=axisy.max){ctx.lineTo(axisx.p2c(x1),axisy.p2c(axisy.max));ctx.lineTo(axisx.p2c(x2),axisy.p2c(axisy.max));continue;} -else if(y1<=axisy.min&&y2<=axisy.min){ctx.lineTo(axisx.p2c(x1),axisy.p2c(axisy.min));ctx.lineTo(axisx.p2c(x2),axisy.p2c(axisy.min));continue;} -var x1old=x1,x2old=x2;if(y1<=y2&&y1=axisy.min){x1=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.min;} -else if(y2<=y1&&y2=axisy.min){x2=(axisy.min-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.min;} -if(y1>=y2&&y1>axisy.max&&y2<=axisy.max){x1=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y1=axisy.max;} -else if(y2>=y1&&y2>axisy.max&&y1<=axisy.max){x2=(axisy.max-y1)/(y2-y1)*(x2-x1)+x1;y2=axisy.max;} -if(x1!=x1old){ctx.lineTo(axisx.p2c(x1old),axisy.p2c(y1));} -ctx.lineTo(axisx.p2c(x1),axisy.p2c(y1));ctx.lineTo(axisx.p2c(x2),axisy.p2c(y2));if(x2!=x2old){ctx.lineTo(axisx.p2c(x2),axisy.p2c(y2));ctx.lineTo(axisx.p2c(x2old),axisy.p2c(y2));}}} -ctx.save();ctx.translate(plotOffset.left,plotOffset.top);ctx.lineJoin="round";var lw=series.lines.lineWidth,sw=series.shadowSize;if(lw>0&&sw>0){ctx.lineWidth=sw;ctx.strokeStyle="rgba(0,0,0,0.1)";var angle=Math.PI/18;plotLine(series.datapoints,Math.sin(angle)*(lw/2+sw/2),Math.cos(angle)*(lw/2+sw/2),series.xaxis,series.yaxis);ctx.lineWidth=sw/2;plotLine(series.datapoints,Math.sin(angle)*(lw/2+sw/4),Math.cos(angle)*(lw/2+sw/4),series.xaxis,series.yaxis);} -ctx.lineWidth=lw;ctx.strokeStyle=series.color;var fillStyle=getFillStyle(series.lines,series.color,0,plotHeight);if(fillStyle){ctx.fillStyle=fillStyle;plotLineArea(series.datapoints,series.xaxis,series.yaxis);} -if(lw>0) -plotLine(series.datapoints,0,0,series.xaxis,series.yaxis);ctx.restore();} -function drawSeriesPoints(series){function plotPoints(datapoints,radius,fillStyle,offset,shadow,axisx,axisy,symbol){var points=datapoints.points,ps=datapoints.pointsize;for(var i=0;iaxisx.max||yaxisy.max) -continue;ctx.beginPath();x=axisx.p2c(x);y=axisy.p2c(y)+offset;if(symbol=="circle") -ctx.arc(x,y,radius,0,shadow?Math.PI:Math.PI*2,false);else -symbol(ctx,x,y,radius,shadow);ctx.closePath();if(fillStyle){ctx.fillStyle=fillStyle;ctx.fill();} -ctx.stroke();}} -ctx.save();ctx.translate(plotOffset.left,plotOffset.top);var lw=series.points.lineWidth,sw=series.shadowSize,radius=series.points.radius,symbol=series.points.symbol;if(lw==0) -lw=0.0001;if(lw>0&&sw>0){var w=sw/2;ctx.lineWidth=w;ctx.strokeStyle="rgba(0,0,0,0.1)";plotPoints(series.datapoints,radius,null,w+w/2,true,series.xaxis,series.yaxis,symbol);ctx.strokeStyle="rgba(0,0,0,0.2)";plotPoints(series.datapoints,radius,null,w/2,true,series.xaxis,series.yaxis,symbol);} -ctx.lineWidth=lw;ctx.strokeStyle=series.color;plotPoints(series.datapoints,radius,getFillStyle(series.points,series.color),0,false,series.xaxis,series.yaxis,symbol);ctx.restore();} -function drawBar(x,y,b,barLeft,barRight,offset,fillStyleCallback,axisx,axisy,c,horizontal,lineWidth){var left,right,bottom,top,drawLeft,drawRight,drawTop,drawBottom,tmp;if(horizontal){drawBottom=drawRight=drawTop=true;drawLeft=false;left=b;right=x;top=y+barLeft;bottom=y+barRight;if(rightaxisx.max||topaxisy.max) -return;if(leftaxisx.max){right=axisx.max;drawRight=false;} -if(bottomaxisy.max){top=axisy.max;drawTop=false;} -left=axisx.p2c(left);bottom=axisy.p2c(bottom);right=axisx.p2c(right);top=axisy.p2c(top);if(fillStyleCallback){c.beginPath();c.moveTo(left,bottom);c.lineTo(left,top);c.lineTo(right,top);c.lineTo(right,bottom);c.fillStyle=fillStyleCallback(bottom,top);c.fill();} -if(lineWidth>0&&(drawLeft||drawRight||drawTop||drawBottom)){c.beginPath();c.moveTo(left,bottom+offset);if(drawLeft) -c.lineTo(left,top+offset);else -c.moveTo(left,top+offset);if(drawTop) -c.lineTo(right,top+offset);else -c.moveTo(right,top+offset);if(drawRight) -c.lineTo(right,bottom+offset);else -c.moveTo(right,bottom+offset);if(drawBottom) -c.lineTo(left,bottom+offset);else -c.moveTo(left,bottom+offset);c.stroke();}} -function drawSeriesBars(series){function plotBars(datapoints,barLeft,barRight,offset,fillStyleCallback,axisx,axisy){var points=datapoints.points,ps=datapoints.pointsize;for(var i=0;i');fragments.push('');rowStarted=true;} -fragments.push('
'+''+entry.label+'');} -if(rowStarted) -fragments.push('');if(fragments.length==0) -return;var table=''+fragments.join("")+'
';if(options.legend.container!=null) -$(options.legend.container).html(table);else{var pos="",p=options.legend.position,m=options.legend.margin;if(m[0]==null) -m=[m,m];if(p.charAt(0)=="n") -pos+='top:'+(m[1]+plotOffset.top)+'px;';else if(p.charAt(0)=="s") -pos+='bottom:'+(m[1]+plotOffset.bottom)+'px;';if(p.charAt(1)=="e") -pos+='right:'+(m[0]+plotOffset.right)+'px;';else if(p.charAt(1)=="w") -pos+='left:'+(m[0]+plotOffset.left)+'px;';var legend=$('
'+table.replace('style="','style="position:absolute;'+pos+';')+'
').appendTo(placeholder);if(options.legend.backgroundOpacity!=0.0){var c=options.legend.backgroundColor;if(c==null){c=options.grid.backgroundColor;if(c&&typeof c=="string") -c=$.color.parse(c);else -c=$.color.extract(legend,'background-color');c.a=1;c=c.toString();} -var div=legend.children();$('
').prependTo(legend).css('opacity',options.legend.backgroundOpacity);}}} -var highlights=[],redrawTimeout=null;function findNearbyItem(mouseX,mouseY,seriesFilter){var maxDistance=options.grid.mouseActiveRadius,smallestDistance=maxDistance*maxDistance+1,item=null,foundPoint=false,i,j,ps;for(i=series.length-1;i>=0;--i){if(!seriesFilter(series[i])) -continue;var s=series[i],axisx=s.xaxis,axisy=s.yaxis,points=s.datapoints.points,mx=axisx.c2p(mouseX),my=axisy.c2p(mouseY),maxx=maxDistance/axisx.scale,maxy=maxDistance/axisy.scale;ps=s.datapoints.pointsize;if(axisx.options.inverseTransform) -maxx=Number.MAX_VALUE;if(axisy.options.inverseTransform) -maxy=Number.MAX_VALUE;if(s.lines.show||s.points.show){for(j=0;jmaxx||x-mx<-maxx||y-my>maxy||y-my<-maxy) -continue;var dx=Math.abs(axisx.p2c(x)-mouseX),dy=Math.abs(axisy.p2c(y)-mouseY),dist=dx*dx+dy*dy;if(dist=Math.min(b,x)&&my>=y+barLeft&&my<=y+barRight):(mx>=x+barLeft&&mx<=x+barRight&&my>=Math.min(b,y)&&my<=Math.max(b,y))) -item=[i,j/ps];}}} -if(item){i=item[0];j=item[1];ps=series[i].datapoints.pointsize;return{datapoint:series[i].datapoints.points.slice(j*ps,(j+1)*ps),dataIndex:j,series:series[i],seriesIndex:i};} -return null;} -function onMouseMove(e){if(options.grid.hoverable) -triggerClickHoverEvent("plothover",e,function(s){return s["hoverable"]!=false;});} -function onMouseLeave(e){if(options.grid.hoverable) -triggerClickHoverEvent("plothover",e,function(s){return false;});} -function onClick(e){triggerClickHoverEvent("plotclick",e,function(s){return s["clickable"]!=false;});} -function triggerClickHoverEvent(eventname,event,seriesFilter){var offset=eventHolder.offset(),canvasX=event.pageX-offset.left-plotOffset.left,canvasY=event.pageY-offset.top-plotOffset.top,pos=canvasToAxisCoords({left:canvasX,top:canvasY});pos.pageX=event.pageX;pos.pageY=event.pageY;var item=findNearbyItem(canvasX,canvasY,seriesFilter);if(item){item.pageX=parseInt(item.series.xaxis.p2c(item.datapoint[0])+offset.left+plotOffset.left,10);item.pageY=parseInt(item.series.yaxis.p2c(item.datapoint[1])+offset.top+plotOffset.top,10);} -if(options.grid.autoHighlight){for(var i=0;iaxisx.max||yaxisy.max) -return;var pointRadius=series.points.radius+series.points.lineWidth/2;octx.lineWidth=pointRadius;octx.strokeStyle=highlightColor;var radius=1.5*pointRadius;x=axisx.p2c(x);y=axisy.p2c(y);octx.beginPath();if(series.points.symbol=="circle") -octx.arc(x,y,radius,0,2*Math.PI,false);else -series.points.symbol(octx,x,y,radius,false);octx.closePath();octx.stroke();} -function drawBarHighlight(series,point){var highlightColor=(typeof series.highlightColor==="string")?series.highlightColor:$.color.parse(series.color).scale('a',0.5).toString(),fillStyle=highlightColor,barLeft=series.bars.align=="left"?0:-series.bars.barWidth/2;octx.lineWidth=series.bars.lineWidth;octx.strokeStyle=highlightColor;drawBar(point[0],point[1],point[2]||0,barLeft,barLeft+series.bars.barWidth,0,function(){return fillStyle;},series.xaxis,series.yaxis,octx,series.bars.horizontal,series.bars.lineWidth);} -function getColorOrGradient(spec,bottom,top,defaultColor){if(typeof spec=="string") -return spec;else{var gradient=ctx.createLinearGradient(0,top,0,bottom);for(var i=0,l=spec.colors.length;i0){$tip=$('#flotTip');} -else{$tip=$('
').attr('id','flotTip');$tip.appendTo('body').hide().css({position:'absolute'});if(this.tooltipOptions.defaultTheme){$tip.css({'background':'#fff','z-index':'100','padding':'0.4em 0.6em','border-radius':'0.5em','font-size':'0.8em','border':'1px solid #111','display':'inline-block','white-space':'nowrap'});}} -return $tip;};FlotTooltip.prototype.updateTooltipPosition=function(pos){var totalTipWidth=$("#flotTip").outerWidth()+this.tooltipOptions.shifts.x;var totalTipHeight=$("#flotTip").outerHeight()+this.tooltipOptions.shifts.y;if((pos.x-$(window).scrollLeft())>($(window).innerWidth()-totalTipWidth)){pos.x-=totalTipWidth;} -if((pos.y-$(window).scrollTop())>($(window).innerHeight()-totalTipHeight)){pos.y-=totalTipHeight;} -this.tipPosition.x=pos.x;this.tipPosition.y=pos.y;};FlotTooltip.prototype.stringFormat=function(content,item){var percentPattern=/%p\.{0,1}(\d{0,})/;var seriesPattern=/%s/;var xPattern=/%x\.{0,1}(\d{0,})/;var yPattern=/%y\.{0,1}(\d{0,})/;if(typeof(content)==='function'){content=content(item.series.data[item.dataIndex][0],item.series.data[item.dataIndex][1]);} -if(typeof(item.series.percent)!=='undefined'){content=this.adjustValPrecision(percentPattern,content,item.series.percent);} -if(typeof(item.series.label)!=='undefined'){content=content.replace(seriesPattern,item.series.label);} -if(this.isTimeMode('xaxis',item)&&this.isXDateFormat(item)){content=content.replace(xPattern,this.timestampToDate(item.series.data[item.dataIndex][0],this.tooltipOptions.xDateFormat));} -if(this.isTimeMode('yaxis',item)&&this.isYDateFormat(item)){content=content.replace(yPattern,this.timestampToDate(item.series.data[item.dataIndex][1],this.tooltipOptions.yDateFormat));} -if(typeof item.series.data[item.dataIndex][0]==='number'){content=this.adjustValPrecision(xPattern,content,item.series.data[item.dataIndex][0]);} -if(typeof item.series.data[item.dataIndex][1]==='number'){content=this.adjustValPrecision(yPattern,content,item.series.data[item.dataIndex][1]);} -if(typeof item.series.xaxis.tickFormatter!=='undefined'){content=content.replace(xPattern,item.series.xaxis.tickFormatter(item.series.data[item.dataIndex][0],item.series.xaxis));} -if(typeof item.series.yaxis.tickFormatter!=='undefined'){content=content.replace(yPattern,item.series.yaxis.tickFormatter(item.series.data[item.dataIndex][1],item.series.yaxis));} -return content;};FlotTooltip.prototype.isTimeMode=function(axisName,item){return(typeof item.series[axisName].options.mode!=='undefined'&&item.series[axisName].options.mode==='time');};FlotTooltip.prototype.isXDateFormat=function(item){return(typeof this.tooltipOptions.xDateFormat!=='undefined'&&this.tooltipOptions.xDateFormat!==null);};FlotTooltip.prototype.isYDateFormat=function(item){return(typeof this.tooltipOptions.yDateFormat!=='undefined'&&this.tooltipOptions.yDateFormat!==null);};FlotTooltip.prototype.timestampToDate=function(tmst,dateFormat){var theDate=new Date(tmst);return $.plot.formatDate(theDate,dateFormat);};FlotTooltip.prototype.adjustValPrecision=function(pattern,content,value){var precision;if(content.match(pattern)!==null){if(RegExp.$1!==''){precision=RegExp.$1;value=value.toFixed(precision);content=content.replace(pattern,value);}} -return content;};var init=function(plot){new FlotTooltip(plot);};$.plot.plugins.push({init:init,options:defaultOptions,name:'tooltip',version:'0.6.1'});})(jQuery);(function($){var options={};function init(plot){function onResize(){var placeholder=plot.getPlaceholder();if(placeholder.width()==0||placeholder.height()==0) -return;plot.resize();plot.setupGrid();plot.draw();} -function bindEvents(plot,eventHolder){$(window).bind('resize',onResize)} -function shutdown(plot,eventHolder){$(window).unbind('resize',onResize)} -plot.hooks.bindEvents.push(bindEvents);plot.hooks.shutdown.push(shutdown);} -$.plot.plugins.push({init:init,options:options,name:'resize',version:'1.0'});})(jQuery);(function($){var options={xaxis:{timezone:null,timeformat:null,twelveHourClock:false,monthNames:null}};function floorInBase(n,base){return base*Math.floor(n/base);} -function formatDate(d,fmt,monthNames,dayNames){if(typeof d.strftime=="function"){return d.strftime(fmt);} -var leftPad=function(n,pad){n=""+n;pad=""+(pad==null?"0":pad);return n.length==1?pad+n:n;};var r=[];var escape=false;var hours=d.getHours();var isAM=hours<12;if(monthNames==null){monthNames=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];} -if(dayNames==null){dayNames=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];} -var hours12;if(hours>12){hours12=hours-12;}else if(hours==0){hours12=12;}else{hours12=hours;} -for(var i=0;i=minSize){break;}} -var size=spec[i][0];var unit=spec[i][1];if(unit=="year"){if(opts.minTickSize!=null&&opts.minTickSize[1]=="year"){size=Math.floor(opts.minTickSize[0]);}else{var magn=Math.pow(10,Math.floor(Math.log(axis.delta/timeUnitSize.year)/Math.LN10));var norm=(axis.delta/timeUnitSize.year)/magn;if(norm<1.5){size=1;}else if(norm<3){size=2;}else if(norm<7.5){size=5;}else{size=10;} -size*=magn;} -if(size<1){size=1;}} -axis.tickSize=opts.tickSize||[size,unit];var tickSize=axis.tickSize[0];unit=axis.tickSize[1];var step=tickSize*timeUnitSize[unit];if(unit=="second"){d.setSeconds(floorInBase(d.getSeconds(),tickSize));}else if(unit=="minute"){d.setMinutes(floorInBase(d.getMinutes(),tickSize));}else if(unit=="hour"){d.setHours(floorInBase(d.getHours(),tickSize));}else if(unit=="month"){d.setMonth(floorInBase(d.getMonth(),tickSize));}else if(unit=="quarter"){d.setMonth(3*floorInBase(d.getMonth()/3,tickSize));}else if(unit=="year"){d.setFullYear(floorInBase(d.getFullYear(),tickSize));} -d.setMilliseconds(0);if(step>=timeUnitSize.minute){d.setSeconds(0);} -if(step>=timeUnitSize.hour){d.setMinutes(0);} -if(step>=timeUnitSize.day){d.setHours(0);} -if(step>=timeUnitSize.day*4){d.setDate(1);} -if(step>=timeUnitSize.month*2){d.setMonth(floorInBase(d.getMonth(),3));} -if(step>=timeUnitSize.quarter*2){d.setMonth(floorInBase(d.getMonth(),6));} -if(step>=timeUnitSize.year){d.setMonth(0);} -var carry=0;var v=Number.NaN;var prev;do{prev=v;v=d.getTime();ticks.push(v);if(unit=="month"||unit=="quarter"){if(tickSize<1){d.setDate(1);var start=d.getTime();d.setMonth(d.getMonth()+ -(unit=="quarter"?3:1));var end=d.getTime();d.setTime(v+carry*timeUnitSize.hour+(end-start)*tickSize);carry=d.getHours();d.setHours(0);}else{d.setMonth(d.getMonth()+ -tickSize*(unit=="quarter"?3:1));}}else if(unit=="year"){d.setFullYear(d.getFullYear()+tickSize);}else{d.setTime(v+step);}}while(vw)&&w>0){nw=w;nh=(w/$obj.width())*$obj.height();} -if((nh>h)&&h>0){nh=h;nw=(h/$obj.height())*$obj.width();} -xscale=$obj.width()/nw;yscale=$obj.height()/nh;$obj.width(nw).height(nh);} -function unscale(c) -{return{x:c.x*xscale,y:c.y*yscale,x2:c.x2*xscale,y2:c.y2*yscale,w:c.w*xscale,h:c.h*yscale};} -function doneSelect(pos) -{var c=Coords.getFixed();if((c.w>options.minSelect[0])&&(c.h>options.minSelect[1])){Selection.enableHandles();Selection.done();}else{Selection.release();} -Tracker.setCursor(options.allowSelect?'crosshair':'default');} -function newSelection(e) -{if(options.disabled){return false;} -if(!options.allowSelect){return false;} -btndown=true;docOffset=getPos($img);Selection.disableHandles();Tracker.setCursor('crosshair');var pos=mouseAbs(e);Coords.setPressed(pos);Selection.update();Tracker.activateHandlers(selectDrag,doneSelect,e.type.substring(0,5)==='touch');KeyManager.watchKeys();e.stopPropagation();e.preventDefault();return false;} -function selectDrag(pos) -{Coords.setCurrent(pos);Selection.update();} -function newTracker() -{var trk=$('
').addClass(cssClass('tracker'));if(is_msie){trk.css({opacity:0,backgroundColor:'white'});} -return trk;} -if(typeof(obj)!=='object'){obj=$(obj)[0];} -if(typeof(opt)!=='object'){opt={};} -setOptions(opt);var img_css={border:'none',visibility:'visible',margin:0,padding:0,position:'absolute',top:0,left:0};var $origimg=$(obj),img_mode=true;if(obj.tagName=='IMG'){if($origimg[0].width!=0&&$origimg[0].height!=0){$origimg.width($origimg[0].width);$origimg.height($origimg[0].height);}else{var tempImage=new Image();tempImage.src=$origimg[0].src;$origimg.width(tempImage.width);$origimg.height(tempImage.height);} -var $img=$origimg.clone().removeAttr('id').css(img_css).show();$img.width($origimg.width());$img.height($origimg.height());$origimg.after($img).hide();}else{$img=$origimg.css(img_css).show();img_mode=false;if(options.shade===null){options.shade=true;}} -presize($img,options.boxWidth,options.boxHeight);var boundx=$img.width(),boundy=$img.height(),$div=$('
').width(boundx).height(boundy).addClass(cssClass('holder')).css({position:'relative',backgroundColor:options.bgColor}).insertAfter($origimg).append($img);if(options.addClass){$div.addClass(options.addClass);} -var $img2=$('
'),$img_holder=$('
').width('100%').height('100%').css({zIndex:310,position:'absolute',overflow:'hidden'}),$hdl_holder=$('
').width('100%').height('100%').css('zIndex',320),$sel=$('
').css({position:'absolute',zIndex:600}).dblclick(function(){var c=Coords.getFixed();options.onDblClick.call(api,c);}).insertBefore($img).append($img_holder,$hdl_holder);if(img_mode){$img2=$('').attr('src',$img.attr('src')).css(img_css).width(boundx).height(boundy),$img_holder.append($img2);} -if(ie6mode){$sel.css({overflowY:'hidden'});} -var bound=options.boundary;var $trk=newTracker().width(boundx+(bound*2)).height(boundy+(bound*2)).css({position:'absolute',top:px(-bound),left:px(-bound),zIndex:290}).mousedown(newSelection);var bgcolor=options.bgColor,bgopacity=options.bgOpacity,xlimit,ylimit,xmin,ymin,xscale,yscale,enabled=true,btndown,animating,shift_down;docOffset=getPos($img);var Touch=(function(){function hasTouchSupport(){var support={},events=['touchstart','touchmove','touchend'],el=document.createElement('div'),i;try{for(i=0;ix1+ox){ox-=ox+x1;} -if(0>y1+oy){oy-=oy+y1;} -if(boundyboundx){xx=boundx;h=Math.abs((xx-x1)/aspect);yy=rh<0?y1-h:h+y1;}}else{xx=x2;h=rwa/aspect;yy=rh<0?y1-h:y1+h;if(yy<0){yy=0;w=Math.abs((yy-y1)*aspect);xx=rw<0?x1-w:w+x1;}else if(yy>boundy){yy=boundy;w=Math.abs(yy-y1)*aspect;xx=rw<0?x1-w:w+x1;}} -if(xx>x1){if(xx-x1max_x){xx=x1+max_x;} -if(yy>y1){yy=y1+(xx-x1)/aspect;}else{yy=y1-(xx-x1)/aspect;}}else if(xxmax_x){xx=x1-max_x;} -if(yy>y1){yy=y1+(x1-xx)/aspect;}else{yy=y1-(x1-xx)/aspect;}} -if(xx<0){x1-=xx;xx=0;}else if(xx>boundx){x1-=xx-boundx;xx=boundx;} -if(yy<0){y1-=yy;yy=0;}else if(yy>boundy){y1-=yy-boundy;yy=boundy;} -return makeObj(flipCoords(x1,y1,xx,yy));} -function rebound(p) -{if(p[0]<0)p[0]=0;if(p[1]<0)p[1]=0;if(p[0]>boundx)p[0]=boundx;if(p[1]>boundy)p[1]=boundy;return[Math.round(p[0]),Math.round(p[1])];} -function flipCoords(x1,y1,x2,y2) -{var xa=x1,xb=x2,ya=y1,yb=y2;if(x2xlimit)){x2=(xsize>0)?(x1+xlimit):(x1-xlimit);} -if(ylimit&&(Math.abs(ysize)>ylimit)){y2=(ysize>0)?(y1+ylimit):(y1-ylimit);} -if(ymin/yscale&&(Math.abs(ysize)0)?(y1+ymin/yscale):(y1-ymin/yscale);} -if(xmin/xscale&&(Math.abs(xsize)0)?(x1+xmin/xscale):(x1-xmin/xscale);} -if(x1<0){x2-=x1;x1-=x1;} -if(y1<0){y2-=y1;y1-=y1;} -if(x2<0){x1-=x2;x2-=x2;} -if(y2<0){y1-=y2;y2-=y2;} -if(x2>boundx){delta=x2-boundx;x1-=delta;x2-=delta;} -if(y2>boundy){delta=y2-boundy;y1-=delta;y2-=delta;} -if(x1>boundx){delta=x1-boundy;y2-=delta;y1-=delta;} -if(y1>boundy){delta=y1-boundy;y2-=delta;y1-=delta;} -return makeObj(flipCoords(x1,y1,x2,y2));} -function makeObj(a) -{return{x:a[0],y:a[1],x2:a[2],y2:a[3],w:a[2]-a[0],h:a[3]-a[1]};} -return{flipCoords:flipCoords,setPressed:setPressed,setCurrent:setCurrent,getOffset:getOffset,moveOffset:moveOffset,getCorner:getCorner,getFixed:getFixed};}());var Shade=(function(){var enabled=false,holder=$('
').css({position:'absolute',zIndex:240,opacity:0}),shades={top:createShade(),left:createShade().height(boundy),right:createShade().height(boundy),bottom:createShade()};function resizeShades(w,h){shades.left.css({height:px(h)});shades.right.css({height:px(h)});} -function updateAuto() -{return updateShade(Coords.getFixed());} -function updateShade(c) -{shades.top.css({left:px(c.x),width:px(c.w),height:px(c.y)});shades.bottom.css({top:px(c.y2),left:px(c.x),width:px(c.w),height:px(boundy-c.y2)});shades.right.css({left:px(c.x2),width:px(boundx-c.x2)});shades.left.css({width:px(c.x)});} -function createShade(){return $('
').css({position:'absolute',backgroundColor:options.shadeColor||options.bgColor}).appendTo(holder);} -function enableShade(){if(!enabled){enabled=true;holder.insertBefore($img);updateAuto();Selection.setBgOpacity(1,0,1);$img2.hide();setBgColor(options.shadeColor||options.bgColor,1);if(Selection.isAwake()) -{setOpacity(options.bgOpacity,1);} -else setOpacity(1,1);}} -function setBgColor(color,now){colorChangeMacro(getShades(),color,now);} -function disableShade(){if(enabled){holder.remove();$img2.show();enabled=false;if(Selection.isAwake()){Selection.setBgOpacity(options.bgOpacity,1,1);}else{Selection.setBgOpacity(1,1,1);Selection.disableHandles();} -colorChangeMacro($div,0,1);}} -function setOpacity(opacity,now){if(enabled){if(options.bgFade&&!now){holder.animate({opacity:1-opacity},{queue:false,duration:options.fadeTime});} -else holder.css({opacity:1-opacity});}} -function refreshAll(){options.shade?enableShade():disableShade();if(Selection.isAwake())setOpacity(options.bgOpacity);} -function getShades(){return holder.children();} -return{update:updateAuto,updateRaw:updateShade,getShades:getShades,setBgColor:setBgColor,enable:enableShade,disable:disableShade,resize:resizeShades,refresh:refreshAll,opacity:setOpacity};}());var Selection=(function(){var awake,hdep=370,borders={},handle={},dragbar={},seehandles=false;function insertBorder(type) -{var jq=$('
').css({position:'absolute',opacity:options.borderOpacity}).addClass(cssClass(type));$img_holder.append(jq);return jq;} -function dragDiv(ord,zi) -{var jq=$('
').mousedown(createDragger(ord)).css({cursor:ord+'-resize',position:'absolute',zIndex:zi}).addClass('ord-'+ord);if(Touch.support){jq.bind('touchstart.jcrop',Touch.createDragger(ord));} -$hdl_holder.append(jq);return jq;} -function insertHandle(ord) -{var hs=options.handleSize,div=dragDiv(ord,hdep++).css({opacity:options.handleOpacity}).addClass(cssClass('handle'));if(hs){div.width(hs).height(hs);} -return div;} -function insertDragbar(ord) -{return dragDiv(ord,hdep++).addClass('jcrop-dragbar');} -function createDragbars(li) -{var i;for(i=0;i').css({position:'fixed',left:'-120px',width:'12px'}).addClass('jcrop-keymgr'),$keywrap=$('
').css({position:'absolute',overflow:'hidden'}).append($keymgr);function watchKeys() -{if(options.keySupport){$keymgr.show();$keymgr.focus();}} -function onBlur(e) -{$keymgr.hide();} -function doNudge(e,x,y) -{if(options.allowMove){Coords.moveOffset([x,y]);Selection.updateVisible(true);} -e.preventDefault();e.stopPropagation();} -function parseKey(e) -{if(e.ctrlKey||e.metaKey){return true;} -shift_down=e.shiftKey?true:false;var nudge=shift_down?10:1;switch(e.keyCode){case 37:doNudge(e,-nudge,0);break;case 39:doNudge(e,nudge,0);break;case 38:doNudge(e,0,-nudge);break;case 40:doNudge(e,0,nudge);break;case 27:if(options.allowSelect)Selection.release();break;case 9:return true;} -return false;} -if(options.keySupport){$keymgr.keydown(parseKey).blur(onBlur);if(ie6mode||!options.fixedSupport){$keymgr.css({position:'absolute',left:'-20px'});$keywrap.append($keymgr).insertBefore($img);}else{$keymgr.insertBefore($img);}} -return{watchKeys:watchKeys};}());function setClass(cname) -{$div.removeClass().addClass(cssClass('holder')).addClass(cname);} -function animateTo(a,callback) -{var x1=a[0]/xscale,y1=a[1]/yscale,x2=a[2]/xscale,y2=a[3]/yscale;if(animating){return;} -var animto=Coords.flipCoords(x1,y1,x2,y2),c=Coords.getFixed(),initcr=[c.x,c.y,c.x2,c.y2],animat=initcr,interv=options.animationDelay,ix1=animto[0]-initcr[0],iy1=animto[1]-initcr[1],ix2=animto[2]-initcr[2],iy2=animto[3]-initcr[3],pcent=0,velocity=options.swingSpeed;x1=animat[0];y1=animat[1];x2=animat[2];y2=animat[3];Selection.animMode(true);var anim_timer;function queueAnimator(){window.setTimeout(animator,interv);} -var animator=(function(){return function(){pcent+=(100-pcent)/velocity;animat[0]=Math.round(x1+((pcent/100)*ix1));animat[1]=Math.round(y1+((pcent/100)*iy1));animat[2]=Math.round(x2+((pcent/100)*ix2));animat[3]=Math.round(y2+((pcent/100)*iy2));if(pcent>=99.8){pcent=100;} -if(pcent<100){setSelectRaw(animat);queueAnimator();}else{Selection.done();Selection.animMode(false);if(typeof(callback)==='function'){callback.call(api);}}};}());queueAnimator();} -function setSelect(rect) -{setSelectRaw([rect[0]/xscale,rect[1]/yscale,rect[2]/xscale,rect[3]/yscale]);options.onSelect.call(api,unscale(Coords.getFixed()));Selection.enableHandles();} -function setSelectRaw(l) -{Coords.setPressed([l[0],l[1]]);Coords.setCurrent([l[2],l[3]]);Selection.update();} -function tellSelect() -{return unscale(Coords.getFixed());} -function tellScaled() -{return Coords.getFixed();} -function setOptionsNew(opt) -{setOptions(opt);interfaceUpdate();} -function disableCrop() -{options.disabled=true;Selection.disableHandles();Selection.setCursor('default');Tracker.setCursor('default');} -function enableCrop() -{options.disabled=false;interfaceUpdate();} -function cancelCrop() -{Selection.done();Tracker.activateHandlers(null,null);} -function destroy() -{$(document).unbind('touchstart.jcrop-ios',Touch.fixTouchSupport);$div.remove();$origimg.show();$origimg.css('visibility','visible');$(obj).removeData('Jcrop');} -function setImage(src,callback) -{Selection.release();disableCrop();var img=new Image();img.onload=function(){var iw=img.width;var ih=img.height;var bw=options.boxWidth;var bh=options.boxHeight;$img.width(iw).height(ih);$img.attr('src',src);$img2.attr('src',src);presize($img,bw,bh);boundx=$img.width();boundy=$img.height();$img2.width(boundx).height(boundy);$trk.width(boundx+(bound*2)).height(boundy+(bound*2));$div.width(boundx).height(boundy);Shade.resize(boundx,boundy);enableCrop();if(typeof(callback)==='function'){callback.call(api);}};img.src=src;} -function colorChangeMacro($obj,color,now){var mycolor=color||options.bgColor;if(options.bgFade&&supportsColorFade()&&options.fadeTime&&!now){$obj.animate({backgroundColor:mycolor},{queue:false,duration:options.fadeTime});}else{$obj.css('backgroundColor',mycolor);}} -function interfaceUpdate(alt) -{if(options.allowResize){if(alt){Selection.enableOnly();}else{Selection.enableHandles();}}else{Selection.disableHandles();} -Tracker.setCursor(options.allowSelect?'crosshair':'default');Selection.setCursor(options.allowMove?'move':'default');if(options.hasOwnProperty('trueSize')){xscale=options.trueSize[0]/boundx;yscale=options.trueSize[1]/boundy;} -if(options.hasOwnProperty('setSelect')){setSelect(options.setSelect);Selection.done();delete(options.setSelect);} -Shade.refresh();if(options.bgColor!=bgcolor){colorChangeMacro(options.shade?Shade.getShades():$div,options.shade?(options.shadeColor||options.bgColor):options.bgColor);bgcolor=options.bgColor;} -if(bgopacity!=options.bgOpacity){bgopacity=options.bgOpacity;if(options.shade)Shade.refresh();else Selection.setBgOpacity(bgopacity);} -xlimit=options.maxSize[0]||0;ylimit=options.maxSize[1]||0;xmin=options.minSize[0]||0;ymin=options.minSize[1]||0;if(options.hasOwnProperty('outerImage')){$img.attr('src',options.outerImage);delete(options.outerImage);} -Selection.refresh();} -if(Touch.support)$trk.bind('touchstart.jcrop',Touch.newSelection);$hdl_holder.hide();interfaceUpdate(true);var api={setImage:setImage,animateTo:animateTo,setSelect:setSelect,setOptions:setOptionsNew,tellSelect:tellSelect,tellScaled:tellScaled,setClass:setClass,disable:disableCrop,enable:enableCrop,cancel:cancelCrop,release:Selection.release,destroy:destroy,focus:KeyManager.watchKeys,getBounds:function(){return[boundx*xscale,boundy*yscale];},getWidgetSize:function(){return[boundx,boundy];},getScaleFactor:function(){return[xscale,yscale];},getOptions:function(){return options;},ui:{holder:$div,selection:$sel}};if(is_msie)$div.bind('selectstart',function(){return false;});$origimg.data('Jcrop',api);return api;};$.fn.Jcrop=function(options,callback) -{var api;this.each(function(){if($(this).data('Jcrop')){if(options==='api')return $(this).data('Jcrop');else $(this).data('Jcrop').setOptions(options);} -else{if(this.tagName=='IMG') -$.Jcrop.Loader(this,function(){$(this).css({display:'block',visibility:'hidden'});api=$.Jcrop(this,options);if($.isFunction(callback))callback.call(api);});else{$(this).css({display:'block',visibility:'hidden'});api=$.Jcrop(this,options);if($.isFunction(callback))callback.call(api);}}});return this;};$.Jcrop.Loader=function(imgobj,success,error){var $img=$(imgobj),img=$img[0];function completeCheck(){if(img.complete){$img.unbind('.jcloader');if($.isFunction(success))success.call(img);} -else window.setTimeout(completeCheck,50);} -$img.bind('load.jcloader',completeCheck).bind('error.jcloader',function(e){$img.unbind('.jcloader');if($.isFunction(error))error.call(img);});if(img.complete&&$.isFunction(success)){$img.unbind('.jcloader');success.call(img);}};$.Jcrop.defaults={allowSelect:true,allowMove:true,allowResize:true,trackDocument:true,baseClass:'jcrop',addClass:null,bgColor:'black',bgOpacity:0.6,bgFade:false,borderOpacity:0.4,handleOpacity:0.5,handleSize:null,aspectRatio:0,keySupport:true,createHandles:['n','s','e','w','nw','ne','se','sw'],createDragbars:['n','s','e','w'],createBorders:['n','s','e','w'],drawBorders:true,dragEdges:true,fixedSupport:true,touchSupport:null,shade:null,boxWidth:0,boxHeight:0,boundary:2,fadeTime:400,animationDelay:20,swingSpeed:3,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){},onDblClick:function(){},onRelease:function(){}};}(jQuery)); \ No newline at end of file +$(document).on('click.bs.dropdown.data-api',clearMenus).on('click.bs.dropdown.data-api','.dropdown form',function(e){e.stopPropagation()}).on('click.bs.dropdown.data-api',toggle,Dropdown.prototype.toggle).on('keydown.bs.dropdown.data-api',toggle+', [role=menu], [role=listbox]',Dropdown.prototype.keydown)}(jQuery); \ No newline at end of file diff --git a/modules/backend/assets/js/vendor/vendor.js b/modules/backend/assets/js/vendor/vendor.js index dd5595269..d09b01726 100644 --- a/modules/backend/assets/js/vendor/vendor.js +++ b/modules/backend/assets/js/vendor/vendor.js @@ -25,6 +25,7 @@ =require ../../../../../modules/system/assets/vendor/bootstrap/js/tab.js =require ../../../../../modules/system/assets/vendor/bootstrap/js/transition.js =require ../../../../../modules/system/assets/vendor/bootstrap/js/dropdown.js +=require ../../../../../modules/system/assets/vendor/bootstrap/js/collapse.js =require ../../vendor/flot/jquery.flot.js =require ../../vendor/flot/jquery.flot.tooltip.js diff --git a/modules/backend/assets/less/controls/forms.less b/modules/backend/assets/less/controls/forms.less index ed1f53574..9dcff95c0 100644 --- a/modules/backend/assets/less/controls/forms.less +++ b/modules/backend/assets/less/controls/forms.less @@ -229,10 +229,37 @@ label { padding-top: 3px; padding-bottom: 7px; + > h4 { + color: rgba(0,0,0,.6); + } + > p:first-child, > h4:first-child { margin: 0; } + + &.is-collapsible { + cursor: pointer; + + > h4:before { + // Icon + display: inline-block; + .icon-FontAutumn(); + vertical-align: baseline; + content: @caret-down; + + margin: 0 8px; + float: right; + color: rgba(0,0,0,.4); + } + + &:hover { + border-bottom: 1px solid darken(@color-form-field-border, 10%); + > h4:before { + color: inherit; + } + } + } } .field-textarea { diff --git a/modules/backend/classes/AuthManager.php b/modules/backend/classes/AuthManager.php index bf84a20cf..d77a3d0c0 100644 --- a/modules/backend/classes/AuthManager.php +++ b/modules/backend/classes/AuthManager.php @@ -31,7 +31,7 @@ class AuthManager extends RainAuthManager 'code' => null, 'label' => null, 'comment' => null, - 'order' => 100, + 'order' => 500 ]; /** @@ -91,7 +91,7 @@ class AuthManager extends RainAuthManager } /** - * Returns a list of the main menu items. + * Returns a list of the registered permissions items. * @return array */ public function listPermissions() @@ -134,4 +134,24 @@ class AuthManager extends RainAuthManager return $this->permissionCache = $this->permissions; } + + /** + * Returns an array of registered permissions, grouped by tabs. + * @return array + */ + public function listTabbedPermissions() + { + $tabs = []; + + foreach ($this->listPermissions() as $permission) { + $tab = isset($permission->tab) ? $permission->tab : null; + if (!array_key_exists($tab, $tabs)) { + $tabs[$tab] = []; + } + + $tabs[$tab][] = $permission; + } + + return $tabs; + } } diff --git a/modules/backend/classes/NavigationManager.php b/modules/backend/classes/NavigationManager.php index 1957b3bf7..23b55dae3 100644 --- a/modules/backend/classes/NavigationManager.php +++ b/modules/backend/classes/NavigationManager.php @@ -36,7 +36,7 @@ class NavigationManager 'icon' => null, 'url' => null, 'permissions' => [], - 'order' => 100, + 'order' => 500, 'sideMenu' => [] ]; diff --git a/modules/backend/controllers/UserGroups.php b/modules/backend/controllers/UserGroups.php index 0eb6c4f9a..a9e48987c 100644 --- a/modules/backend/controllers/UserGroups.php +++ b/modules/backend/controllers/UserGroups.php @@ -33,25 +33,49 @@ class UserGroups extends Controller /** * Add available permission fields to the Group form. */ - protected function formExtendFields($host) + protected function formExtendFields($form) + { + /* + * Add permissions tab + */ + $form->addTabFields($this->generatePermissionFields()); + } + + /** + * Generates an array of form fields to assign permissions provided + * by the system. + * @return array + */ + protected function generatePermissionFields() { $permissionFields = []; - foreach (BackendAuth::listPermissions() as $permission) { - $fieldName = 'permissions['.$permission->code.']'; + foreach (BackendAuth::listTabbedPermissions() as $tab => $permissions) { + + $fieldName = 'permissions_'.snake_case($tab).'_section'; $fieldConfig = [ - 'label' => $permission->label, - 'comment' => $permission->comment, - 'type' => 'checkbox', + 'label' => $tab, + 'type' => 'section', + 'tab' => 'backend::lang.user.permissions', + 'containerAttributes' => ['data-field-collapsible' => 1] ]; - if (isset($permission->tab)) { - $fieldConfig['tab'] = $permission->tab; - } - $permissionFields[$fieldName] = $fieldConfig; + + foreach ($permissions as $permission) { + $fieldName = 'permissions['.$permission->code.']'; + $fieldConfig = [ + 'label' => $permission->label, + 'comment' => $permission->comment, + 'type' => 'checkbox', + 'span' => 'auto', + 'tab' => 'backend::lang.user.permissions' + ]; + + $permissionFields[$fieldName] = $fieldConfig; + } } - $host->addTabFields($permissionFields); + return $permissionFields; } } diff --git a/modules/backend/controllers/Users.php b/modules/backend/controllers/Users.php index 1d0d5d478..9f5ddbf77 100644 --- a/modules/backend/controllers/Users.php +++ b/modules/backend/controllers/Users.php @@ -94,35 +94,10 @@ class Users extends Controller return; } - $permissionFields = []; - foreach (BackendAuth::listPermissions() as $permission) { - - $fieldName = 'permissions['.$permission->code.']'; - $fieldConfig = [ - 'label' => $permission->label, - 'comment' => $permission->comment, - 'type' => 'balloon-selector', - 'options' => [ - 1 => 'backend::lang.user.allow', - 0 => 'backend::lang.user.inherit', - -1 => 'backend::lang.user.deny', - ], - 'attributes' => [ - 'data-trigger-action' => 'disable', - 'data-trigger' => "input[name='User[permissions][superuser]']", - 'data-trigger-condition' => 'checked', - ], - 'span' => 'auto', - ]; - - if (isset($permission->tab)) { - $fieldConfig['tab'] = $permission->tab; - } - - $permissionFields[$fieldName] = $fieldConfig; - } - - $form->addTabFields($permissionFields); + /* + * Add permissions tab + */ + $form->addTabFields($this->generatePermissionFields()); /* * Mark default groups @@ -134,4 +109,54 @@ class Users extends Controller $groupField->value = $defaultGroupIds; } } + + /** + * Generates an array of form fields to assign permissions provided + * by the system. + * @return array + */ + protected function generatePermissionFields() + { + $permissionFields = []; + + foreach (BackendAuth::listTabbedPermissions() as $tab => $permissions) { + + $fieldName = 'permissions_'.snake_case($tab).'_section'; + $fieldConfig = [ + 'label' => $tab, + 'type' => 'section', + 'tab' => 'backend::lang.user.permissions', + 'containerAttributes' => [ + 'data-field-collapsible' => 1 + ], + ]; + + $permissionFields[$fieldName] = $fieldConfig; + + foreach ($permissions as $permission) { + $fieldName = 'permissions['.$permission->code.']'; + $fieldConfig = [ + 'label' => $permission->label, + 'comment' => $permission->comment, + 'type' => 'balloon-selector', + 'options' => [ + 1 => 'backend::lang.user.allow', + 0 => 'backend::lang.user.inherit', + -1 => 'backend::lang.user.deny', + ], + 'trigger' => [ + 'action' => 'disable', + 'field' => 'permissions[superuser]', + 'condition' => 'checked' + ], + 'span' => 'auto', + 'tab' => 'backend::lang.user.permissions', + ]; + + $permissionFields[$fieldName] = $fieldConfig; + } + } + + return $permissionFields; + } } diff --git a/modules/backend/lang/en/lang.php b/modules/backend/lang/en/lang.php index 5e2b152c7..c36728631 100644 --- a/modules/backend/lang/en/lang.php +++ b/modules/backend/lang/en/lang.php @@ -81,15 +81,16 @@ return [ 'full_name' => 'Full Name', 'email' => 'Email', 'groups' => 'Groups', - 'groups_comment' => 'Specify which groups this person belongs to.', + 'groups_comment' => 'Specify which groups this account should belong to.', 'avatar' => 'Avatar', 'password' => 'Password', 'password_confirmation' => 'Confirm Password', 'permissions' => 'Permissions', + 'account' => 'Account', 'superuser' => 'Super User', - 'superuser_comment' => 'Check this box to allow this person to access all areas.', + 'superuser_comment' => 'Grants this account unlimited access to all areas.', 'send_invite' => 'Send invitation by email', - 'send_invite_comment' => 'Use this checkbox to send an invitation to the user by email', + 'send_invite_comment' => 'Sends a welcome message containing login and password information.', 'delete_confirm' => 'Do you really want to delete this administrator?', 'return' => 'Return to the administrator list', 'allow' => 'Allow', @@ -99,7 +100,7 @@ return [ 'name' => 'Group', 'name_field' => 'Name', 'description_field' => 'Description', - 'is_new_user_default_field' => 'Add new administrators to this group by default', + 'is_new_user_default_field' => 'Add new administrators to this group by default.', 'code_field' => 'Code', 'code_comment' => 'Enter a unique code if you want to access it with the API.', 'menu_label' => 'Groups', diff --git a/modules/backend/models/user/columns.yaml b/modules/backend/models/user/columns.yaml index 4bdec362f..532ea88f4 100644 --- a/modules/backend/models/user/columns.yaml +++ b/modules/backend/models/user/columns.yaml @@ -3,22 +3,31 @@ # =================================== columns: - login: - label: backend::lang.user.login - searchable: true first_name: label: backend::lang.user.first_name searchable: true + invisible: true + last_name: label: backend::lang.user.last_name searchable: true + invisible: true + full_name: label: backend::lang.user.full_name select: concat(first_name, ' ', last_name) searchable: true + invisible: true + + login: + label: backend::lang.user.login + searchable: true + width: 15% + email: label: backend::lang.user.email searchable: true + groups: label: backend::lang.user.groups relation: groups diff --git a/modules/backend/models/user/fields.yaml b/modules/backend/models/user/fields.yaml index 4708a1e46..f963ab325 100644 --- a/modules/backend/models/user/fields.yaml +++ b/modules/backend/models/user/fields.yaml @@ -3,55 +3,56 @@ # =================================== fields: - first_name: - span: left - label: backend::lang.user.first_name - - last_name: - span: right - label: backend::lang.user.last_name - - login: - span: left - label: backend::lang.user.login - - email: - span: right - label: backend::lang.user.email - - password: - type: password - span: left - label: backend::lang.user.password - - password_confirmation: - type: password - span: right - label: backend::lang.user.password_confirmation - - send_invite: - context: create - type: checkbox - label: backend::lang.user.send_invite - comment: backend::lang.user.send_invite_comment + permissions[superuser]: + context: [create, update] + tab: backend::lang.user.permissions + label: backend::lang.user.superuser + type: switch + comment: backend::lang.user.superuser_comment tabs: + defaultTab: backend::lang.user.account fields: + login: + span: left + label: backend::lang.user.login - permissions[superuser]: - context: [create, update] - tab: backend::lang.user.permissions - label: backend::lang.user.superuser + email: + span: right + label: backend::lang.user.email + + send_invite: + context: create type: checkbox - comment: backend::lang.user.superuser_comment + label: backend::lang.user.send_invite + comment: backend::lang.user.send_invite_comment + default: true + + first_name: + span: left + label: backend::lang.user.first_name + + last_name: + span: right + label: backend::lang.user.last_name + + password: + type: password + span: left + label: backend::lang.user.password + + password_confirmation: + type: password + span: right + label: backend::lang.user.password_confirmation groups: context: [create, update] - tab: backend::lang.user.permissions label: backend::lang.user.groups commentAbove: backend::lang.user.groups_comment type: checkboxlist + secondaryTabs: fields: @@ -61,3 +62,4 @@ secondaryTabs: mode: image imageHeight: 260 imageWidth: 260 + diff --git a/modules/backend/models/usergroup/fields.yaml b/modules/backend/models/usergroup/fields.yaml index 1e382e750..10dda15b4 100644 --- a/modules/backend/models/usergroup/fields.yaml +++ b/modules/backend/models/usergroup/fields.yaml @@ -3,6 +3,9 @@ # =================================== fields: + is_new_user_default: + label: backend::lang.user.group.is_new_user_default_field + type: checkbox name: label: backend::lang.user.group.name_field @@ -18,9 +21,5 @@ fields: type: textarea size: tiny - is_new_user_default: - label: backend::lang.user.group.is_new_user_default_field - type: checkbox - tabs: stretch: true diff --git a/modules/backend/widgets/form/assets/js/october.form.js b/modules/backend/widgets/form/assets/js/october.form.js index 67784ce11..7295da269 100644 --- a/modules/backend/widgets/form/assets/js/october.form.js +++ b/modules/backend/widgets/form/assets/js/october.form.js @@ -10,11 +10,13 @@ var $el = this.$el = $(element); + this.$form = $el.closest('form') this.options = options || {}; this.bindDependants() this.bindCheckboxlist() this.toggleEmptyTabs() + this.bindCollapsibleSections() } FormWidget.DEFAULTS = { @@ -49,7 +51,7 @@ FormWidget.prototype.bindDependants = function() { var self = this, form = this.$el, - formEl = form.closest('form'), + formEl = this.$form, fieldMap = {} /* @@ -88,6 +90,9 @@ }) } + /* + * Hides tabs that have no content + */ FormWidget.prototype.toggleEmptyTabs = function() { var tabControl = $('[data-control=tab]', this.$el) @@ -98,7 +103,24 @@ $('[data-target="#' + $(this).attr('id') + '"]', tabControl) .toggle(!!$('.form-group:not(:empty)', $(this)).length) }) + } + /* + * Makes sections collapsible by targeting every field after + * up until the next section + */ + FormWidget.prototype.bindCollapsibleSections = function() { + $('.section-field[data-field-collapsible]', this.$form) + .addClass('collapsed') + .find('.field-section:first') + .addClass('is-collapsible') + .end() + .on('click', function() { + $(this) + .toggleClass('collapsed') + .nextUntil('.section-field').toggle() + }) + .nextUntil('.section-field').hide() } // FORM WIDGET PLUGIN DEFINITION diff --git a/modules/cms/ServiceProvider.php b/modules/cms/ServiceProvider.php index 3605e5684..036a21ae0 100644 --- a/modules/cms/ServiceProvider.php +++ b/modules/cms/ServiceProvider.php @@ -156,27 +156,33 @@ class ServiceProvider extends ModuleServiceProvider $manager->registerPermissions('October.Cms', [ 'cms.manage_content' => [ 'label' => 'cms::lang.permissions.manage_content', - 'tab' => 'cms::lang.permissions.name' + 'tab' => 'cms::lang.permissions.name', + 'order' => 100 ], 'cms.manage_assets' => [ 'label' => 'cms::lang.permissions.manage_assets', - 'tab' => 'cms::lang.permissions.name' + 'tab' => 'cms::lang.permissions.name', + 'order' => 100 ], 'cms.manage_pages' => [ 'label' => 'cms::lang.permissions.manage_pages', - 'tab' => 'cms::lang.permissions.name' + 'tab' => 'cms::lang.permissions.name', + 'order' => 100 ], 'cms.manage_layouts' => [ 'label' => 'cms::lang.permissions.manage_layouts', - 'tab' => 'cms::lang.permissions.name' + 'tab' => 'cms::lang.permissions.name', + 'order' => 100 ], 'cms.manage_partials' => [ 'label' => 'cms::lang.permissions.manage_partials', - 'tab' => 'cms::lang.permissions.name' + 'tab' => 'cms::lang.permissions.name', + 'order' => 100 ], 'cms.manage_themes' => [ 'label' => 'cms::lang.permissions.manage_themes', - 'tab' => 'cms::lang.permissions.name' + 'tab' => 'cms::lang.permissions.name', + 'order' => 100 ] ]); });