Merge branch 'squash-test'
diff --git a/app/soc/content/js.min/bulk-review.js b/app/soc/content/js.min/bulk-review.js
deleted file mode 100644
index f0d982c..0000000
--- a/app/soc/content/js.min/bulk-review.js
+++ /dev/null
@@ -1,4 +0,0 @@
-jQuery(document).ready(function(){jQuery("#applications_progress_bar").progressBar({showText:false})});
-function bulkReview(b){var d=b.link,c=b.nr_applications,a=0,j=b.applications.length;setTimeout(function(){var g=false,h=b.applications[a],i=a+1,e=/\((\w*)\)/,k=d.match(e)[1];e=d.replace(e,h[k]);jQuery.ajax({async:false,cache:false,url:e,timeout:1E4,success:function(f){if(f){f=Math.floor(100*i/c);jQuery("#description_progressbar").html([" Processed application ",h.name," (",i,"/",c,")"].join(""));jQuery("#applications_progress_bar").progressBar(f)}},error:function(f,l,m){g=true;jQuery("[id^=button_bulk_]").fadeIn("slow",
-function(){jQuery("#description_done").html("<strong class='error'> Error encountered, try again</strong>")})}});if(!g){a++;if(a<j)setTimeout(arguments.callee,0);else{jQuery("#applications_progress_bar").fadeOut("slow",function(){jQuery("#applications_progress_bar").progressBar(0);jQuery("[id^=button_bulk_]").fadeIn("slow")});jQuery("#description_progressbar").html("");jQuery("#description_done").html("<strong>Done!</strong>")}}},0)}
-function bulkReviewInit(b,d){jQuery.getJSON(b+"?_="+(new Date).getTime(),function(c){if(c.nr_applications!==0)jQuery("[id^=button_bulk_]").fadeOut("slow",function(){jQuery("#applications_progress_bar").progressBar(0);jQuery("#description_done").html("");jQuery("#applications_progress_bar").fadeIn("slow",bulkReview(c))});else{var a="No organizations to ";a+=jQuery(d).attr("id").indexOf("reject")!==-1?"reject":"accept";jQuery("#description_done").html("<strong>"+a+"</strong>")}})};
diff --git a/app/soc/content/js.min/melange.dependency.js b/app/soc/content/js.min/melange.dependency.js
index a80f216..d3bbd53 100644
--- a/app/soc/content/js.min/melange.dependency.js
+++ b/app/soc/content/js.min/melange.dependency.js
@@ -1,12 +1,12 @@
-(function(){if(window.melange===undefined)throw new Error("Melange not loaded");var f=window.melange;f.dependency=window.melange.dependency=function(){return new f.dependency};var g=f.logging.debugDecorator(f.dependency);f.error.createErrors([]);g.templateWithContext=function(h,c){this.script_template=h;this.context=c};g.cssFile=function(h){this.css=h};var a={},b="/js/"+f.config.app_version+"/",e="/soc/content/"+f.config.app_version+"/js/",k="/"+f.config.css_path+"/";a.google=f.config.google_api_key!==
-undefined?["https://www.google.com/jsapi?key="+f.config.google_api_key]:["https://www.google.com/jsapi"];a.jquery=f.config.is_local!==undefined&&f.config.is_local===true?[b+"jquery/jquery-1.6.4.js"]:["https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"];a.json=[b+"json/json2.js"];a.tinymce=["/tiny_mce/tiny_mce.js"];a.purr=[b+"jquery/jquery-purr.js"];a.counter=[b+"jquery/jquery-counter.js"];a.spin=[b+"jquery/jquery-spin-1.1.1.js"];a.bgiframe=[b+"jquery/jquery-bgiframe.js"];a.ajaxQueue=
+(function(){if(window.melange===undefined)throw new Error("Melange not loaded");var e=window.melange;e.dependency=window.melange.dependency=function(){return new e.dependency};var g=e.logging.debugDecorator(e.dependency);e.error.createErrors([]);g.templateWithContext=function(h,c){this.script_template=h;this.context=c};g.cssFile=function(h){this.css=h};var a={},b="/js/"+e.config.app_version+"/",f="/soc/content/"+e.config.app_version+"/js/",k="/"+e.config.css_path+"/";a.google=e.config.google_api_key!==
+undefined?["https://www.google.com/jsapi?key="+e.config.google_api_key]:["https://www.google.com/jsapi"];a.jquery=e.config.is_local!==undefined&&e.config.is_local===true?[b+"jquery/jquery-1.6.4.js"]:["https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"];a.json=[b+"json/json2.js"];a.tinymce=["/tiny_mce/tiny_mce.js"];a.purr=[b+"jquery/jquery-purr.js"];a.counter=[b+"jquery/jquery-counter.js"];a.spin=[b+"jquery/jquery-spin-1.1.1.js"];a.bgiframe=[b+"jquery/jquery-bgiframe.js"];a.ajaxQueue=
[b+"jquery/jquery-ajaxQueue.js"];a.progressbar=[b+"jquery/jquery-progressbar.js"];a.uniform=[b+"jquery/jquery-uniform.js"];a.raty=[b+"jquery/jquery.raty.js"];a.cluetip=[b+"jquery/jquery.cluetip.js"];a.dimensions=[b+"jquery/jquery.dimensions.js"];a.scrollTo=[b+"jquery/jquery.scrollTo.js"];a.formbuilder=[a.scrollTo,null,b+"jquery/jquery.formbuilder.js"];a.hashchange=[b+"jquery/jquery.ba-hashchange.js"];a.dd=[b+"jquery/jquery.dd.js"];a.modernizr=[b+"modernizr/modernizr-svg.js"];a.jqueryui={};a.jqueryui.core=
-f.config.is_local!==undefined&&f.config.is_local===true?[new g.cssFile(k+"jquery-ui/jquery.ui.all.css"),b+"jquery/jquery-ui.core.js"]:[new g.cssFile(k+"jquery-ui/jquery.ui.merged.css"),b+"jquery/jquery-ui.core.js"];a.jqueryui.datepicker=[a.jqueryui.core,null,b+"jquery/jquery-ui.datepicker.js"];a.jqueryui.position=[a.jqueryui.core,null,b+"jquery/jquery-ui.position.js"];a.jqueryui.widget=[a.jqueryui.core,null,b+"jquery/jquery-ui.widget.js"];a.jqueryui.mouse=[a.jqueryui.core,null,b+"jquery/jquery-ui.mouse.js"];
+e.config.is_local!==undefined&&e.config.is_local===true?[new g.cssFile(k+"jquery-ui/jquery.ui.all.css"),b+"jquery/jquery-ui.core.js"]:[new g.cssFile(k+"jquery-ui/jquery.ui.merged.css"),b+"jquery/jquery-ui.core.js"];a.jqueryui.datepicker=[a.jqueryui.core,null,b+"jquery/jquery-ui.datepicker.js"];a.jqueryui.position=[a.jqueryui.core,null,b+"jquery/jquery-ui.position.js"];a.jqueryui.widget=[a.jqueryui.core,null,b+"jquery/jquery-ui.widget.js"];a.jqueryui.mouse=[a.jqueryui.core,null,b+"jquery/jquery-ui.mouse.js"];
a.jqueryui.button=[a.jqueryui.widget,null,b+"jquery/jquery-ui.button.js"];a.jqueryui.autocomplete=[a.jqueryui.position,a.jqueryui.widget,null,new g.cssFile(k+"jquery-ui/jquery.ui.autocomplete.css"),b+"jquery/jquery-ui.autocomplete.js"];a.jqueryui.dialog=[a.jqueryui.position,a.jqueryui.widget,null,b+"jquery/jquery-ui.dialog.js"];a.jqueryui.checkboxes=[a.jqueryui.core,b+"jquery/jquery.ui-checkboxes.js"];a.jqueryui.draggable=[a.jqueryui.widget,a.jqueryui.mouse,null,b+"jquery/jquery-ui.draggable.js"];
a.jqueryui.sortable=[a.jqueryui.widget,a.jqueryui.mouse,null,b+"jquery/jquery-ui.sortable.js"];a.jqueryui.effects=[b+"jquery/jquery-ui.effects.core.js"];a.jqueryui.effects.blind=[a.jqueryui.effects,null,b+"jquery/jquery-ui.effects.blind.js"];a.jqgrid=[a.jqueryui.core,a.jqueryui.dialog,a.jqueryui.draggable,a.jqueryui.sortable,null,new g.cssFile(k+"ui.multiselect.css"),b+"jquery/jquery-jqgrid.ui.multiselect.js",null,new g.cssFile(k+"ui.jqgrid.css"),b+"jquery/jquery-jqgrid.locale-en.js",null,b+"jquery/jquery-jqgrid.base.js",
null,b+"jquery/jquery-jqgrid.custom.js",b+"jquery/jquery-jqgrid.filter.js",b+"jquery/jquery-jqgrid.jqueryui.js"];a.jqgridediting=[a.jqgrid,null,b+"jquery/jquery-jqgrid.common.js",b+"jquery/jquery-jqgrid.fmatter.js",b+"jquery/jquery-jqgrid.formedit.js",null,b+"jquery/jquery-jqgrid.searchFilter.js",b+"jquery/jquery-jqgrid.inlinedit.js",null,b+"jquery/jquery-jqgrid.jqDnR.js",null,b+"jquery/jquery-jqgrid.jqModal.js"];a.cookie=[b+"jquery/jquery-cookie.js"];a.jquery.svg=[b+"jquery/jquery.svg.pack.js"];
-a.jlinq=[b+"jlinq/jLinq-2.2.1.js"];a.fileupload=[a.jqueryui.widget,b+"jquery/jquery.fileupload.js"];a.melange={};a.melange.main=[a.google,a.cookie,null,e+"melange.js"];a.melange.gdata={};a.melange.gdata.core=[e+"melange.gdata.core.js"];a.melange.datetimepicker=[a.jqueryui.datepicker,null,e+"melange.datetimepicker.js"];a.melange.duplicates=[a.progressbar,null,e+"duplicate-slots.js"];a.melange.form=[];a.melange.list=[a.jqgrid,a.jlinq,new g.cssFile(k+"others.css"),null,a.jqueryui.dialog,a.jqueryui.button,
-a.jqgridediting,null,e+"melange.list.js",null,e+"melange.list.cookie_service.js",e+"melange.list.process_data.js",null,function(){window.melange_list_queue!==undefined&&window.melange_list_queue instanceof Array&&jQuery.each(window.melange_list_queue,function(h,c){c()})}];a.melange.tooltip=[a.purr,null];a.melange.autocomplete=[a.jqueryui.autocomplete,null,e+"melange.autocomplete.js"];a.melange.graph=[a.google,null,e+"melange.graph.js"];a.melange.uploadform=[a.fileupload,null,e+"upload-form.js"];a.melange.blog=
-[a.google,null,e+"melange.blog.js"];a.melange.action=[a.dimensions,a.cluetip,a.jqueryui.checkboxes,null,e+"melange.action.js"];a.melange.map=[e+"melange.map.js"];a.melange.program_select=[e+"melange.program_select.js"];a.melange.dynamicoptions=[a.json,null,e+"melange.dynamicoptions.js"];a.melange.clock=[a.modernizr,a.jquery.svg,null,e+"melange.clock.js"];g.s=a;var m=function(h){for(var c=[],l=0,d=h.length;l<d;l++){var i=h[l];if(typeof i==="object"&&i instanceof Array){i=m(i);c=c.concat(i)}else c.push(i)}return c};
-g.loadScripts=function(h){h=m(h);for(var c=[],l=[],d=0,i=h.length;d<i;d++){var j=h[d];if(typeof j=="string")jQuery.inArray(j,c)===-1&&c.push(j);else if(j instanceof g.cssFile){if(jQuery.inArray(j.css,l)===-1){c.push(j);l.push(j.css)}}else c.push(j)}d=0;for(i=c.length;d<i;d++)if(typeof c[d]=="string")$LAB=$LAB.script(c[d]);else if(c[d])if(typeof c[d]=="object"&&c[d]instanceof g.templateWithContext)$LAB=$LAB.wait(function(n){return function(){f.templates.setContextToLast(n)}}(c[d].context)).script(c[d].script_template).wait();
-else if(typeof c[d]=="object"&&c[d]instanceof g.cssFile)jQuery("<link>",{href:c[d].css,media:"screen",rel:"stylesheet",type:"text/css"}).appendTo("head");else{if(typeof c[d]=="function")$LAB=$LAB.wait(c[d])}else $LAB=$LAB.wait()}})();
+a.jlinq=[b+"jlinq/jLinq-2.2.1.js"];a.fileupload=[a.jqueryui.widget,b+"jquery/jquery.fileupload.js"];a.melange={};a.melange.main=[a.google,a.cookie,null,f+"melange.js"];a.melange.gdata={};a.melange.gdata.core=[f+"melange.gdata.core.js"];a.melange.datetimepicker=[a.jqueryui.datepicker,null,f+"melange.datetimepicker.js"];a.melange.duplicates=[a.progressbar,null,f+"duplicate-slots.js"];a.melange.form=[];a.melange.list=[a.jqgrid,a.jlinq,new g.cssFile(k+"others.css"),null,a.jqueryui.dialog,a.jqueryui.button,
+a.jqgridediting,null,f+"melange.list.js",null,f+"melange.list.cookie_service.js",f+"melange.list.process_data.js",null,function(){window.melange_list_queue!==undefined&&window.melange_list_queue instanceof Array&&jQuery.each(window.melange_list_queue,function(h,c){c()})}];a.melange.tooltip=[a.purr,null];a.melange.autocomplete=[a.jqueryui.autocomplete,null,f+"melange.autocomplete.js"];a.melange.uploadform=[a.fileupload,null,f+"upload-form.js"];a.melange.blog=[a.google,null,f+"melange.blog.js"];a.melange.action=
+[a.dimensions,a.cluetip,a.jqueryui.checkboxes,null,f+"melange.action.js"];a.melange.map=[f+"melange.map.js"];a.melange.program_select=[f+"melange.program_select.js"];a.melange.dynamicoptions=[a.json,null,f+"melange.dynamicoptions.js"];a.melange.clock=[a.modernizr,a.jquery.svg,null,f+"melange.clock.js"];g.s=a;var m=function(h){for(var c=[],l=0,d=h.length;l<d;l++){var i=h[l];if(typeof i==="object"&&i instanceof Array){i=m(i);c=c.concat(i)}else c.push(i)}return c};g.loadScripts=function(h){h=m(h);for(var c=
+[],l=[],d=0,i=h.length;d<i;d++){var j=h[d];if(typeof j=="string")jQuery.inArray(j,c)===-1&&c.push(j);else if(j instanceof g.cssFile){if(jQuery.inArray(j.css,l)===-1){c.push(j);l.push(j.css)}}else c.push(j)}d=0;for(i=c.length;d<i;d++)if(typeof c[d]=="string")$LAB=$LAB.script(c[d]);else if(c[d])if(typeof c[d]=="object"&&c[d]instanceof g.templateWithContext)$LAB=$LAB.wait(function(n){return function(){e.templates.setContextToLast(n)}}(c[d].context)).script(c[d].script_template).wait();else if(typeof c[d]==
+"object"&&c[d]instanceof g.cssFile)jQuery("<link>",{href:c[d].css,media:"screen",rel:"stylesheet",type:"text/css"}).appendTo("head");else{if(typeof c[d]=="function")$LAB=$LAB.wait(c[d])}else $LAB=$LAB.wait()}})();
diff --git a/app/soc/content/js.min/melange.graph.js b/app/soc/content/js.min/melange.graph.js
deleted file mode 100644
index 41c5696..0000000
--- a/app/soc/content/js.min/melange.graph.js
+++ /dev/null
@@ -1,20 +0,0 @@
-(function(){if(window.melange===undefined)throw new Error("Melange not loaded");var k=window.melange;k.graph=window.melange.graph=function(){return new k.graph};var i=k.logging.debugDecorator(k.graph);k.error.createErrors(["chartNotExistent","containerIsNull"]);i.allCharts={AreaChart:{public_name:"Area Chart",googlePackage:["areachart"]},BarChart:{public_name:"Bar Chart",googlePackage:["barchart"],default_options:{}},ColumnChart:{public_name:"Column Chart",googlePackage:["columnchart"],default_options:{}},
-GeoMap:{public_name:"Geo Map",googlePackage:["geomap"],default_options:{}},ImageChartBar:{public_name:"Bar Chart (I)",googlePackage:["imagechart"],default_options:{cht:"bvs"}},ImageChartLine:{public_name:"Line Chart (I)",googlePackage:["imagechart"],default_options:{cht:"lc"}},ImageChartMap:{public_name:"Map Chart (I)",googlePackage:["imagechart"],default_options:{cht:"t",chtm:"world"}},ImageChartP:{public_name:"Pie Chart (I)",googlePackage:["imagechart"],default_options:{cht:"p"}},ImageChartP3:{public_name:"3D Pie Chart (I)",
-googlePackage:["imagechart"],default_options:{cht:"p3"}},PieChart:{public_name:"Pie Chart",googlePackage:["piechart"],default_options:{is3D:true,pieJoinAngle:1}},ScatterChart:{public_name:"Scatter Chart",googlePackage:["scatterchart"],default_options:{}},Table:{public_name:"Table",googlePackage:["table"],default_options:{showRowNumber:true,page:"enable",pageSize:10}}};i.Widget=function(g,o){var r=this,p=["red","blue","green","yellow"],b=""+(new Date).getTime(),c={title:"Click to change me!",column:2,
-place:null,style:{head:{background:"#765364"},content:{color:"white"}},movable:"true",visible:"true",virtual_statistic:null},e={type:"PieChart",options:{showRowNumber:true}},t={comment:"New chart",data:{}},v={},s=null,H={},u=[],w=null;this.setData=function(a){t.data=a};this.getData=function(){return t.data};this.setWidgetOptions=function(a){c=a};this.getWidgetOptions=function(){return c};this.setVisualizationTypes=function(a){H=a};this.setVirtualStatistics=function(a){v=a};var I=function(){c.place=
-1+jQuery("#column3").find("li").size();c.style.head.background=p[Math.floor(Math.random()*p.length)];c.virtual_statistic=u[0];e.type="Table"},B=function(){u=[];jQuery.each(v,function(a){u.push(a)})};this.getId=function(){return b};var J=function(){jQuery.post("save_chart",{id:b,statistic_scope_path:g,statistic_link_id:o,widget_options:JSON.stringify(c),visualization_options:JSON.stringify(e)},function(){},"json")},x=function(){jQuery.post("update_chart",{data:JSON.stringify([{id:b,widget_options:JSON.stringify(c),
-visualization_options:JSON.stringify(e)}])},function(){},"json")},C=function(a){var d=""+(new Date).getTime();jQuery.post("save_visualization",{id:d,statistic_scope_path:g,statistic_link_id:o,widget_options:JSON.stringify(c),visualization_options:JSON.stringify(e)},function(){a.call(r,d)},"json")},y=function(){jQuery.ajax({async:false,url:["/statistic/get_json_response/",g,"/",o].join(""),type:"POST",data:{statistic_name:s},success:function(a){t.data=a},dataType:"json"})},D=function(){var a="";jQuery.each(v[s],
-function(d,h){a+="<option value='"+h+"'";if(h===e.type)a+=" selected='selected'";a+=[">",i.allCharts[h].public_name,"</option>"].join("")});return a},A=function(a,d){var h=/^(.*)\/show_dashboard/.exec(window.location.href)[1],m=/^\/(.*)\/show_dashboard/.exec(window.location.pathname)[1];jQuery("#export_"+b).remove();jQuery("#select_switch_visualization_"+b).after("<button id='export_"+b+"' value='Export'>Export</button>");var n=jQuery("#div_visualization_"+b).width(),q=jQuery("#div_visualization_"+
-b).width();if(a.indexOf("ImageChart")>=0){if(a==="ImageChartP")q=Math.ceil(n/2);else if(a==="ImageChartP3")q=Math.ceil(n/3);d.chs=n+"x"+q;jQuery("#export_"+b).bind("click",{visualization_div:"#div_visualization_"+b},function(f){var l=jQuery(jQuery(f.data.visualization_div+" img")[0]).attr("src");C(function(z){alert(['If you want to copy the current image, paste this: \n <img src="',l,"\">\n\nIf you want to embed the visualization, paste this to your page: \n<script type='text/javascript' src='https://www.google.com/jsapi'><\/script>\nIf you want to embed the LIVE visualization,\n<script type='text/javascript' src='",
-h,"/export?id=",b,"&path=",encodeURIComponent(m),"&div=myvisualization'><\/script>\n\notherwise if you want to embed the FREEZED visualization,\n<script type='text/javascript' src='",h,"/get_visualization?id=",z,"&path=",encodeURIComponent(m),"&div=myvisualization'><\/script>\n\nand put \n<div id='myvisualization'></div>\nwhere you want the visualization to appear"].join(""))})})}else{d.width=n;d.height=q;jQuery("#export_"+b).bind("click",function(){C(function(f){alert(["Paste this to your page: \n<script type='text/javascript' src='https://www.google.com/jsapi'><\/script>\nIf you want to embed the LIVE visualization,\n<script type='text/javascript' src='",
-h,"/export?id=",b,"&path=",encodeURIComponent(m),"&div=myvisualization'><\/script>\n\notherwise if you want to embed the FREEZED visualization,\n<script type='text/javascript' src='",h,"/get_visualization?id=",f,"&path=",encodeURIComponent(m),"&div=myvisualization'><\/script>\n\nand put \n<div id='myvisualization'></div>\nwhere you want the visualization to appear"].join(""))})})}return new i[a]("div_visualization_"+b,t.data,d,function(){w.drawIntoContainer()})},K=function(){c.virtual_statistic=
-s;e.type="Table";e.options=i.allCharts.Table.default_options||{};w=A("Table",i.allCharts.Table.default_options);x()},F=function(){var a=jQuery('<li class="widget"> <div class="widget-head"> </div> <div class="widget-content"> </div></li>'),d=jQuery(a.find("[class=widget-head]")[0]);a.attr("id","widget-"+b);jQuery.each(c.style.head,function(f,l){a.css(f,l);f=jQuery("<h3>"+c.title+"</h3>");var z=function(j){c.title=j;x()};f.css({cursor:"text"});f.editable({submit:"ok",cancel:"cancel",onEdit:function(){var j=
-this;j.find("button:contains('ok')").css({display:"none"});j.find("button:contains('cancel')").css({display:"none"});j.keydown(function(E){if(E.keyCode===13)j.find("button:contains('ok')").mouseup();else E.keyCode===27&&j.find("button:contains('c')").mouseup()})},onSubmit:function(j){z(j.current)}});d.html(f);d.append(jQuery('<a href="#" class="remove">CLOSE</a>').mousedown(function(j){j.stopPropagation()}).click(function(){confirm("This widget will be removed, ok?")&&jQuery(this).parents(".widget").animate({opacity:0},
-function(){jQuery(this).wrap("<div/>").parent().slideUp(function(){jQuery(this).trigger({type:"widgetdeletion",widget:r}).remove()})})}));d.prepend(jQuery('<a href="#" class="collapse">COLLAPSE</a>').mousedown(function(j){j.stopPropagation()}).click(function(){if(c.visible==="true"){c.visible="false";jQuery(this).css({backgroundPosition:"-38px 0"}).parents(".widget").find(".widget-content").hide()}else{c.visible="true";jQuery(this).css({backgroundPosition:""}).parents(".widget").find(".widget-content").show()}x()}))});
-var h=jQuery(a.find("[class=widget-content]")[0]),m="";if(u.length>1){var n="";jQuery.each(u,function(f,l){n+="<option value='"+l+"'";if(l===c.virtual_statistic)n+=" selected='selected'";n+=">"+l+"</option>"});m+=["<div id='div_switch_statistic_",b,"'> Show statistic: <select id='select_switch_statistic_",b,"'> ",n," </select></div>"].join("")}var q=D();m+=["<div id='div_switch_visualization_",b,"'> Show visualization: <select id='select_switch_visualization_",b,"'> ",q," </select></div>"].join("");
-m+="<div id='div_visualization_"+b+"'></div>";h.html(m);Boolean(c.movable)===true&&d.css({cursor:"move"}).mousedown(function(){jQuery(this).css({width:""});jQuery(this).parent().css({width:jQuery(this).parent().width()+"px"})}).mouseup(function(){jQuery(this).parent().hasClass("dragging")?jQuery(".column").sortable("disable").change():jQuery(this).parent().css({width:""})});jQuery("#column"+c.column).append(a);if(c.visible==="false"){h.hide();h.parents(".widget").find(".widget-head").css({backgroundPosition:"-38px 0"})}h=
-jQuery(".column").sortable("option","items");h+=",#"+b;jQuery("#select_switch_statistic_"+b).bind("change",function(f){s=f.target.value;y();K(s);q=D();jQuery("#select_switch_visualization_"+b).replaceWith(["<select id='select_switch_visualization_",b,"'>",q,"</select>"].join(""));jQuery("#select_switch_visualization_"+b).bind("change",{current_widget:r},function(l){l.data.current_widget.switchVisualizationTo(l.target.value)})});jQuery("#select_switch_visualization_"+b).bind("change",{current_widget:r},
-function(f){f.data.current_widget.switchVisualizationTo(f.target.value)});w=A(e.type,e.options)};this.switchVisualizationTo=function(a){e.type=a;e.options=i.allCharts[a].default_options||{};w=A(a,i.allCharts[a].default_options);x()};this.initialize=function(a){this.setVirtualStatistics(a);B();I();s=u[0];y();F();J()};this.createFromJSON=function(a,d){b=a;jQuery.extend(c,d.widget_options);jQuery.extend(e,d.visualization_options);jQuery.extend(v,d.virtual_statistics);B();o=d.statistic_link_id;g=d.statistic_scope_path;
-s=d.current_statistic;y();F()}};var G=function(g,o,r){this.packages={packages:[]};this.chart_data={container:g,data:o||{},options:r||{}};this.visualization=null;this.getData=function(){return k.clone(this.chart_data.data)};this.getOptions=function(){return k.clone(this.chart_data.options)};this._drawIntoContainer=function(){throw new k.error.notImplementedByChildClass("_drawIntoContainer should be implemented by a child class");};this.drawIntoContainer=function(p){if(p=p||this.chart_data.container)this._drawIntoContainer(p);
-else throw new k.error.containerIsNull(["container should be a valid id, ",p," passed instead"].join(""));}};jQuery.each(i.allCharts,function(g,o){i[g]=function(r,p,b,c){G.apply(this,arguments);this.packages.packages=o.googlePackage;k.loadGoogleApi("visualization","1",this.packages,c);this._drawIntoContainer=function(e){jQuery("#"+e).html("");var t=new google.visualization.DataTable(this.chart_data.data,0.6);if(g.indexOf("ImageChart")>=0)g="ImageChart";this.visualization=new google.visualization[g](document.getElementById(e));
-this.visualization.draw(t,this.chart_data.options)}};i[g].prototype=new G;i[g].prototype.constructor=i[g]})})();
diff --git a/app/soc/content/js.min/templates/modules/statistic/show.js b/app/soc/content/js.min/templates/modules/statistic/show.js
deleted file mode 100644
index dde04dd..0000000
--- a/app/soc/content/js.min/templates/modules/statistic/show.js
+++ /dev/null
@@ -1,5 +0,0 @@
-(function(){var c=window.melange;this.prototype=new c.templates._baseTemplate;this.prototype.constructor=c.templates._baseTemplate;c.templates._baseTemplate.apply(this,arguments);var g=this,h=g.context.visualization_types,d="Table",p=g.context.link_id,q=g.context.scope_path,i={},j=[],e=null,f={width:400,height:300},l=function(a){var b=c.graph.allCharts[d].default_options;jQuery.extend(b,a);var k=new c.graph[d]("div_json",i[e],b,function(){k.drawIntoContainer()})},r=function(){var a={};a.width=parseInt(jQuery("#input_width_value").val(),
-10);a.height=parseInt(jQuery("#input_height_value").val(),10);l(a)},s=function(a){var b="<div id='div_change_options'>";if(a.change_size){a=["Change visualization size:<br />Width: <input id='input_width_value' value='",f.width,"' maxlength='3'></input><br /> Height:<input id='input_height_value' value='",f.height,"' maxlength='3'></input><br />"].join("");b+=a}b+="<input id='input_change_commit' type='button' value='Change'></div>";return b},m=function(){jQuery.get("/statistic/get_json_response/"+
-q+"/"+p,{statistic_name:e},function(a){i[e]=a;d="Table";jQuery("#div_change_options").remove();l()},"json")},n=function(a){d=a.target.value;a=c.graph.allCharts[d].default_options;var b={change_size:true};jQuery("#div_change_options").remove();if(d!=="Table"){jQuery("#div_change_chart_options").append(s(b));a.height=f.height;a.width=f.width}jQuery("#input_change_commit").bind("click",r);var k=new c.graph[d]("div_json",i[e],a,function(){k.drawIntoContainer()})},t=function(){return j[0]},u=function(){jQuery.each(h,
-function(a){j.push(a)})},v=function(){var a="";jQuery.each(h,function(b){a+=["<option value='",b,"'>",b,"</option>"].join("")});return a},o=function(){var a="";jQuery.each(h[e],function(){a+=["<option value='",this,"'>",this,"</option>"].join("")});return a};jQuery(function(){u();if(j.length>1){var a=v();jQuery("#div_switch_statistic").append(["Show statistic: <select id='select_switch_statistic'>",a,"</select>"].join(""));jQuery("#select_switch_statistic").bind("change",function(b){e=b.target.value;
-m();b=o();jQuery("#select_switch_visualization").replaceWith(["<select id='select_switch_visualization'>",b,"</select>"].join(""));jQuery("#select_switch_visualization").bind("change",n)})}e=t();a=o();jQuery("#div_switch_visualization").append(["Show visualization: <select id='select_switch_visualization'>",a,"</select>"].join(""));jQuery("#select_switch_visualization").bind("change",n);m()})})();
diff --git a/app/soc/content/js.min/templates/soc/templatetags/_as_table.js b/app/soc/content/js.min/templates/soc/templatetags/_as_table.js
deleted file mode 100644
index 2dae858..0000000
--- a/app/soc/content/js.min/templates/soc/templatetags/_as_table.js
+++ /dev/null
@@ -1 +0,0 @@
-(function(){var a=window.melange;this.prototype=new a.templates._baseTemplate;this.prototype.constructor=a.templates._baseTemplate;a.templates._baseTemplate.apply(this,arguments);var d=this.context.data;jQuery(function(){jQuery.each(d,function(c,b){b.tooltip!==""&&a.tooltip.createTooltip(c,b.tooltip);b.autocomplete!==null&&a.autocomplete.makeAutoComplete(c,b.autocomplete)})})})();
diff --git a/app/soc/content/js/bulk-review.js b/app/soc/content/js/bulk-review.js
deleted file mode 100644
index 647ecea..0000000
--- a/app/soc/content/js/bulk-review.js
+++ /dev/null
@@ -1,119 +0,0 @@
-jQuery(document).ready(function () {
- jQuery("#applications_progress_bar").progressBar({showText: false});
-});
-
-function bulkReview(data) {
- // some global constants
- var GLOBAL_LINK = data.link;
- var TOTAL_APPLICATIONS = data.nr_applications;
-
- // some global variables set needed for internal iteration
- var application_index = 0;
- // number of iteration is not taken from data.nr_applications
- // to ensure avoidance of array out of bounds errors
- var total_index = data.applications.length;
-
-
- // call immediately the function for review
- // real iteration is inside
- setTimeout(
- function () {
- var error_happened = false;
- var application = data.applications[application_index];
- var current_application = application_index + 1;
- // regular expression to find a valid scope path
- // inside matching parenthesis
- var re = /\((\w*)\)/;
- var scope_path = GLOBAL_LINK.match(re)[1];
- // the URL is obtained by using the scope path found
- // in the matching parenthesis
- var url_to_call = GLOBAL_LINK.replace(re, application[scope_path]);
- // now we can call the URL found
- jQuery.ajax({
- async: false,
- cache: false,
- url: url_to_call,
- timeout: 10000,
- success: function (data) {
- if (data) {
- // update progress bar percentage and description
- var percentage =
- Math.floor(100 * (current_application) / (TOTAL_APPLICATIONS));
- jQuery("#description_progressbar").html([
- " Processed application ", application.name,
- " (", current_application, "/", TOTAL_APPLICATIONS, ")"
- ].join(""));
- jQuery("#applications_progress_bar").progressBar(percentage);
- }
- },
- error: function (XMLHttpRequest, textStatus, errorThrown) {
- // if there is an error return the button and
- // leave a try again message
- error_happened = true;
- jQuery("[id^=button_bulk_]").fadeIn(
- "slow",
- function () {
- jQuery("#description_done").html([
- "<strong class='error'>",
- " Error encountered, try again",
- "</strong>"
- ].join(""));
- }
- );
- }
- });
- // if there were no errors, continue the iteration
- if (!error_happened) {
- // prepare for new iteration and then recall this function
- application_index++;
- if (application_index < total_index) {
- setTimeout(arguments.callee, 0);
- }
- else {
- // all ok, tell the user we are done
- jQuery("#applications_progress_bar").fadeOut(
- "slow",
- function () {
- jQuery("#applications_progress_bar").progressBar(0);
- jQuery("[id^=button_bulk_]").fadeIn("slow");
- }
- );
- jQuery("#description_progressbar").html("");
- jQuery("#description_done").html("<strong>Done!</strong>");
- }
- }
- },
- 0
- );
-}
-
-function bulkReviewInit(bulk_review_link, button) {
- // get the JSON object with details of every application for bulk acceptance
- jQuery.getJSON(
- bulk_review_link + "?_=" + (new Date().getTime()),
- function (data) {
- // If there are applications to review...
- if (data.nr_applications !== 0) {
- //...then fade out the button, show the progress bar and call the function for review
- jQuery("[id^=button_bulk_]").fadeOut(
- "slow",
- function () {
- jQuery("#applications_progress_bar").progressBar(0);
- jQuery("#description_done").html("");
- jQuery("#applications_progress_bar").fadeIn("slow", bulkReview(data));
- }
- );
- }
- else {
- var no_organization_text = "No organizations to ";
- if (jQuery(button).attr("id").indexOf("reject") !== -1) {
- no_organization_text += "reject";
- }
- else {
- no_organization_text += "accept";
- }
- jQuery("#description_done").html("<strong>" + no_organization_text + "</strong>");
- }
- }
- );
-}
diff --git a/app/soc/content/js/melange.dependency.js b/app/soc/content/js/melange.dependency.js
index 36a2fa8..3aa1a26 100644
--- a/app/soc/content/js/melange.dependency.js
+++ b/app/soc/content/js/melange.dependency.js
@@ -364,12 +364,6 @@
mpjs + "melange.autocomplete.js"
];
- s.melange.graph = [
- s.google,
- null,
- mpjs + "melange.graph.js"
- ];
-
s.melange.uploadform = [
s.fileupload,
null,
diff --git a/app/soc/content/js/melange.graph.js b/app/soc/content/js/melange.graph.js
deleted file mode 100644
index 856fd0c..0000000
--- a/app/soc/content/js/melange.graph.js
+++ /dev/null
@@ -1,932 +0,0 @@
-/* Copyright 2010 the Melange authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/**
- * @author <a href="mailto:fadinlight@gmail.com">Mario Ferraro</a>
- * @author <a href="mailto:daniel.m.hans@gmail.com">Daniel Hans</a>
- */
-(function () {
- /** @lends melange.graph */
-
- if (window.melange === undefined) {
- throw new Error("Melange not loaded");
- }
-
- var melange = window.melange;
-
- /** Package that handles all charts related functions
- * @name melange.graph
- * @namespace melange.graph
- * @borrows melange.logging.debugDecorator.log as log
- */
- melange.graph = window.melange.graph = function () {
- return new melange.graph();
- };
-
- /** Shortcut to current package.
- * @private
- */
- var $m = melange.logging.debugDecorator(melange.graph);
-
- melange.error.createErrors([
- "chartNotExistent",
- "containerIsNull"
- ]);
-
- /** List of all available charts, their name, the corresponding Google
- * Ajax API package and default options.
- * @property
- * @public
- * @name melange.graph.allCharts
- */
- $m.allCharts = {
- "AreaChart": {
- "public_name": "Area Chart",
- "googlePackage": ["areachart"]
- },
- "BarChart": {
- "public_name": "Bar Chart",
- "googlePackage": ["barchart"],
- "default_options": {}
- },
- "ColumnChart": {
- "public_name": "Column Chart",
- "googlePackage": ["columnchart"],
- "default_options": {}
- },
- "GeoMap": {
- "public_name": "Geo Map",
- "googlePackage": ["geomap"],
- "default_options": {}
- },
- "ImageChartBar": {
- "public_name": "Bar Chart (I)",
- "googlePackage": ["imagechart"],
- "default_options": {
- cht: "bvs"
- }
- },
- "ImageChartLine": {
- "public_name": "Line Chart (I)",
- "googlePackage": ["imagechart"],
- "default_options": {
- cht: "lc"
- }
- },
- "ImageChartMap": {
- "public_name": "Map Chart (I)",
- "googlePackage": ["imagechart"],
- "default_options": {
- cht: "t",
- chtm: "world"
- }
- },
- "ImageChartP": {
- "public_name": "Pie Chart (I)",
- "googlePackage": ["imagechart"],
- "default_options": {
- cht: "p"
- }
- },
- "ImageChartP3": {
- "public_name": "3D Pie Chart (I)",
- "googlePackage": ["imagechart"],
- "default_options": {
- cht: "p3"
- }
- },
- "PieChart": {
- "public_name": "Pie Chart",
- "googlePackage": ["piechart"],
- "default_options": {
- is3D: true,
- pieJoinAngle: 1
- }
- },
- "ScatterChart": {
- "public_name": "Scatter Chart",
- "googlePackage": ["scatterchart"],
- "default_options": {}
- },
- "Table": {
- "public_name": "Table",
- "googlePackage": ["table"],
- "default_options": {
- showRowNumber: true,
- page: 'enable',
- pageSize: 10
- }
- }
- };
-
- /** Creates a new widget instance for the dashboard
- * @class
- * @constructor
- * @exports melange.graph.Widget as $m.Widget
- * @name melange.graph.Widget
- * @public
- * @param {String} statistic_scope_path Scope Path of the statistic which
- * this widget should be based on
- * @param {String} statistic_link_id Link ID of the statistic which
- * this widget should be based on
- */
- $m.Widget = function (statistic_scope_path, statistic_link_id) {
- /** @lends melange.graph.Widget */
-
- /** Shortcut to current instance.
- * @private
- */
- var _self = this;
-
- /** List of possible colors for widget's title
- * @private
- */
- var colors_list = ['red', 'blue', 'green', 'yellow'];
-
- /** Template skeleton for the widget
- * @private
- */
- var widget_template = [
- '<li class="widget">',
- ' <div class="widget-head">',
- ' </div>',
- ' <div class="widget-content">',
- ' </div>',
- '</li>'
- ].join("");
-
- /** Numeric ID for this widget
- * @private
- */
- var id = "" + new Date().getTime();
-
- /** Default options for the widget
- * @private
- */
- var widget_options = {
- "title": "Click to change me!",
- "column": 2,
- "place": null,
- "style": {
- "head": {
- "background": "#765364" // 148ea4
- },
- "content": {
- "color": "white"
- }
- },
- "movable": "true",
- "visible": "true",
- "virtual_statistic": null
- };
-
- /** Default options for the visualization inside the widget
- * @private
- */
- var visualization_options = {
- "type": "PieChart",
- "options": {
- showRowNumber: true
- }
- };
-
- /** Default data for the visualization inside the widget
- * @private
- */
- var data = {
- "comment": "New chart",
- "data": {}
- };
-
- /** List of virtual statistics available in the current visualization
- * @private
- */
- var virtual_statistics = {};
-
- /** Current displayed statistic
- * @private
- */
- var current_statistic = null;
-
- /** List of available visualization types for this statistic
- * @private
- */
- var visualization_types = {};
-
- /** List of names of available virtual statistics
- * @private
- */
- var virtual_statistic_names = [];
-
- /** Reference to Google Visualization object inside the widget
- * @private
- */
- var chart = null;
-
- /** Set widget's data
- * @function
- * @public
- * @name melange.graph.Widget.setData
- * @param {Object} new_data new data
- */
- this.setData = function (new_data) {
- data.data = new_data;
- };
-
- /** Get widget's data
- * @function
- * @public
- * @name melange.graph.Widget.getData
- * @returns {Object} Widget's data
- */
- this.getData = function () {
- return data.data;
- };
-
- /** Set widget's options
- * @function
- * @public
- * @name melange.graph.Widget.setWidgetOptions
- * @param {Object} new_options new options
- */
- this.setWidgetOptions = function (new_options) {
- widget_options = new_options;
- };
-
- /** Get widget's options
- * @function
- * @public
- * @name melange.graph.Widget.getWidgetOptions
- * @returns {Object} Widget's options
- */
- this.getWidgetOptions = function () {
- return widget_options;
- };
-
- /** Set available visualization types
- * @function
- * @public
- * @name melange.graph.Widget.setVisualizationTypes
- * @param {Object} types new types
- */
- this.setVisualizationTypes = function (types) {
- visualization_types = types;
- };
-
- /** Set available virtual statistics
- * @function
- * @public
- * @name melange.graph.Widget.setVirtualStatistics
- * @param {Object} statistics new virtual statistics
- */
- this.setVirtualStatistics = function (statistics) {
- virtual_statistics = statistics;
- };
-
- /** Set widget options during creation
- * @function
- * @private
- * @name melange.graph.Widget.setOptionsOnCreate
- */
- var setOptionsOnCreate = function () {
- /* determine correct place for a new widget */
- widget_options.place = 1 + jQuery("#column3").find("li").size();
- /* generate initial color for a widget */
- widget_options.style.head.background =
- colors_list[Math.floor(Math.random() * colors_list.length)];
- widget_options.virtual_statistic = virtual_statistic_names[0];
- visualization_options.type = "Table";
- };
-
- /** Set available virtual statistics names
- * @function
- * @private
- * @name melange.graph.Widget.setVirtualStatisticsNames
- */
- var setVirtualStatisticNames = function () {
- virtual_statistic_names = [];
- jQuery.each(virtual_statistics, function (k, v) {
- virtual_statistic_names.push(k);
- });
- };
-
- /** Get widget's id
- * @function
- * @public
- * @name melange.graph.Widget.getId
- * @returns {String} Widget's id
- */
- this.getId = function () {
- return id;
- };
-
-
- /** Save this widget to server
- * @function
- * @private
- * @name melange.graph.Widget.saveToServer
- */
- var saveToServer = function () {
- jQuery.post(
- "save_chart",
- {
- "id": id,
- "statistic_scope_path": statistic_scope_path,
- "statistic_link_id": statistic_link_id,
- "widget_options": JSON.stringify(widget_options),
- "visualization_options": JSON.stringify(visualization_options)
- },
- function (data) {
- //TODO:(merio) check if returns true or false
- },
- "json"
- );
- };
-
- /** Update this widget to server
- * @function
- * @private
- * @name melange.graph.Widget.updateToServer
- */
- var updateToServer = function () {
- jQuery.post(
- "update_chart",
- {
- "data": JSON.stringify([{
- "id": id,
- "widget_options": JSON.stringify(widget_options),
- "visualization_options": JSON.stringify(visualization_options)
- }])
- },
- function (data) {
- //TODO but probably nothing
- },
- "json"
- );
- };
-
- /** Save a freezed visualization to the server
- * @function
- * @private
- * @name melange.graph.Widget.createFreezedVisualizationToServer
- */
- var createFreezedVisualizationToServer = function (callback) {
- var visualization_id = "" + new Date().getTime();
- jQuery.post(
- "save_visualization",
- {
- "id": visualization_id,
- "statistic_scope_path": statistic_scope_path,
- "statistic_link_id": statistic_link_id,
- "widget_options": JSON.stringify(widget_options),
- "visualization_options": JSON.stringify(visualization_options)
- },
- function (data) {
- callback.call(_self, visualization_id);
- },
- "json"
- );
- };
-
- /** Get virtual statistic data from server
- * @function
- * @private
- * @name melange.graph.Widget.getVirtualStatisticData
- */
- var getVirtualStatisticData = function () {
- jQuery.ajax({
- async: false,
- url: [
- "/statistic/get_json_response/",
- statistic_scope_path, "/", statistic_link_id
- ].join(""),
- type: "POST",
- data: {
- "statistic_name": current_statistic
- },
- success: function (statistic_data) {
- data.data = statistic_data;
- },
- dataType: "json"
- });
- };
-
- /** Get HTML content for visualization list
- * @function
- * @private
- * @name melange.graph.Widget.getVisualizationOptionsHtmlContent
- * @returns {String} HTML content
- */
- var getVisualizationOptionsHtmlContent = function () {
- var visualization_switch_options = "";
- jQuery.each(virtual_statistics[current_statistic], function (index, value) {
- visualization_switch_options += "<option value='" + value + "'";
- if (value === visualization_options.type) {
- visualization_switch_options += " selected='selected'";
- }
- visualization_switch_options += [
- ">",
- $m.allCharts[value].public_name,
- "</option>"
- ].join("");
- });
- return visualization_switch_options;
- };
-
- /** Draw the visualization inside this widget
- * @function
- * @private
- * @name melange.graph.Widget._drawChartInside
- * @param {String} visualization_type Type of visualization
- * @param {Object} visualization_options Options for the visualization
- */
- var _drawChartInside =
- function (visualization_type, visualization_options) {
- var exp_server =
- /^(.*)\/show_dashboard/.exec(window.location.href)[1];
- var exp_chart =
- /^\/(.*)\/show_dashboard/.exec(window.location.pathname)[1];
- jQuery("#export_" + id).remove();
- jQuery("#select_switch_visualization_" + id).after(
- "<button id='export_" + id + "' value='Export'>Export</button>"
- );
- var vis_width = jQuery("#div_visualization_" + id).width();
- var vis_height = jQuery("#div_visualization_" + id).width();
- if (visualization_type.indexOf("ImageChart") >= 0) {
- // setting height/width as suggested by
- // https://code.google.com/apis/chart/labels.html#pie_labels
- if (visualization_type === "ImageChartP") {
- vis_height = Math.ceil(vis_width / 2);
- }
- else if (visualization_type === "ImageChartP3") {
- // 2.5 seems not sufficient, setting it as 3
- vis_height = Math.ceil(vis_width / 3);
- }
- visualization_options.chs = vis_width + "x" + vis_height;
- jQuery("#export_" + id).bind(
- "click",
- {visualization_div: "#div_visualization_" + id},
- function (event) {
- var image_url = jQuery(
- jQuery(event.data.visualization_div + " img")[0]
- ).attr("src");
- createFreezedVisualizationToServer(function (visualization_id) {
- alert([
- "If you want to copy the current image, paste this: \n ",
- "<img src=\"", image_url, "\">\n\n",
- "If you want to embed the visualization, ",
- "paste this to your page: \n",
- "<script type='text/javascript' ",
- "src='https://www.google.com/jsapi'></script>\n",
- "If you want to embed the LIVE visualization,\n",
- "<script type='text/javascript' src='", exp_server,
- "/export?",
- "id=", id, "&",
- "path=", encodeURIComponent(exp_chart), "&",
- "div=myvisualization'></script>\n\n",
- "otherwise if you want to embed the ",
- "FREEZED visualization,\n",
- "<script type='text/javascript' ",
- "src='", exp_server, "/get_visualization?",
- "id=", visualization_id, "&",
- "path=", encodeURIComponent(exp_chart), "&",
- "div=myvisualization'></script>\n\n",
- "and put \n",
- "<div id='myvisualization'></div>\n",
- "where you want the visualization to appear"
- ].join(""));
- });
- }
- );
- }
- else {
- visualization_options.width = vis_width;
- visualization_options.height = vis_height;
- jQuery("#export_" + id).bind(
- "click",
- function (event) {
- createFreezedVisualizationToServer(function (visualization_id) {
- alert([
- "Paste this to your page: \n",
- "<script type='text/javascript' ",
- "src='https://www.google.com/jsapi'></script>\n",
- "If you want to embed the LIVE visualization,\n",
- "<script type='text/javascript' src='", exp_server,
- "/export?",
- "id=", id, "&",
- "path=", encodeURIComponent(exp_chart), "&",
- "div=myvisualization'></script>\n\n",
- "otherwise if you want to embed the ",
- "FREEZED visualization,\n",
- "<script type='text/javascript' ",
- "src='", exp_server, "/get_visualization?",
- "id=", visualization_id, "&",
- "path=", encodeURIComponent(exp_chart), "&",
- "div=myvisualization'></script>\n\n",
- "and put \n",
- "<div id='myvisualization'></div>\n",
- "where you want the visualization to appear"
- ].join(""));
- });
- }
- );
- }
-
- return new $m[visualization_type](
- "div_visualization_" + id,
- data.data,
- visualization_options,
- function () {
- chart.drawIntoContainer();
- }
- );
- };
-
- /** Switch to another virtual statistic
- * @function
- * @private
- * @name melange.graph.Widget.switchVirtualStatisticTo
- * @param {String} statistic_name the new virtual statistic
- */
- var switchVirtualStatisticTo = function (statistic_name) {
- widget_options.virtual_statistic = current_statistic;
- var visualization_type = "Table";
- visualization_options.type = visualization_type;
- visualization_options.options =
- $m.allCharts[visualization_type].default_options || {};
- chart = _drawChartInside(
- visualization_type,
- $m.allCharts[visualization_type].default_options
- );
- updateToServer();
- };
-
-
- /** Append this widget to the DOM
- * @function
- * @private
- * @name melange.graph.Widget.appendWidgetToDOM
- */
- var appendWidgetToDOM = function () {
- var widget_to_create = jQuery(widget_template);
- var widget_head = jQuery(widget_to_create
- .find("[class=widget-head]")[0]);
-
- // give the widget an id
- widget_to_create.attr("id", "widget-" + id);
- var widget_id = "widget-" + id;
- // for each widget, give the head the style and the title
- jQuery.each(
- widget_options.style.head,
- function (_class, _value) {
- widget_to_create.css(_class, _value);
- var widget_title = jQuery("<h3>" + widget_options.title + "</h3>");
- var change_title_and_submit = function (title_text) {
- widget_options.title = title_text;
- updateToServer();
- };
- widget_title.css({cursor: 'text'});
- var editable_widget = widget_title.editable({
- submit: "ok",
- cancel: "cancel",
- onEdit: function (content) {
- var object = this;
- // workaround not to display the ok/cancel button but
- // use them for their bound events to submit/cancel
- object.find("button:contains('ok')").css({display: "none"});
- object.find("button:contains('cancel')").css({display: "none"});
- object.keydown(
- function (event) {
- if (event.keyCode === 13) {
- object.find("button:contains('ok')").mouseup();
- }
- else if (event.keyCode === 27) {
- object.find("button:contains('c')").mouseup();
- }
- }
- );
- },
- onSubmit: function (content) {
- change_title_and_submit(content.current);
- }
- });
- widget_head.html(widget_title);
- /* Add button which removes the widget */
- widget_head.append(
- jQuery('<a href="#" class="remove">CLOSE</a>').mousedown(
- function (e) {
- e.stopPropagation();
- }
- ).click(
- function () {
- if (confirm('This widget will be removed, ok?')) {
- jQuery(this).parents(".widget").animate({
- opacity: 0
- },
- function () {
- jQuery(this).wrap('<div/>').parent().slideUp(function () {
- jQuery(this).trigger(
- {
- type: "widgetdeletion",
- widget: _self
- }
- ).remove();
- });
- });
- }
- })
- );
- /* Add button which collapses the widget */
- widget_head.prepend(
- jQuery('<a href="#" class="collapse">COLLAPSE</a>').mousedown(
- function (e) {
- e.stopPropagation();
- }).click(
- function () {
- if (widget_options.visible === "true") {
- widget_options.visible = "false";
- jQuery(this).css({backgroundPosition: '-38px 0'})
- .parents(".widget")
- .find(".widget-content").hide();
- } else {
- widget_options.visible = "true";
- jQuery(this).css({backgroundPosition: ''})
- .parents(".widget")
- .find(".widget-content").show();
- }
- updateToServer();
- }
- )
- );
- }
- );
-
- var widget_content = jQuery(widget_to_create
- .find("[class=widget-content]")[0]);
- var html_content = "";
- // drop-down menu to change virtual statistic if there is more than one
- if (virtual_statistic_names.length > 1) {
- var statistic_switch_options = "";
- jQuery.each(virtual_statistic_names, function (index, value) {
- statistic_switch_options += "<option value='" + value + "'";
- if (value === widget_options.virtual_statistic) {
- statistic_switch_options += " selected='selected'";
- }
- statistic_switch_options += ">" + value + "</option>";
- });
- html_content += [
- "<div id='div_switch_statistic_", id, "'>",
- " Show statistic: ",
- " <select id='select_switch_statistic_", id, "'>",
- " ", statistic_switch_options,
- " </select>",
- "</div>"
- ].join("");
- }
-
- // drop-down menu to change visualization type
- var visualization_switch_options =
- getVisualizationOptionsHtmlContent();
- html_content += [
- "<div id='div_switch_visualization_", id, "'>",
- " Show visualization: ",
- " <select id='select_switch_visualization_", id, "'>",
- " ", visualization_switch_options,
- " </select>",
- "</div>"
- ].join("");
-
- html_content += "<div id='div_visualization_" + id + "'></div>";
- widget_content.html(html_content);
-
- // if the widget is movable, give it proper classes and handlers
- if (Boolean(widget_options.movable) === true) {
- widget_head.css({
- cursor: 'move'
- }).mousedown(
- function (e) {
- jQuery(this).css({
- width: ''
- });
- jQuery(this).parent().css({
- width: jQuery(this).parent().width() + 'px'
- });
- }
- ).mouseup(
- function () {
- if (!jQuery(this).parent().hasClass('dragging')) {
- jQuery(this).parent().css({
- width: ''
- });
- }
- else {
- jQuery('.column').sortable('disable').change();
- }
- }
- );
- }
-
- var column_for_widget = widget_options.column;
- var place_for_widget = widget_options.place;
-
- // append the widget in the correct column
- jQuery("#column" + column_for_widget).append(widget_to_create);
- if (widget_options.visible === "false") {
- widget_content.hide();
- /* why isn't it working? */
- widget_content.parents(".widget").find(".widget-head")
- .css({backgroundPosition: '-38px 0'});
- }
-
- // make the widget sortable
- var current_sortable_widgets = jQuery('.column')
- .sortable('option', 'items');
- current_sortable_widgets += ',#' + id;
-
- jQuery("#select_switch_statistic_" + id).bind(
- "change",
- function (event) {
- current_statistic = event.target.value;
- getVirtualStatisticData();
- switchVirtualStatisticTo(current_statistic);
- visualization_switch_options =
- getVisualizationOptionsHtmlContent();
- jQuery('#select_switch_visualization_' + id).replaceWith(
- [
- "<select id='select_switch_visualization_", id, "'>",
- "", visualization_switch_options,
- "</select>"
- ].join("")
- );
- jQuery('#select_switch_visualization_' + id).bind(
- "change",
- {current_widget: _self},
- function (event) {
- event.data.current_widget
- .switchVisualizationTo(event.target.value);
- }
- );
- }
- );
- jQuery("#select_switch_visualization_" + id).bind(
- "change",
- {current_widget: _self},
- function (event) {
- event.data.current_widget.switchVisualizationTo(event.target.value);
- }
- );
-
- // create chart inside the widget
- chart = _drawChartInside(
- visualization_options.type,
- visualization_options.options
- );
- };
-
- /** Switch to another visualization
- * @function
- * @private
- * @name melange.graph.Widget.switchVisualizationTo
- * @param {String} visualization_type the new visualization
- */
- this.switchVisualizationTo = function (visualization_type) {
- visualization_options.type = visualization_type;
- visualization_options.options =
- $m.allCharts[visualization_type].default_options || {};
- chart = _drawChartInside(
- visualization_type,
- $m.allCharts[visualization_type].default_options
- );
- updateToServer();
- };
-
- /** Initialize this widget
- * @function
- * @private
- * @name melange.graph.Widget.initialize
- * @param {Object} data virtual statistic's data
- */
- this.initialize = function (data) {
- this.setVirtualStatistics(data);
- setVirtualStatisticNames();
- setOptionsOnCreate();
- current_statistic = virtual_statistic_names[0];
- getVirtualStatisticData();
- appendWidgetToDOM();
- saveToServer();
- };
-
- /** Create a new widget from JSON data (usually taken from backend)
- * @function
- * @public
- * @name melange.graph.Widget.createFromJSON
- * @param {String} widget_id id of the widget
- * @param {Object} widget_data all widget's data
- */
- this.createFromJSON = function (widget_id, widget_data) {
- id = widget_id;
- jQuery.extend(widget_options, widget_data.widget_options);
- jQuery.extend(visualization_options, widget_data.visualization_options);
- jQuery.extend(virtual_statistics, widget_data.virtual_statistics);
- setVirtualStatisticNames();
- statistic_link_id = widget_data.statistic_link_id;
- statistic_scope_path = widget_data.statistic_scope_path;
- current_statistic = widget_data.current_statistic;
- getVirtualStatisticData();
- appendWidgetToDOM();
- };
-
- };
-
- /** Creates a new visualization into the given container
- * @class
- * @constructor
- * @name melange.graph._baseChart
- * @private
- * @param {String} div_container div in which the visualization should
- be injected to
- * @param {Object} vis_data data to send to Google Visualization constructor
- * @param {Object} chart_options options for visualization
- */
- var _baseChart = function (div_container, vis_data, chart_options) {
- this.packages = {
- "packages": []
- };
-
- this.chart_data = {
- container: div_container,
- data: vis_data || {},
- options: chart_options || {}
- };
-
- this.visualization = null;
-
- this.getData = function () {
- return melange.clone(this.chart_data.data);
- };
-
- this.getOptions = function () {
- return melange.clone(this.chart_data.options);
- };
-
- this._drawIntoContainer = function (container) {
- throw new melange.error.notImplementedByChildClass(
- "_drawIntoContainer should be implemented by a child class"
- );
- };
-
- this.drawIntoContainer = function (container) {
- var container_to_draw_in = container || this.chart_data.container;
- if (!container_to_draw_in) {
- throw new melange.error.containerIsNull([
- "container should be a valid id, ",
- container_to_draw_in,
- " passed instead"
- ].join(""));
- }
- else {
- this._drawIntoContainer(container_to_draw_in);
- }
- };
- };
-
- jQuery.each($m.allCharts, function (visualization_name, _element) {
- $m[visualization_name] =
- function (div_container, vis_data, chart_options, callback) {
-
- _baseChart.apply(this, arguments);
- this.packages.packages = _element.googlePackage;
- melange.loadGoogleApi("visualization", "1", this.packages, callback);
-
- this._drawIntoContainer = function (container) {
- jQuery("#" + container).html("");
- var my_data =
- new google.visualization.DataTable(this.chart_data.data, 0.6);
- if (visualization_name.indexOf("ImageChart") >= 0) {
- visualization_name = "ImageChart";
- }
- this.visualization =
- new google.visualization[visualization_name](
- document.getElementById(container)
- );
- this.visualization.draw(my_data, this.chart_data.options);
- };
- };
-
- $m[visualization_name].prototype = new _baseChart();
- $m[visualization_name].prototype.constructor = $m[visualization_name];
-
- });
-
-}());
diff --git a/app/soc/content/js/templates/modules/statistic/show.js b/app/soc/content/js/templates/modules/statistic/show.js
deleted file mode 100644
index cf4c496..0000000
--- a/app/soc/content/js/templates/modules/statistic/show.js
+++ /dev/null
@@ -1,196 +0,0 @@
-/* Copyright 2010 the Melange authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/**
- * @author <a href="mailto:fadinlight@gmail.com">Mario Ferraro</a>
- * @author <a href="mailto:daniel.m.hans@gmail.com">Daniel Hans</a>
- */
-(function () {
- var melange = window.melange;
- this.prototype = new melange.templates._baseTemplate();
- this.prototype.constructor = melange.templates._baseTemplate;
- melange.templates._baseTemplate.apply(this, arguments);
-
- var _self = this;
-
- var chart_options = {
- "Table" : {
- showRowNumber: true,
- page: 'enable'
- }
- };
-
- var visualization_types = _self.context.visualization_types;
- var visualization_type = "Table";
- var link_id = _self.context.link_id;
- var scope_path = _self.context.scope_path;
- var visualization_data = {};
- var statistic_options = [];
- var current_statistic = null;
- var chart_height = null;
- var chart_width = null;
- var default_options = {
- 'width': 400,
- 'height': 300
- };
-
- var drawVisualization = function (new_options) {
- var chart_options =
- melange.graph.allCharts[visualization_type].default_options;
- jQuery.extend(chart_options, new_options);
- var chart_type = new melange.graph[visualization_type](
- "div_json",
- visualization_data[current_statistic],
- chart_options,
- function () {
- chart_type.drawIntoContainer();
- }
- );
- };
-
- var changeVisualizationOptions = function () {
- var new_options = {};
- new_options.width = parseInt(jQuery("#input_width_value").val(), 10);
- new_options.height = parseInt(jQuery("#input_height_value").val(), 10);
- drawVisualization(new_options);
- };
-
- var getChangeChartOptionsHtml = function (options) {
- var change_chart_options = "<div id='div_change_options'>";
- if (options.change_size) {
- var change_size = [
- "Change visualization size:",
- "<br />Width: ",
- "<input id='input_width_value' value='", default_options.width, "'",
- " maxlength='3'></input>",
- "<br /> Height:",
- "<input id='input_height_value' value='", default_options.height, "'",
- " maxlength='3'></input><br />"
- ].join("");
- change_chart_options += change_size;
- }
- change_chart_options +=
- "<input id='input_change_commit' type='button' value='Change'></div>";
- return change_chart_options;
- };
-
-
- var changeStatistic = function () {
- jQuery.get(
- "/statistic/get_json_response/" + scope_path + "/" + link_id,
- {
- "statistic_name": current_statistic
- },
- function (data) {
- visualization_data[current_statistic] = data;
- visualization_type = "Table";
- jQuery("#div_change_options").remove();
- drawVisualization();
- },
- "json"
- );
- };
-
- var changeVisualization = function (event) {
- visualization_type = event.target.value;
- var chart_options =
- melange.graph.allCharts[visualization_type].default_options;
- var options = {'change_size': true};
- jQuery("#div_change_options").remove();
- if (visualization_type !== "Table") {
- jQuery("#div_change_chart_options")
- .append(getChangeChartOptionsHtml(options));
- chart_options.height = default_options.height;
- chart_options.width = default_options.width;
- }
- jQuery("#input_change_commit").bind("click", changeVisualizationOptions);
-
- var chart_type = new melange.graph[visualization_type](
- "div_json",
- visualization_data[current_statistic],
- chart_options,
- function () {
- chart_type.drawIntoContainer();
- }
- );
- };
-
- var getInitialStatistic = function () {
- return statistic_options[0];
- };
-
- var getStatisticOptions = function () {
- jQuery.each(visualization_types, function (statistic, types) {
- statistic_options.push(statistic);
- });
- };
-
- var getStatisticSwitchOptionsHtml = function () {
- var statistic_switch_options = "";
- jQuery.each(visualization_types, function (statistic, types) {
- statistic_switch_options += [
- "<option value='", statistic, "'>", statistic, "</option>"
- ].join("");
- });
- return statistic_switch_options;
- };
-
- var getVisualizationSwitchOptionsHtml = function () {
- var visualization_switch_options = "";
- jQuery.each(visualization_types[current_statistic], function () {
- visualization_switch_options += [
- "<option value='", this, "'>", this, "</option>"
- ].join("");
- });
- return visualization_switch_options;
- };
-
- jQuery(function () {
- getStatisticOptions();
- if (statistic_options.length > 1) {
- var statistic_switch_options = getStatisticSwitchOptionsHtml();
- jQuery("#div_switch_statistic").append([
- "Show statistic: <select id='select_switch_statistic'>",
- statistic_switch_options,
- "</select>"
- ].join(""));
- jQuery("#select_switch_statistic").bind("change", function (event) {
- current_statistic = event.target.value;
- changeStatistic();
- var visualization_switch_options = getVisualizationSwitchOptionsHtml();
- jQuery('#select_switch_visualization').replaceWith([
- "<select id='select_switch_visualization'>",
- visualization_switch_options,
- "</select>"
- ].join(""));
- jQuery('#select_switch_visualization')
- .bind("change", changeVisualization);
- });
- }
-
- current_statistic = getInitialStatistic();
- var visualization_switch_options = getVisualizationSwitchOptionsHtml();
-
- jQuery("#div_switch_visualization").append([
- "Show visualization: ",
- "<select id='select_switch_visualization'>",
- visualization_switch_options,
- "</select>"
- ].join(""));
-
- jQuery('#select_switch_visualization').bind("change", changeVisualization);
- changeStatistic();
- });
-
-}());
diff --git a/app/soc/content/js/templates/soc/templatetags/_as_table.js b/app/soc/content/js/templates/soc/templatetags/_as_table.js
deleted file mode 100644
index 7faffd0..0000000
--- a/app/soc/content/js/templates/soc/templatetags/_as_table.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Copyright 2010 the Melange authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/**
- * @author <a href="mailto:fadinlight@gmail.com">Mario Ferraro</a>
- */
-
-(function () {
- var melange = window.melange;
- this.prototype = new melange.templates._baseTemplate();
- this.prototype.constructor = melange.templates._baseTemplate;
- melange.templates._baseTemplate.apply(this, arguments);
-
- var _self = this;
-
- var data = _self.context.data;
-
- jQuery(
- function () {
- jQuery.each(data, function (field_id, details) {
- if (details.tooltip !== '') {
- melange.tooltip.createTooltip(field_id, details.tooltip);
- }
- if (details.autocomplete !== null) {
- melange.autocomplete.makeAutoComplete(field_id, details.autocomplete);
- }
- });
- }
- );
-
-}());
diff --git a/app/soc/logic/cleaning.py b/app/soc/logic/cleaning.py
index 7bb75f5..42f234f 100644
--- a/app/soc/logic/cleaning.py
+++ b/app/soc/logic/cleaning.py
@@ -158,22 +158,6 @@
return wrapper
-def clean_scope_path(field_name):
- """Checks if the field_name value is in a valid scope path format.
- """
-
- @check_field_is_empty(field_name)
- def wrapper(self):
- """Decorator wrapper method.
- """
- # convert to lowercase for user comfort
- scope_path = self.cleaned_data.get(field_name).lower()
- if not validate.isScopePathFormatValid(scope_path):
- raise forms.ValidationError("This scope path is in wrong format.")
- return scope_path
- return wrapper
-
-
def clean_existing_user(field_name):
"""Check if the field_name field is a valid user.
"""
diff --git a/app/soc/logic/helper/prefixes.py b/app/soc/logic/helper/prefixes.py
index 1570929..d3dedcd 100644
--- a/app/soc/logic/helper/prefixes.py
+++ b/app/soc/logic/helper/prefixes.py
@@ -16,20 +16,6 @@
"""
-def getOrSetScope(entity):
- """Gets or sets scope for the given entity.
-
- params:
- entity = Entity which uses document prefix.
- """
-
- if getattr(entity, 'scope', None):
- return entity.scope
-
- entity.scope = getScopeForPrefix(entity.prefix, entity.scope_path)
- entity.put()
-
-
def getScopeForPrefix(prefix, key_name):
"""Gets the scope for the given prefix and key_name.
diff --git a/app/soc/logic/host.py b/app/soc/logic/host.py
index d880595..7789e12 100644
--- a/app/soc/logic/host.py
+++ b/app/soc/logic/host.py
@@ -12,12 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Logic for Host Model.
-"""
+"""Logic for Host Model."""
+from soc.logic import program as program_logic
from soc.models.host import Host
-from soc.models.program import Program
from soc.models.user import User
@@ -44,8 +43,7 @@
Returns:
The list of host entities for the specified program entity
"""
- sponsor_key = Program.scope.get_value_for_datastore(
- program_entity)
+ sponsor_key = program_logic.getSponsorKey(program_entity)
q = User.all()
q.filter('host_for', sponsor_key)
# TODO(Madhu): Return the host entities once we run the Mapreduce to convert
diff --git a/app/soc/logic/links.py b/app/soc/logic/links.py
index f016eaf..2d2bd70 100644
--- a/app/soc/logic/links.py
+++ b/app/soc/logic/links.py
@@ -16,6 +16,8 @@
from django.core import urlresolvers
+from soc.models import program as program_model
+
class Linker(object):
"""URL creator for Melange."""
@@ -37,14 +39,14 @@
Args:
program: A program.
- url_name: The name with which a url was registered with Django.
+ url_name: The name with which a URL was registered with Django.
Returns:
- The url of the page matching the given name for the given program.
+ The URL of the page matching the given name for the given program.
"""
kwargs = {
'program': program.link_id,
- 'sponsor': program.scope_path,
+ 'sponsor': program.scope.key().name()
}
return urlresolvers.reverse(url_name, kwargs=kwargs)
diff --git a/app/soc/logic/program.py b/app/soc/logic/program.py
new file mode 100644
index 0000000..eeea2ef
--- /dev/null
+++ b/app/soc/logic/program.py
@@ -0,0 +1,31 @@
+# Copyright 2013 the Melange authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Logic for programs.
+"""
+
+from soc.models import program as program_model
+
+
+def getSponsorKey(program):
+ """Returns Key which represents Sponsor of the specified program.
+
+ Args:
+ program: the specified Program entity
+
+ Returns:
+ db.Key instance of the sponsor for the specified program
+ """
+
+ return program_model.Program.scope.get_value_for_datastore(program)
diff --git a/app/soc/logic/validate.py b/app/soc/logic/validate.py
index bc7c2d5..08d1b01 100644
--- a/app/soc/logic/validate.py
+++ b/app/soc/logic/validate.py
@@ -61,16 +61,6 @@
return bool(linkable.LINK_ID_REGEX.match(link_id))
-def isScopePathFormatValid(scope_path):
- """Returns True if scope_path is in a valid format.
-
- Args:
- scope_path: scope path prepended to link ID
- used for identification.
- """
- return bool(linkable.SCOPE_PATH_REGEX.match(scope_path))
-
-
def isAgeSufficientForProgram(birth_date, program):
"""Returns True if a student with birth_date can participate in program.
diff --git a/app/soc/models/linkable.py b/app/soc/models/linkable.py
index 4cf65a3..d8b3f11 100644
--- a/app/soc/models/linkable.py
+++ b/app/soc/models/linkable.py
@@ -32,27 +32,6 @@
LINK_ID_PATTERN = r'^%s$' % LINK_ID_PATTERN_CORE
LINK_ID_REGEX = re.compile(LINK_ID_PATTERN)
-# scope path is multiple link_id chunks,
-# each separated by a trailing /
-# (at least 1)
-SCOPE_PATH_ARG_PATTERN = (r'(?P<scope_path>%(link_id)s'
- '(?:/%(link_id)s)*)' % {
- 'link_id': LINK_ID_PATTERN_CORE})
-SCOPE_PATH_PATTERN = r'^%s$' % SCOPE_PATH_ARG_PATTERN
-SCOPE_PATH_REGEX = re.compile(SCOPE_PATH_PATTERN)
-
-# path is multiple link_id chunks,
-# each separated by a trailing /
-# (at least 1)
-# followed by a single link_id with no trailing /
-PATH_LINK_ID_ARGS_PATTERN = (
- r'%(scope_path)s/'
- '(?P<link_id>%(link_id)s)' % {
- 'scope_path' : SCOPE_PATH_ARG_PATTERN,
- 'link_id': LINK_ID_PATTERN_CORE})
-PATH_LINK_ID_PATTERN = r'^%s$' % PATH_LINK_ID_ARGS_PATTERN
-PATH_LINK_ID_REGEX = re.compile(PATH_LINK_ID_PATTERN)
-
class Linkable(db.Model):
"""A base class for Model classes that are "linkable".
@@ -114,15 +93,3 @@
scope.help_text = ugettext(
'Reference to another Linkable entity that defines the "scope" of'
' this Linkable entity.')
-
- #: Hidden (not displayed to users or editable in forms) cache of the string
- #: representation of the transitive closure of scopes, for use in URLs.
- #: The multiple queries required to produce this string for entities in
- #: deeply-nested scopes can be prohibitively expensive. The scope of an
- #: entity is not expected to change frequently (only for move, copy, and
- #: maybe re-parenting operations), so this property is not likely to need
- #: updating.
- scope_path = db.StringProperty(required=False,
- verbose_name=ugettext('Scope path'))
- scope_path.help_text = ugettext(
- 'Cache of the string form of the entity scope.')
diff --git a/app/soc/models/seed_db.py b/app/soc/models/seed_db.py
index 32430f9..6c484b1 100644
--- a/app/soc/models/seed_db.py
+++ b/app/soc/models/seed_db.py
@@ -111,7 +111,6 @@
'link_id': 'test',
'public_name': 'test',
'scope': google,
- 'scope_path': 'google',
'user': current_user,
'given_name': 'Test',
'surname': 'Example',
@@ -143,7 +142,6 @@
timeline_properties = {
'key_name': 'google/gsoc2009',
'link_id': 'gsoc2009',
- 'scope_path': 'google',
'scope': google,
'program_start': before,
'program_end': after,
@@ -159,7 +157,6 @@
program_properties = {
'key_name': 'google/gsoc2009',
'link_id': 'gsoc2009',
- 'scope_path': 'google',
'scope': google,
'name': 'Google Summer of Code 2009',
'short_name': 'GSoC 2009',
@@ -198,7 +195,6 @@
timeline_properties = {
'key_name': 'google/gci2009',
'link_id': 'gci2009',
- 'scope_path': 'google',
'scope': google,
'program_start': before,
'program_end': after,
@@ -236,7 +232,6 @@
'link_id': 'melange',
'name': 'Melange Development Team',
'short_name': 'Melange',
- 'scope_path': 'google/gci2009',
'scope': gci2009,
'home_page': 'http://code.google.com/p/soc',
'description': 'Melange, share the love!',
@@ -248,14 +243,12 @@
melange.put()
group_properties.update({
- 'scope_path': 'google/gsoc2009',
'scope': gsoc2009,
})
role_properties.update({
'key_name': 'google/gsoc2009/test',
'link_id': 'test',
- 'scope_path': 'google/gsoc2009',
'scope': gsoc2009,
'program': gsoc2009,
'parent': current_user,
@@ -295,7 +288,6 @@
role_properties.update({
'key_name': 'google/gci2009/test',
'link_id': 'test',
- 'scope_path': 'google/gci2009',
'scope': gci2009,
'program': gci2009,
'org_admin_for': [melange.key()],
@@ -340,7 +332,6 @@
student_properties = {
'key_name': gsoc2009.key().name() + "/" + student_id,
'link_id': student_id,
- 'scope_path': gsoc2009.key().name(),
'parent': student_user,
'scope': gsoc2009,
'program': gsoc2009,
@@ -473,7 +464,6 @@
'key_name': gci2009.key().name() + '/' + student_id,
'parent': student_user,
'scope': gci2009,
- 'scope_path': gci2009.key().name(),
})
gci_student = GCIProfile(**student_properties)
gci_student.put()
@@ -500,7 +490,6 @@
document_properties = {
'key_name': 'site/site/home',
'link_id': 'home',
- 'scope_path': 'site',
'scope': site,
'prefix': 'site',
'author': current_user,
@@ -517,7 +506,6 @@
document_properties = {
'key_name': 'user/test/notes',
'link_id': 'notes',
- 'scope_path': 'test',
'scope': current_user,
'prefix': 'user',
'author': current_user,
diff --git a/app/soc/modules/gci/logic/cleaning.py b/app/soc/modules/gci/logic/cleaning.py
deleted file mode 100644
index 3f063fe..0000000
--- a/app/soc/modules/gci/logic/cleaning.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright 2009 the Melange authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""GCI module cleaning methods.
-"""
-
-
-from django import forms
-from django.utils.translation import ugettext
-
-from soc.logic import cleaning
-from soc.logic import validate
-
-from soc.modules.gci.logic.models.task import logic as gci_task_logic
-
-
-def cleanTaskComment(comment_field, action_field, ws_ext_field,
- ws_upld_field, extended_deadline_field):
- """Cleans the comment form and checks to see if there is either
- action or comment content.
-
- Raises ValidationError if:
- -There is no action taking place and no comment present
- -The action is needs_review and there is no comment or work submission
- present
- """
-
- def wrapper(self):
- """Decorator wrapper method.
- """
-
- cleaned_data = self.cleaned_data
- content = cleaned_data.get(comment_field)
- action = cleaned_data.get(action_field)
- ws_ext = cleaned_data.get(ws_ext_field)
- extended_deadline = cleaned_data.get(extended_deadline_field)
-
- # not using cleaned data because this is separately handled by
- # Appengine's blobstore APIs
- ws_upld = self.data.get(ws_upld_field)
-
- if action == 'noaction' and not content:
- raise forms.ValidationError(
- ugettext('You cannot have comment field empty with no action.'))
-
- if action == 'needs_review' and not (content or ws_ext or ws_upld):
- raise forms.ValidationError(
- ugettext('You cannot have all the three fields: comment, '
- 'and two work submission fields empty'))
-
- if action == 'needs_work' and extended_deadline <= 0:
- raise forms.ValidationError(
- ugettext('Some time extension must be given to the student '
- 'when more work on the task is expected.'))
-
- if ws_upld:
- cleaned_data[ws_upld_field] = ws_upld
-
- return cleaned_data
-
- return wrapper
-
-
-def cleanMentorsList(field_name):
- """Clean method to check and validate list of mentor's link_ids.
- """
-
- @cleaning.check_field_is_empty(field_name)
- def wrapper(self):
- """Decorator wrapped method.
- """
-
- from soc.modules.gci.logic.models.mentor import logic as gci_mentor_logic
-
- mentors_list_str = cleaning.str2set(field_name)(self)
-
- fields = {
- 'scope_path': self.cleaned_data.get('scope_path'),
- 'status': 'active'
- }
-
- mentors = []
- for link_id in mentors_list_str:
-
- if not validate.isLinkIdFormatValid(link_id):
- raise forms.ValidationError(
- "'%s' is not a valid username." % link_id)
-
- fields['link_id'] = link_id
-
- mentor = gci_mentor_logic.getFromKeyFields(fields)
- if not mentor:
- raise forms.ValidationError(
- '"%s" is not a valid Mentor.' % link_id)
-
- mentors.append(mentor.key())
-
- return mentors
- return wrapper
diff --git a/app/soc/modules/gci/logic/helper/notifications.py b/app/soc/modules/gci/logic/helper/notifications.py
index 2dbb7cd..bcc8a34 100644
--- a/app/soc/modules/gci/logic/helper/notifications.py
+++ b/app/soc/modules/gci/logic/helper/notifications.py
@@ -24,6 +24,7 @@
from soc.logic import accounts
from soc.logic import dicts
from soc.logic import mail_dispatcher
+from soc.logic import program as program_logic
from soc.logic import site
from soc.logic import system
from soc.tasks import mailer
@@ -158,7 +159,7 @@
program = student.scope
kwargs = {
- 'sponsor': program.scope_path,
+ 'sponsor': program_logic.getSponsorKey(program).name(),
'program': program.link_id
}
url = reverse('gci_student_form_upload', kwargs=kwargs)
@@ -184,7 +185,7 @@
to_emails: list of recepients for the notification.
"""
url_kwargs = {
- 'sponsor': task.program.scope_path,
+ 'sponsor': program_logic.getSponsorKey(task.program).name(),
'program': task.program.link_id,
'id': task.key().id(),
}
diff --git a/app/soc/modules/gci/logic/profile.py b/app/soc/modules/gci/logic/profile.py
index 9613e52..1f8d975 100644
--- a/app/soc/modules/gci/logic/profile.py
+++ b/app/soc/modules/gci/logic/profile.py
@@ -226,9 +226,8 @@
key_name = '%s/%s' % (program.key(), user_logic.MELANGE_DELETED_USER)
profile_ent = profile_model.GCIProfile(
- parent=user_ent, key_name=key_name,
+ parent=user_ent, key_name=key_name, user=user_ent,
link_id=user_logic.MELANGE_DELETED_USER, scope=program,
- scope_path=program.key().id_or_name(), user=user_ent,
public_name=MELANGE_DELETED_USER_PNAME,
given_name=MELANGE_DELETED_USER_GNAME,
surname=MELANGE_DELETED_USER_SNAME,
diff --git a/app/soc/modules/gci/views/forms.py b/app/soc/modules/gci/views/forms.py
index e7d2554..ae00cdb 100644
--- a/app/soc/modules/gci/views/forms.py
+++ b/app/soc/modules/gci/views/forms.py
@@ -31,6 +31,7 @@
from django.template import defaultfilters
from django.utils.formats import dateformat
+from soc.models import document as document_model
from soc.views import forms
from soc.views import org_app
@@ -504,11 +505,13 @@
if value:
document = db.get(value)
- sponsor, program = document.scope_path.split('/')
+ scope_key_name = document_model.Document.scope.get_value_for_datastore(
+ document).name()
+ sponsor, program = scope_key_name.split('/')
args = [document.prefix, sponsor, program, document.link_id]
else:
- scope_path = self.form.request_data.program.key().id_or_name()
- sponsor, program = scope_path.split('/')
+ scope_key_name = self.form.request_data.program.key().id_or_name()
+ sponsor, program = scope_key_name.split('/')
args = ['gci_program', sponsor, program, self.name]
edit_document_link = reverse('edit_gci_document', args=args)
diff --git a/app/soc/modules/gci/views/helper/request_data.py b/app/soc/modules/gci/views/helper/request_data.py
index 2fc5925..fe41076 100644
--- a/app/soc/modules/gci/views/helper/request_data.py
+++ b/app/soc/modules/gci/views/helper/request_data.py
@@ -21,12 +21,12 @@
from google.appengine.ext import db
+from soc.logic import program as program_logic
from soc.logic.exceptions import NotFound
from soc.models.site import Site
from soc.views.helper import request_data
from soc.modules.gci.logic.helper import timeline as timeline_helper
-from soc.modules.gci.models import program as program_model
from soc.modules.gci.models.program import GCIProgram
from soc.modules.gci.models import profile as profile_model
from soc.modules.gci.models import organization as org_model
@@ -234,8 +234,7 @@
key = db.Key.from_path('Sponsor', self.kwargs.get('sponsor'))
self._is_host = key in self.user.host_for
else:
- key = program_model.GCIProgram.scope.get_value_for_datastore(
- self.program)
+ key = program_logic.getSponsorKey(self.program)
self._is_host = key in self.user.host_for
return self._is_host
diff --git a/app/soc/modules/gci/views/org_profile.py b/app/soc/modules/gci/views/org_profile.py
index 41626a5..d6ea264 100644
--- a/app/soc/modules/gci/views/org_profile.py
+++ b/app/soc/modules/gci/views/org_profile.py
@@ -134,7 +134,6 @@
org_id = data.GET['org_id']
form.cleaned_data['founder'] = data.user
form.cleaned_data['scope'] = data.program
- form.cleaned_data['scope_path'] = data.program.key().name()
form.cleaned_data['link_id'] = org_id
key_name = '%s/%s' % (data.program.key().name(), org_id)
entity = form.create(key_name=key_name)
diff --git a/app/soc/modules/gci/views/program.py b/app/soc/modules/gci/views/program.py
index a1291ea..0dd0e64 100644
--- a/app/soc/modules/gci/views/program.py
+++ b/app/soc/modules/gci/views/program.py
@@ -41,7 +41,7 @@
class Meta:
css_prefix = 'timeline_form'
model = timeline_model.GCITimeline
- exclude = ['link_id', 'scope', 'scope_path']
+ exclude = ['link_id', 'scope']
class CreateProgramForm(gci_forms.GCIModelForm):
@@ -55,8 +55,8 @@
css_prefix = 'create_program_form'
model = program_model.GCIProgram
exclude = [
- 'scope', 'scope_path', 'timeline', 'org_admin_agreement',
- 'mentor_agreement', 'student_agreement', 'about_page', 'events_page',
+ 'scope', 'timeline', 'org_admin_agreement', 'events_page',
+ 'mentor_agreement', 'student_agreement', 'about_page',
'connect_with_us_page', 'help_page', 'task_types']
def clean(self):
@@ -89,7 +89,7 @@
class Meta:
css_prefix = 'edit_program_form'
model = program_model.GCIProgram
- exclude = ['link_id', 'scope', 'scope_path', 'timeline', 'task_types']
+ exclude = ['link_id', 'scope', 'timeline', 'task_types']
def clean(self):
"""Cleans the data input by the user as a response to the form.
diff --git a/app/soc/modules/gsoc/models/follower.py b/app/soc/modules/gsoc/models/follower.py
deleted file mode 100644
index de1e294..0000000
--- a/app/soc/modules/gsoc/models/follower.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2009 the Melange authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""This module contains the Follower Model."""
-
-
-from google.appengine.ext import db
-
-import soc.models.linkable
-
-
-class Follower(soc.models.linkable.Linkable):
- """Details specific to a Follower.
-
- A Follower is a generic model which indicates that a User is following
- some other Linkable entity in the application.
-
- Scope and scope_path should be set to the entity being followed.
- The link_id should be used to indicate which user is following.
-
- If more functionality is needed like for instance when following
- either a public or private review for Student Proposals this model
- should be extended. As to make it possible to create different types
- of following.
- """
-
- #: Required property to tie a user to the entity it is following
- user = db.ReferenceProperty(reference_class=soc.models.user.User,
- required=True, collection_name='following')
diff --git a/app/soc/modules/gsoc/models/review_follower.py b/app/soc/modules/gsoc/models/review_follower.py
deleted file mode 100644
index 585ebf7..0000000
--- a/app/soc/modules/gsoc/models/review_follower.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2009 the Melange authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""This module contains the Review Follower Model."""
-
-
-from google.appengine.ext import db
-
-import soc.modules.gsoc.models.follower
-
-
-class ReviewFollower(soc.modules.gsoc.models.follower.Follower):
- """Details specific to a Review Follower.
- """
-
- #: Required property indicating if the public reviews should be followed
- subscribed_public = db.BooleanProperty(required=True, default=False)
-
- #: Required property indicating if the private reviews should be followed
- subscribed_private = db.BooleanProperty(required=True, default=False)
diff --git a/app/soc/modules/gsoc/views/forms.py b/app/soc/modules/gsoc/views/forms.py
index 33b3918..a6a392e 100644
--- a/app/soc/modules/gsoc/views/forms.py
+++ b/app/soc/modules/gsoc/views/forms.py
@@ -23,6 +23,7 @@
from django.utils.formats import dateformat
from django.utils.safestring import mark_safe
+from soc.models import document as document_model
from soc.views import forms
@@ -207,11 +208,13 @@
if value:
document = db.get(value)
- sponsor, program = document.scope_path.split('/')
+ scope_key_name = document_model.Document.scope.get_value_for_datastore(
+ document).name()
+ sponsor, program = scope_key_name.split('/')
args = [document.prefix, sponsor, program, document.link_id]
else:
- scope_path = self.form.request_data.program.key().id_or_name()
- sponsor, program = scope_path.split('/')
+ scope_key_name = self.form.request_data.program.key().id_or_name()
+ sponsor, program = scope_key_name.split('/')
args = ['gsoc_program', sponsor, program, self.name]
edit_document_link = reverse('edit_gsoc_document', args=args)
diff --git a/app/soc/modules/gsoc/views/helper/request_data.py b/app/soc/modules/gsoc/views/helper/request_data.py
index 0cbb7be..21ebab2 100644
--- a/app/soc/modules/gsoc/views/helper/request_data.py
+++ b/app/soc/modules/gsoc/views/helper/request_data.py
@@ -21,6 +21,7 @@
from soc.models import site as site_model
from soc.logic import exceptions
+from soc.logic import program as program_logic
from soc.views.helper.access_checker import isSet
from soc.views.helper import request_data
@@ -219,8 +220,7 @@
key = db.Key.from_path('Sponsor', self.kwargs.get('sponsor'))
self._is_host = key in self.user.host_for
else:
- key = program_model.GSoCProgram.scope.get_value_for_datastore(
- self.program)
+ key = program_logic.getSponsorKey(program)
self._is_host = key in self.user.host_for
return self._is_host
diff --git a/app/soc/modules/gsoc/views/helper/templatetags/__init__.py b/app/soc/modules/gsoc/views/helper/templatetags/__init__.py
deleted file mode 100644
index 8fb3e03..0000000
--- a/app/soc/modules/gsoc/views/helper/templatetags/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# Copyright 2010 the Melange authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Module contains custom Django template tags used in GSoC module."""
\ No newline at end of file
diff --git a/app/soc/modules/gsoc/views/helper/templatetags/student_proposal_helpers.py b/app/soc/modules/gsoc/views/helper/templatetags/student_proposal_helpers.py
deleted file mode 100644
index 43ae973..0000000
--- a/app/soc/modules/gsoc/views/helper/templatetags/student_proposal_helpers.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# Copyright 2010 the Melange authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""A Django template tag library containing StudentProposal helpers.
-"""
-
-
-from google.appengine.ext import db
-
-from django import template
-
-from soc.modules.gsoc.models.org_admin import GSoCOrgAdmin
-
-register = template.Library()
-
-
-@register.inclusion_tag(
- 'modules/gsoc/templatetags/_as_proposal_duplicates.html',
- takes_context=True)
-def as_proposal_duplicates(context, proposal_duplicate):
- """Returns a HTML representation of a proposal duplicates.
- """
-
- context['student'] = proposal_duplicate.student
- orgs = db.get(proposal_duplicate.orgs)
- proposals = db.get(proposal_duplicate.duplicates)
-
- orgs_details = {}
- for org in orgs:
- orgs_details[org.key().id_or_name()] = {
- 'name': org.name
- }
-
- q = GSoCOrgAdmin.all()
- q.filter('scope', org)
- q.filter('status', 'active')
- org_admins = q.fetch(1000)
-
- orgs_details[org.key().id_or_name()]['admins'] = []
- for org_admin in org_admins:
- orgs_details[org.key().id_or_name()]['admins'].append({
- 'name': org_admin.name(),
- 'email': org_admin.email
- })
-
- orgs_details[org.key().id_or_name()]['proposals'] = []
- for proposal in proposals:
- if proposal.org.key() == org.key():
- orgs_details[org.key().id_or_name()]['proposals'].append({
- 'key': proposal.key().id_or_name(),
- 'title': proposal.title,
- })
-
- context['orgs'] = orgs_details
- return context
-
-
-@register.inclusion_tag(
- 'modules/gsoc/templatetags/_as_student_proposal_review_duplicate.html',
- takes_context=True)
-def as_student_proposal_review_duplicate(context, proposal):
- """Returns a HTML representation of a proposal duplicates for the Proposal
- Review page.
- """
-
- org_entity = proposal.org
-
- fields = {'scope': org_entity,
- 'status': 'active'}
- org_admin_entities = org_admin_logic.getForFields(fields)
-
- org_admins = [(org_admin.name(), org_admin.email)
- for org_admin in org_admin_entities]
-
- context.update({'title': proposal.title,
- 'org_name': org_entity.name,
- 'org_admins': org_admins })
-
- return context
diff --git a/app/soc/modules/gsoc/views/mentor_evaluation.py b/app/soc/modules/gsoc/views/mentor_evaluation.py
index 3cca0ef..668f469 100644
--- a/app/soc/modules/gsoc/views/mentor_evaluation.py
+++ b/app/soc/modules/gsoc/views/mentor_evaluation.py
@@ -45,9 +45,8 @@
model = GradingProjectSurvey
css_prefix = 'gsoc-mentor-eval-edit'
exclude = ['program', 'scope', 'author', 'created_by', 'modified_by',
- 'survey_content', 'scope_path', 'link_id', 'prefix',
- 'read_access', 'write_access', 'taking_access',
- 'is_featured']
+ 'survey_content', 'link_id', 'prefix', 'is_featured',
+ 'read_access', 'write_access', 'taking_access']
class GSoCMentorEvaluationTakeForm(gsoc_forms.SurveyTakeForm):
"""Form for the organization to evaluate a student project."""
diff --git a/app/soc/modules/gsoc/views/org_profile.py b/app/soc/modules/gsoc/views/org_profile.py
index e5a72a4..4cb202b 100644
--- a/app/soc/modules/gsoc/views/org_profile.py
+++ b/app/soc/modules/gsoc/views/org_profile.py
@@ -229,7 +229,6 @@
if not data.organization:
form.cleaned_data['founder'] = data.user
form.cleaned_data['scope'] = data.program
- form.cleaned_data['scope_path'] = data.program.key().name()
form.cleaned_data['link_id'] = data.org_id
form.cleaned_data['new_org'] = data.org_app_record.new_org
key_name = '%s/%s' % (
diff --git a/app/soc/modules/gsoc/views/program.py b/app/soc/modules/gsoc/views/program.py
index b69b224..b7d1d75 100644
--- a/app/soc/modules/gsoc/views/program.py
+++ b/app/soc/modules/gsoc/views/program.py
@@ -66,7 +66,7 @@
class Meta:
css_prefix = 'timeline_form'
model = timeline_model.GSoCTimeline
- exclude = ['link_id', 'scope', 'scope_path']
+ exclude = ['link_id', 'scope']
class CreateProgramForm(forms.GSoCModelForm):
@@ -80,9 +80,9 @@
css_prefix = 'create_program_form'
model = program.GSoCProgram
exclude = [
- 'scope', 'scope_path', 'timeline', 'slots_allocation',
+ 'scope', 'timeline', 'slots_allocation', 'events_page',
'student_max_age', 'min_slots', 'org_admin_agreement',
- 'mentor_agreement', 'student_agreement', 'about_page', 'events_page',
+ 'mentor_agreement', 'student_agreement', 'about_page',
'connect_with_us_page', 'help_page']
@@ -97,8 +97,8 @@
css_prefix = 'edit_program_form'
model = program.GSoCProgram
exclude = [
- 'link_id', 'scope', 'scope_path', 'timeline',
- 'slots_allocation', 'student_max_age', 'min_slots']
+ 'link_id', 'scope', 'timeline', 'min_slots',
+ 'slots_allocation', 'student_max_age']
class GSoCProgramMessagesForm(forms.GSoCModelForm):
diff --git a/app/soc/modules/gsoc/views/student_evaluation.py b/app/soc/modules/gsoc/views/student_evaluation.py
index eedd92a..bc51bc8 100644
--- a/app/soc/modules/gsoc/views/student_evaluation.py
+++ b/app/soc/modules/gsoc/views/student_evaluation.py
@@ -45,8 +45,8 @@
model = ProjectSurvey
css_prefix = 'gsoc-student-eval-edit'
exclude = ['program', 'scope', 'author', 'created_by', 'modified_by',
- 'survey_content', 'scope_path', 'link_id', 'prefix',
- 'read_access', 'write_access', 'taking_access', 'is_featured']
+ 'survey_content', 'link_id', 'prefix', 'is_featured',
+ 'read_access', 'write_access', 'taking_access']
class GSoCStudentEvaluationTakeForm(gsoc_forms.SurveyTakeForm):
diff --git a/app/soc/modules/seeder/logic/providers/string.py b/app/soc/modules/seeder/logic/providers/string.py
index 2718742..f8ffb44 100644
--- a/app/soc/modules/seeder/logic/providers/string.py
+++ b/app/soc/modules/seeder/logic/providers/string.py
@@ -105,7 +105,6 @@
scope = values.get('scope', None)
if scope:
key_name = scope.key().name() + '/' + key_name
- values['scope_path'] = scope.key().name()
return key_name
diff --git a/app/soc/modules/seeder/logic/seeder.py b/app/soc/modules/seeder/logic/seeder.py
index 74707a5..b21a8dc 100644
--- a/app/soc/modules/seeder/logic/seeder.py
+++ b/app/soc/modules/seeder/logic/seeder.py
@@ -412,10 +412,6 @@
"""
result = properties.get(prop_name)
- # scope_path is to be produced from scope
- if prop_name == 'scope_path' and not result:
- return ''
-
# Specially generate link_id because it needs to be unique
if prop_name == 'link_id' and not result:
result = LinkIDProvider(model_class)
diff --git a/app/soc/views/document.py b/app/soc/views/document.py
index 04b1ea5..6ac40db 100644
--- a/app/soc/views/document.py
+++ b/app/soc/views/document.py
@@ -39,7 +39,7 @@
class Meta:
model = document_model.Document
exclude = [
- 'scope', 'scope_path', 'author', 'modified_by', 'prefix', 'home_for',
+ 'scope', 'author', 'modified_by', 'prefix', 'home_for',
'link_id', 'read_access', 'write_access', 'is_featured'
]
@@ -74,8 +74,8 @@
cleaned_data['link_id'] = data.kwargs['document']
cleaned_data['author'] = data.user
cleaned_data['prefix'] = prefix
- cleaned_data['scope'] = prefixes.getScopeForPrefix(prefix, data.scope_path)
- cleaned_data['scope_path'] = data.scope_path
+ cleaned_data['scope'] = prefixes.getScopeForPrefix(
+ prefix, data.scope_key_name)
document = document_form.create(key_name=data.key_name)
return document
diff --git a/app/soc/views/helper/access_checker.py b/app/soc/views/helper/access_checker.py
index cfbc5e3..a698113 100644
--- a/app/soc/views/helper/access_checker.py
+++ b/app/soc/views/helper/access_checker.py
@@ -272,7 +272,7 @@
self.data.key_name = unset
self.data.request_entity = unset
self.data.requester = unset
- self.data.scope_path = unset
+ self.data.scope_key_name = unset
self.data.url_profile = unset
self.data.url_student_info = unset
self.data.url_user = unset
@@ -305,7 +305,7 @@
if not all(fields):
raise BadRequest("Missing value for document url")
- self.data.scope_path = '/'.join(fields[1:-1])
+ self.data.scope_key_name = '/'.join(fields[1:-1])
self.data.key_name = '/'.join(fields)
self.data.document = Document.get_by_key_name(self.data.key_name)
diff --git a/app/soc/views/helper/request_data.py b/app/soc/views/helper/request_data.py
index 5cf0a9c..5d3fbe0 100644
--- a/app/soc/views/helper/request_data.py
+++ b/app/soc/views/helper/request_data.py
@@ -24,10 +24,10 @@
from django.core import urlresolvers
from django.utils import encoding
+from soc.logic import program as program_logic
from soc.logic import system
from soc.logic import site as site_logic
from soc.logic import user
-from soc.models import program as program_model
from soc.models import sponsor as sponsor_model
from soc.views.helper import access_checker
@@ -292,8 +292,7 @@
# because it requires a program to be fetched first. It seems to
# be acceptable, because there is a great chance that program has
# to also be provided at some point of request's life cycle.
- sponsor_key = program_model.Program.scope.get_value_for_datastore(
- self.program)
+ sponsor_key = program_logic.getSponsorKey(self.program)
self._sponsor = sponsor_model.Sponsor.get(sponsor_key)
@@ -395,7 +394,7 @@
assert access_checker.isSet(self._data.program)
program = self._data.program
self._clear()
- self.kwargs['sponsor'] = program.scope_path
+ self.kwargs['sponsor'] = program_logic.getSponsorKey(program).name()
def program(self, program=None):
"""Sets kwargs for an url_patterns.PROGRAM redirect."""
diff --git a/app/soc/views/helper/templatetags/forms_helpers.py b/app/soc/views/helper/templatetags/forms_helpers.py
deleted file mode 100644
index fe3c1d7..0000000
--- a/app/soc/views/helper/templatetags/forms_helpers.py
+++ /dev/null
@@ -1,424 +0,0 @@
-# Copyright 2008 the Melange authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""A Django template tag library containing forms helpers.
-"""
-
-
-import re
-
-from django import template
-from django.forms import forms as forms_in
-from django.template import defaultfilters as djangofilter
-from django.utils import simplejson
-from django.utils.encoding import force_unicode
-from django.utils.html import escape
-
-from soc.logic import accounts
-from soc.logic import dicts
-from soc.views.helper import widgets
-
-
-register = template.Library()
-
-
-@register.inclusion_tag('soc/templatetags/_as_user.html')
-def as_user(user):
- """Prints a user as a hyperlinked link_id.
- """
-
- return {'user': user}
-
-
-@register.inclusion_tag('soc/templatetags/_as_email.html')
-def as_email(account):
- """Prints a user as a hyperlinked link_id.
- """
-
- denormalized = accounts.denormalizeAccount(account)
-
- return {'email': denormalized.email()}
-
-
-@register.inclusion_tag('soc/templatetags/_as_upload_form.html')
-def as_upload_form(form, form_name, submit_button_text):
- """Prints an upload form.
- """
-
- return {
- 'form': form,
- 'form_name': form_name,
- 'submit_button_text': submit_button_text,
- }
-
-
-
-@register.inclusion_tag('soc/templatetags/_field_as_table_row.html')
-def field_as_table_row(field):
- """Prints a newforms field as a table row.
-
- This function actually does very little, simply passing the supplied
- form field instance in a simple context used by the _field_as_table_row.html
- template (which is actually doing all of the work).
-
- See soc/templates/soc/templatetags/_field_as_table_row.html for the CSS
- styles used by this template tag.
-
- Usage:
- {% load forms_helpers %}
- ...
- <table>
- {% field_as_table_row form.fieldname %}
- ...
- </table>
-
- Args:
- field: a Django newforms field instance
-
- Returns:
- a simple context containing the supplied newforms field instance:
- { 'field': field }
- """
- return {'field': field}
-
-
-@register.inclusion_tag('soc/templatetags/_readonly_field_as_table_row.html')
-def readonly_field_as_table_row(label, value):
- """Prints a field value and it's verbose name as a table row.
-
- This function actually does very little, simply passing the
- supplied field_label and field_value in a simple context used by the
- _readonly_field_as_table_row.html template (which is actually
- doing all of the work).
-
- See soc/templates/soc/templatetags/_readonly_field_as_table_row.html for
- the CSS styles used by this template tag.
-
- Usage:
- {% load forms_helpers %}
- ...
- <table>
- {% readonly_field_as_table_row field_label field_value %}
- ...
- </table>
-
- Args:
- field_label: label of the field to render
- field_value: value of the field to render
-
- Returns:
- a simple context containing the supplied newforms field instance:
- { 'field_label': field_label',
- 'field_value': field_value'}
- """
-
- value = value.strip() if isinstance(value, basestring) else value
-
- return {'field_label': label,
- 'field_value': value}
-
-
-@register.inclusion_tag(
- 'soc/templatetags/_readonly_field_as_twoline_table_row.html')
-def readonly_field_as_twoline_table_row(label, value):
- """See readonly_field_as_table_row().
- """
-
- value = value.strip() if isinstance(value, basestring) else value
-
- return {'field_label': label,
- 'field_value': value}
-
-@register.inclusion_tag('soc/templatetags/_readonly_field_as_table_row.html')
-def readonly_date_field_as_table_row(label, value):
- """Prints a field value formatted as the given format string.
-
- """
-
- import datetime
- if isinstance(value, datetime.datetime):
- if value.day % 10 == 1 and value.day != 11:
- ord_suf = 'st'
- elif value.day % 10 == 2 and value.day != 12:
- ord_suf = 'nd'
- elif value.day % 10 == 3 and value.day != 13:
- ord_suf = 'rd'
- else:
- ord_suf = 'th'
-
- fmt = "%d" + ord_suf + " %B %Y, %H:%M"
- value = value.strftime(fmt)
-
- return {'field_label': label,
- 'field_value': value}
-
-@register.inclusion_tag(
- 'soc/templatetags/_readonly_url_field_as_table_row.html')
-def readonly_url_field_as_table_row(field_label, field_value):
- """See readonly_field_as_table_row().
- """
- return {'field_label': field_label,
- 'field_value': field_value}
-
-
-@register.inclusion_tag(
- 'soc/templatetags/_readonly_url_field_as_twoline_table_row.html')
-def readonly_url_field_as_twoline_table_row(field_label, field_value):
- """See readonly_field_as_table_row().
- """
- return {'field_label': field_label,
- 'field_value': field_value}
-
-@register.inclusion_tag(
- 'soc/templatetags/_readonly_email_field_as_table_row.html')
-def readonly_email_field_as_table_row(field_label, field_value):
- """See readonly_field_as_table_row().
- """
- return {'field_label': field_label,
- 'field_value': field_value}
-
-@register.inclusion_tag(
- 'soc/templatetags/_readonly_safe_field_as_table_row.html')
-def readonly_safe_field_as_table_row(field_label, field_value):
- """See readonly_field_as_table_row().
- """
- return {'field_label': field_label,
- 'field_value': field_value}
-
-
-@register.inclusion_tag(
- 'soc/templatetags/_readonly_safe_field_as_twoline_table_row.html')
-def readonly_safe_field_as_twoline_table_row(field_label, field_value):
- """See readonly_field_as_table_row().
- """
- return {'field_label': field_label,
- 'field_value': field_value}
-
-
-@register.inclusion_tag('soc/templatetags/_as_readonly_table.html',
- takes_context=True)
-def as_readonly_table(context, form):
- """Outputs a form as a properly formatted html table.
-
- Args:
- form: the form that should be converted to a table
- """
-
- # create the bound fields
- fields = [forms_in.BoundField(form, field, name) for name, field in
- form.fields.items() if field]
-
- return {'fields': fields}
-
-@register.inclusion_tag('soc/templatetags/_as_table.html', takes_context=True)
-def as_table(context, form):
- """Outputs a form as a properly formatted html table.
-
- Args:
- form: the form that should be converted to a table
- """
-
- return as_table_helper(context, form)
-
-
-@register.inclusion_tag('soc/templatetags/_as_twoline_table.html',
- takes_context=True)
-def as_twoline_table(context, form):
- """Outputs a form as a properly formatted html table.
-
- Args:
- form: the form that should be converted to a table
- """
-
- return as_table_helper(context, form)
-
-
-def as_table_helper(context, form):
- """See as_table().
- """
-
- fields = []
- hidden_fields = []
- hidden_fields_errors = []
- errors = False
-
- # entity = context['entity']
-
- # support defining output order like in Django
- a = form.Meta
- if hasattr(form, 'Meta') and form.Meta.fields:
- items = [(i, form.fields[i]) for i in form.Meta.fields]
- else:
- items = form.fields.items()
-
- # Iterate over all fields and prepare it for adding
- for name, field in items:
- if not field:
- continue
-
- bf = forms_in.BoundField(form, field, name)
- attrs = {}
-
- if isinstance(field, widgets.ReferenceField):
- attrs = field.rf
-
- # If the field is hidden we display it elsewhere
- if not bf.is_hidden:
- if bf.errors:
- errors = True
-
- group = '0. '
-
- if hasattr(field, 'group'):
- group = field.group
-
- item = {
- 'field': bf,
- 'required': field.required,
- 'group': group,
- }
-
- item.update(attrs)
- fields.append(item)
- else:
- hidden_fields.append(unicode(bf))
-
- for error in bf.errors:
- item = (name, force_unicode(error))
- hidden_fields_errors.append(item)
-
- grouped = dicts.groupby(fields, 'group')
- rexp = re.compile(r"\d+. ")
- fields = [(rexp.sub('', key), grouped[key]) for key in sorted(grouped)]
-
- context.update({
- 'top_errors': form.non_field_errors() or '',
- 'hidden_field_errors': hidden_fields_errors or '',
- 'errors': errors,
- 'groups': fields if fields else '',
- 'hidden_fields': hidden_fields or '',
- 'form': form,
- 'json_for_js': {},
- })
-
- return context
-
-
-@register.inclusion_tag('soc/templatetags/_as_table_row.html',
- takes_context=True)
-def as_table_row(context, item):
- """Outputs a field as a properly formatted html row.
-
- Args:
- item: the item that is being rendered
- """
-
- return as_table_row_helper(context, item)
-
-
-@register.inclusion_tag('soc/templatetags/_as_twoline_table_row.html',
- takes_context=True)
-def as_twoline_table_row(context, item):
- """See as_table_row().
- """
-
- return as_table_row_helper(context, item)
-
-
-def as_table_row_helper(context, item):
- """See as_table_row().
- """
-
- field = item['field']
- required = item['required']
-
- form = context['form']
- entity = context.get('entity', None)
-
- reference = item.get('reference_url')
- filter = item.get('filter')
- filter_fields = item.get('filter_fields')
-
- # Escape and cache in local variable.
- errors = [force_unicode(escape(error)) for error in field.errors]
-
- if reference:
- from soc.views.helper import redirects
- params = {
- 'url_name': reference,
- }
- args = {}
-
- if entity:
- for filter_field, filter_value in filter_fields.iteritems():
- args[filter_field] = filter_value
- for filter_field in (i for i in filter if hasattr(entity, i)):
- args[filter_field] = getattr(entity, filter_field)
-
- if '__scoped__' in filter:
- args['scope_path'] = entity.key().id_or_name()
-
- # TODO: replace this hack needed to get org-scoped mentor
- # autocompletion on student proposals
- if '__org__' in filter:
- args['scope_path'] = entity.org.key().id_or_name()
-
- # even if the entity is not available, it can still be necessary
- # to access its potential scope path
- elif 'scope_path' in filter and 'scope_path' in context:
- args['scope_path'] = context['scope_path']
-
- params['args'] = '&'.join(['%s=%s' % item for item in args.iteritems()])
-
- select_url = redirects.getSelectRedirect(params)
-
- if field.label:
- label = escape(force_unicode(field.label))
-
- # Only add the suffix if the label does not end in punctuation.
- if form.label_suffix and (label[-1] not in ':?.!'):
- label += form.label_suffix
-
- label = field.label_tag(label) or ''
-
- field_class_type = 'formfield%slabel' % ('error' if errors else '')
-
- help_text = field.help_text
-
- context['json_for_js'][field.auto_id] = {
- 'autocomplete':
- djangofilter.safe(select_url) if reference else None,
- 'tooltip':
- djangofilter.linebreaksbr(
- force_unicode(help_text)
- ) if help_text else '',
- }
-
- context.update({
- 'help_text': force_unicode(help_text) if help_text else '',
- 'field_class_type': field_class_type,
- 'label': force_unicode(label) if field.label else '',
- 'field': field,
- 'field_id': field.auto_id,
- 'required': required,
- 'select_url': select_url if reference else None,
- 'errors': errors,
- })
-
- return context
-
-@register.simple_tag
-def tojson(json_dictionary):
- json_string = simplejson.dumps(json_dictionary, ensure_ascii=False)
- return json_string.replace('\"','"')
diff --git a/app/soc/views/org_profile.py b/app/soc/views/org_profile.py
index abe9767..ee5df7a 100644
--- a/app/soc/views/org_profile.py
+++ b/app/soc/views/org_profile.py
@@ -20,10 +20,10 @@
from soc.views import forms
PROFILE_EXCLUDE = [
- 'status', 'scope', 'scope_path', 'founder', 'founder', 'slots', 'note',
+ 'status', 'scope', 'founder', 'founder', 'slots', 'note', 'new_org',
'slots_calculated', 'nr_applications', 'nr_mentors', 'link_id',
- 'proposal_extra', 'new_org',
-]
+ 'proposal_extra',
+ ]
HOMEPAGE_INFO_GROUP = translation.ugettext(
'1. Homepage Info (displayed on org homepage)')
diff --git a/app/soc/views/profile.py b/app/soc/views/profile.py
index a00dfdb..3405290 100644
--- a/app/soc/views/profile.py
+++ b/app/soc/views/profile.py
@@ -41,7 +41,7 @@
PROFILE_EXCLUDE = [
# identification fields
- 'link_id', 'user', 'scope', 'scope_path', 'status',
+ 'link_id', 'user', 'scope', 'status',
'agreed_to_tos_on', 'name_on_documents',
# notification fields
'notify_new_requests', 'notify_new_invites',
diff --git a/app/soc/views/program.py b/app/soc/views/program.py
index 988c38b..edff3e2 100644
--- a/app/soc/views/program.py
+++ b/app/soc/views/program.py
@@ -46,7 +46,6 @@
timeline = self._createTimelineFromForm(data, form)
form.cleaned_data['timeline'] = timeline
form.cleaned_data['scope'] = data.sponsor
- form.cleaned_data['scope_path'] = data.sponsor.key().name()
key_name = '%s/%s' % (
data.sponsor.key().name(), form.cleaned_data['link_id'])
@@ -80,7 +79,6 @@
properties = {
'link_id': form.cleaned_data['link_id'],
'scope': data.sponsor,
- 'scope_path': data.sponsor.key().name(),
}
timeline_model = self._getTimelineModel()
diff --git a/app/soc/views/site.py b/app/soc/views/site.py
index c29caa8..acae524 100644
--- a/app/soc/views/site.py
+++ b/app/soc/views/site.py
@@ -52,7 +52,7 @@
class Meta:
model = site.Site
- exclude = ['link_id', 'scope', 'scope_path', 'xsrf_secret_key']
+ exclude = ['link_id', 'scope', 'xsrf_secret_key']
# NOTE(nathaniel): There aren't really no choices, it's just that we
# can't know what the choices are at module-load-time. For the moment
# we have to set the available choices below in EditSitePage.context.
diff --git a/tests/app/soc/logic/helper/test_prefixes.py b/tests/app/soc/logic/helper/test_prefixes.py
index 21daec3..62880ea 100644
--- a/tests/app/soc/logic/helper/test_prefixes.py
+++ b/tests/app/soc/logic/helper/test_prefixes.py
@@ -67,12 +67,6 @@
self.gsoc_org_key_name = self.gsoc_organization.key().name()
self.gci_org_key_name = self.gci_organization.key().name()
- def testGetOrSetScope(self):
- """Not tested because it is used in soc.logic.models.survey and
- soc.logic.models.document and soc.logic.models will be removed.
- """
- pass
-
def testGetScopeForPrefix(self):
"""Tests if the scope for a given prefix and key_name is returned.
"""
diff --git a/tests/app/soc/logic/test_cleaning.py b/tests/app/soc/logic/test_cleaning.py
index 823072a..76b8cdc 100644
--- a/tests/app/soc/logic/test_cleaning.py
+++ b/tests/app/soc/logic/test_cleaning.py
@@ -130,28 +130,6 @@
self.assertEqual(self.form.cleaned_data, cleaned_data_before)
self.assertEqual(self.form._errors, {})
- def testCleanScopePath(self):
- """Tests that scope_path field can be cleaned.
- """
- field_name = 'scope_path'
- clean_field = cleaning.clean_scope_path(field_name)
- # Test that the value will be returned if the value of field
- # has a valid scope_path format
- field_value = 'valid_scope_path'
- cleaned_data_before = {field_name: field_value}
- self.form.cleaned_data = cleaned_data_before.copy()
- self.assertEqual(clean_field(self.form), field_value)
- self.assertEqual(self.form.cleaned_data, cleaned_data_before)
- self.assertEqual(self.form._errors, {})
- # Test that forms.ValidationError will be raised if the value of field
- # has not a valid scope_path format
- field_value = 'v1_@?'
- cleaned_data_before = {field_name: field_value}
- self.form.cleaned_data = cleaned_data_before.copy()
- self.assertRaises(forms.ValidationError, clean_field, self.form)
- self.assertEqual(self.form.cleaned_data, cleaned_data_before)
- self.assertEqual(self.form._errors, {})
-
def testCleanExistingUser(self):
"""Tests that the user field can be cleaned for existing users.
"""
diff --git a/tests/app/soc/logic/test_links.py b/tests/app/soc/logic/test_links.py
index c6e9531..c8b6ffa 100644
--- a/tests/app/soc/logic/test_links.py
+++ b/tests/app/soc/logic/test_links.py
@@ -19,17 +19,10 @@
from soc.logic import links
-TEST_PROGRAM_SPONSOR = 'test_sponsor'
TEST_PROGRAM_NAME = 'test_program'
TEST_SPONSOR_KEY_NAME = 'test_sponsor_key_name'
-# TODO(nathaniel): use a real program here.
-class MockProgram(object):
- scope_path = TEST_PROGRAM_SPONSOR
- link_id = TEST_PROGRAM_NAME
-
-
class MockKey(object):
def __init__(self, name):
@@ -44,6 +37,12 @@
return MockKey(TEST_SPONSOR_KEY_NAME)
+# TODO(nathaniel): use a real program here.
+class MockProgram(object):
+ scope = MockSponsor()
+ link_id = TEST_PROGRAM_NAME
+
+
# TODO(daniel): this class is on a non-specific level, but it refers
# to GCI specific names. Make it generic.
class TestLinker(unittest.TestCase):
@@ -57,7 +56,7 @@
def testProgram(self):
self.assertEqual(
- '/gci/homepage/%s/%s' % (TEST_PROGRAM_SPONSOR, TEST_PROGRAM_NAME),
+ '/gci/homepage/%s/%s' % (TEST_SPONSOR_KEY_NAME, TEST_PROGRAM_NAME),
self.linker.program(MockProgram(), 'gci_homepage'))
def testSponsor(self):
diff --git a/tests/app/soc/logic/test_validate.py b/tests/app/soc/logic/test_validate.py
index e1ad895..f196d5d 100644
--- a/tests/app/soc/logic/test_validate.py
+++ b/tests/app/soc/logic/test_validate.py
@@ -66,41 +66,6 @@
#invalid: a capital letter in the middle
self.assertFalse(validate.isLinkIdFormatValid('aBc'))
- def testIsScopePathFormatValid(self):
- """Tests the validity of Scope Paths.
-
- Scope paths are group of Link Ids separated by '/'.
- """
- #invalid: empty string
- self.assertFalse(validate.isScopePathFormatValid(''))
-
- #valid: single chunk
- self.assertTrue(validate.isScopePathFormatValid('addvw'))
-
- #invalid: starts with an underscore
- self.assertFalse(validate.isScopePathFormatValid('_jhads/sdafsa'))
-
- #valid: chunks separated by '/'
- self.assertTrue(validate.isScopePathFormatValid('adhcd/dfds'))
-
- #valid: has a double underscore
- self.assertTrue(validate.isScopePathFormatValid('ndfnsj__nj'))
-
- #invalid: starts with a capital letter
- self.assertFalse(validate.isScopePathFormatValid('Usdn_/sdfa'))
-
- #invalid: second chunk ends with '/'
- self.assertFalse(validate.isScopePathFormatValid('adsf/sdfgr/'))
-
- #invalid: first chunk should not start with a '/'
- self.assertFalse(validate.isScopePathFormatValid('/abc'))
-
- #invalid: has a capital letter
- self.assertFalse(validate.isScopePathFormatValid('aBc/def'))
-
- #valid: underscore in the middle and rest of the letters in lowercase
- self.assertTrue(validate.isScopePathFormatValid('a_b/cde'))
-
def testIsAgeSufficientForProgram(self):
test_program_start = datetime.date(2012, 11, 26)
test_min_age = 13
diff --git a/tests/app/soc/modules/gsoc/tasks/test_grading_survey_group.py b/tests/app/soc/modules/gsoc/tasks/test_grading_survey_group.py
index 045efb8..1fddea8 100644
--- a/tests/app/soc/modules/gsoc/tasks/test_grading_survey_group.py
+++ b/tests/app/soc/modules/gsoc/tasks/test_grading_survey_group.py
@@ -72,7 +72,7 @@
'modified_by': self.founder,
'link_id': 'link_id',
'scope': self.gsoc,
- 'scope_path': self.gsoc.key().id_or_name()}
+ }
self.project_survey = ps_model.ProjectSurvey(key_name='key_name',
**survey_values)
diff --git a/tests/app/soc/modules/gsoc/tasks/test_survey_reminders.py b/tests/app/soc/modules/gsoc/tasks/test_survey_reminders.py
index 298fef9..4214b35 100644
--- a/tests/app/soc/modules/gsoc/tasks/test_survey_reminders.py
+++ b/tests/app/soc/modules/gsoc/tasks/test_survey_reminders.py
@@ -67,7 +67,7 @@
'modified_by': self.founder,
'link_id': 'link_id',
'scope': self.gsoc,
- 'scope_path': self.gsoc.key().id_or_name()}
+ }
self.project_survey = ProjectSurvey(key_name='key_name',
**survey_values)