galaxy-commits
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
galaxy-dist commit 56431b214df1: Don't 'use strict' as FF4 beta doesn't support it
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kanwei Li <kanwei(a)gmail.com>
# Date 1289944688 18000
# Node ID 56431b214df16653a966b96bf399c7646da267b8
# Parent 394d8186f666b506cd0a93aefb7a079e0c9ec59b
Don't 'use strict' as FF4 beta doesn't support it
--- a/static/scripts/jquery.jstore.js
+++ b/static/scripts/jquery.jstore.js
@@ -15,7 +15,7 @@
* http://creativecommons.org/licenses/by/3.0/us
*/
-"use strict";
+//"use strict";
/*global Class, window, jQuery, ActiveXObject, google */
--- a/static/scripts/class.js
+++ b/static/scripts/class.js
@@ -5,7 +5,7 @@
* Inspired by base2 and Prototype
*/
-"use strict";
+//"use strict";
(function () {
--- a/static/scripts/packed/jquery.jstore.js
+++ b/static/scripts/packed/jquery.jstore.js
@@ -14,4 +14,4 @@
* Licensed under the Creative Commons Attribution 3.0 United States License:
* http://creativecommons.org/licenses/by/3.0/us
*/
-"use strict";(function(i,n){var h="JSTORE_ENGINE_UNSTABLE",t="JSTORE_UNKNOWN_ENGINE_REQUESTED",r="JSTORE_ENGINE_NAMESPACE_COLLISION",j="JSTORE_RESOURCE_NAMESPACE_COLLISION",m="JSTORE_ENGINE_UNAVAILABLE",o="JSTORE_INVALID_FLAVOR",f=(function(){try{return new RegExp('^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$')}catch(I){return(/^(true|false|null|\[.*\]|\{.*\}|".*"|\d+|\d+\.\d+)$/)}}()),b="jstore-html5-local",y="jstore-html5-sql",F="jstore-flash",G="jstore-google-gears",A="jstore-msie",u,E={},D={},C={},c=false,d={},q={project:undefined,flash:"jStore.Flash.html",json:"browser.json.js"},l;function z(I){switch(I){case b:case y:case F:case G:case A:return true;default:return false}}function g(I,J){return !I?false:I.constructor.toString().match(new RegExp(J+"\\(\\)","i"))!==null}function s(K,I,J){if(g(K,"Function")){return K.apply(I||E,g(J,"Array")?J:[J])}}function p(J,I){i.ajax({url:J,complete:I||i.noop(),type:"GET",dataType:"script",cache:false})}func
tion x(I){if(I===undefined){return""}if(g(I,"Object")||g(I,"Array")||g(I,"Function")){return JSON.stringify(I)}return I}function k(I){return f.test(I)?JSON.parse(I):I}function w(I){return I.replace(/^\s+|\s+$/g,"")}function e(I,J,K){if(!z(I)){throw o}if(K[I]!==undefined){throw r}if(s(K)===true){E.available[I]=true;J.flavor=I;D[I]=u.extend(J)}else{E.available[I]=false;E.enginePriority=i.map(E.enginePriority,function(L){if(L===I){return null}else{return L}})}}function v(){if(E.isReady){return}if((c&&E.isFlashReady)||!c){E.isReady=true;E.trigger("jstore-ready",[C[l]])}}function a(){E.create(E.enginePriority[0],undefined,"best-fit")}function H(){try{var J=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");try{J.AllowScriptAccess="always"}catch(L){return"6,0,0"}return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}catch(K){try{if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){return(navi
gator.plugins["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}}catch(I){}}return"0,0,0"}function B(I){var N=H().match(/\d+/g),L=I.match(/\d+/g),J=0,K,M;for(;J<3;J++){K=parseInt(N[J],10);M=parseInt(L[J],10);if(K<M){return false}else{if(K>M){return true}}}return true}i.extend(E,{enginePriority:[b,y,F,A],available:{},isReady:false,isFlashReady:false,flavors:{local:b,sql:y,flash:F,gears:G,msie:A},init:function(J,K,I){i.extend(q,{project:J},K);i(function(){if(n.JSON===undefined){p(q.json)}if(I!==undefined){E.create(I,J,"default")}else{a()}});return E},create:function(I,M,J){M=M||q.project||location.hostname.replace(/\./g,"-")||"unknown";if(!z(I)){throw o}if(D[I]===undefined){throw m}var L=(J!==undefined?J+".":"")+M+"."+I,K;if(C[L]!==undefined){throw j}K=C[L]=new D[I](M,L);K.ready(function(){E.trigger("jstore-engine-ready",[K])});if(I===F&&!E.isFlashReady){if(l===undefined){c=true}n.jstore_ready=function(){E.isFl
ashReady=true;E.trigger("flash-ready");if(l===undefined){v()}n.flash_ready=undefined};n.jstore_error=function(N){E.trigger("jstore-error",["JSTORE_FLASH_EXCEPTION",null,N])};i('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" id="jStoreFlashFrame" src="'+q.flash+'"></iframe>').appendTo("body")}else{if(l===undefined){l=L;v()}}return K},engine:function(I){return C[I]},activeEngine:function(I){if(I!==undefined){if(C[I]===undefined){throw t}else{l=I}}return C[l]},bind:function(J,K,I){I=I||"jstore";if(d[I]===undefined){d[I]={}}if(d[I][J]===undefined){d[I][J]=[K]}else{d[I][J].push(K)}return E},trigger:function(K,J,I){I=I||"jstore";if(d[I]!==undefined){if(d[I][K]!==undefined){i.each(d[I][K],function(){s(this,E,J)})}}return E},error:function(I){E.bind("jstore-error",I)},ready:function(I){if(E.isReady){s(I)}else{E.bind("jstore-ready",I)}return E},engineReady:function(I){if(E.isReady){s(I)}else{E.bind("jstore-engine-ready",I)}return E},store:func
tion(I,J){return J===undefined?E.get(I):E.set(I,J)},remove:function(I){return E.activeEngine().remove(I)},get:function(I){return E.activeEngine().get(I)},set:function(I,J){return E.activeEngine().set(I,J)}});u=Class.extend({project:undefined,jri:undefined,flavor:undefined,database:undefined,data:undefined,limit:undefined,isReady:undefined,init:function(J,I){this.project=J;this.jri=I;this.data={};this.isReady=false;this.updateCache()},updateCache:function(){this.isReady=true;this.trigger("engine-ready",[this])},bind:function(I,J){E.bind(I,J,this.jri)},trigger:function(J,I){E.trigger(J,I,this.jri)},ready:function(I){if(this.isReady){s(I,this)}else{this.bind("engine-ready",I)}},get:function(I){this.__interruptAccess();return this.data[I]},set:function(I,J){this.__interruptAccess();I=w(I);try{this.__set(I,J)}catch(K){E.trigger("jstore-error",["JSTORE_STORAGE_FAILURE",this.jri,K])}this.data[I]=J;return J},remove:function(J){this.__interruptAccess();J=w(J);try{this.__remove(J)}cat
ch(K){E.trigger("jstore-error",["JSTORE_REMOVE_FAILURE",this.jri,K])}var I=this.data[J];this.data[J]=undefined;return I},__interruptAccess:function(){if(!this.isReady){throw h}},__set:function(I,J){return},__remove:function(I){return}});i.extend(i.fn,{store:function(I,J){if(J===undefined){E.get(I)}else{E.set(I,J)}return this},removeStore:function(I){E.activeEngine().remove(I);return this},getStore:function(I){return E.activeEngine().get(I)},setStore:function(I,J){E.activeEngine().set(I,J);return this}});n.jStore=i.jStore=E;e(b,{limit:parseInt(500000,16),init:function(J,I){this.database=n.globalStorage===undefined?n.localStorage:n.globalStorage[location.hostname];this._super(J,I)},updateCache:function(){var J,K;for(J in this.database){var I=false;if(this.database.hasOwnProperty){if(this.database.hasOwnProperty(J)){I=true}}else{if(this.database.getItem(J)!==null){I=true}}if(I){K=this.database.getItem(J);this.data[J]=k(K&&K.value?K.value:K)}}this._super()},__set:function(I,J){t
his.database.setItem(I,x(J))},__remove:function(I){this.database.removeItem(I)}},function(){return n.localStorage!==undefined||n.globalStorage!==undefined});e(y,{limit:parseInt(32000,16),init:function(J,I){this.database=n.openDatabase("jstore-"+J,"1.0",J,this.limit);if(!this.database){throw"JSTORE_SQL_NO_DB"}this.database.transaction(function(K){K.executeSql("CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)")});this._super(J,I)},updateCache:function(){var I=this,J=this._super;this.database.transaction(function(K){K.executeSql("SELECT k,v FROM jstore",[],function(O,L){var N=L.rows,M=0,P;for(;M<N.length;++M){P=N.item(M);I.data[P.k]=k(P.v)}J.apply(I)})})},__set:function(I,J){this.database.transaction(function(K){K.executeSql("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[I,x(J)])})},__remove:function(I){this.database.transaction(function(J){J.executeSql("DELETE FROM jstore WHERE k = ?",[I])})}},function(){return n.openDatabase!==unde
fined});e(F,{limit:-1,init:function(K,J){var I=this;E.bind("flash-ready",function(){I.__flashReadyListener()});this._super(K,J)},updateCache:function(I){if(I===true){var J,K=this.database.jstore_get_all();for(J in K){if(K.hasOwnProperty(J)){this.data[J]=k(this.database.jstore_get(J))}}this._super()}},__set:function(I,J){if(!this.database.jstore_set(I,x(J))){E.trigger("jstore-error",["JSTORE_STORAGE_FAILURE",this.jri,"Flash Exception"])}},__remove:function(I){this.database.jstore_remove(I)},__flashReadyListener:function(){var I=i("#jStoreFlashFrame")[0],J;if(I.Document!==undefined&&g(I.Document.jStoreFlash.jstore_get,"Function")){this.database=I.Document.jStoreFlash}else{if(I.contentWindow&&I.contentWindow.document){J=i(I.contentWindow.document);if(g(i("object",J)[0].jstore_get,"Function")){this.database=i("object",J)[0]}else{if(g(i("embed",J)[0].jstore_get,"Function")){this.database=i("embed",J)[0]}}}}if(this.database===undefined){throw"JSTORE_FLASH_REFERENCE_ISSUE"}else{thi
s.updateCache(true)}}},function(){return B("9.0.0")});e(G,{limit:-1,init:function(J,I){this.database=google.gears.factory.create("beta.database");this.database.open("jstore-"+J);this.database.execute("CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)");this._super(J,I)},updateCache:function(){var I=this.database.execute("SELECT k,v FROM jstore");while(I.isValidRow()){this.data[I.field(0)]=k(I.field(1));I.next()}I.close();this._super()},__set:function(I,J){this.database.execute("BEGIN");this.database.execute("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[I,x(J)]);this.database.execute("COMMIT")},__remove:function(I){this.database.execute("BEGIN");this.database.execute("DELETE FROM jstore WHERE k = ?",[I]);this.database.execute("COMMIT")}},function(){return n.google!==undefined&&n.google.gears!==undefined});e(A,{limit:parseInt(10000,16),init:function(J,I){this.database=i('<div style="display:none;behavior:url(\'#default#userData\')"
id="jstore-'+J+'"></div>').appendTo(document.body).get(0);this._super(J,I)},updateCache:function(){this.database.load(this.project);var K=document.getElementById("jstore-"+this.project),L=K.XMLDocument,I,J=0;if(L&&L.documentElement&&L.documentElement.attributes){I=L.documentElement;for(;J<I.attributes.length;++J){this.data[I.attributes.item(J).nodeName]=k(I.attributes.item(J).nodeValue)}}this._super()},__set:function(I,J){this.database.setAttribute(I,x(J));this.database.save(this.project)},__remove:function(I){this.database.removeAttribute(I);this.database.save(this.project)}},function(){return n.ActiveXObject!==undefined})}(jQuery,window));
+(function(i,n){var h="JSTORE_ENGINE_UNSTABLE",t="JSTORE_UNKNOWN_ENGINE_REQUESTED",r="JSTORE_ENGINE_NAMESPACE_COLLISION",j="JSTORE_RESOURCE_NAMESPACE_COLLISION",m="JSTORE_ENGINE_UNAVAILABLE",o="JSTORE_INVALID_FLAVOR",f=(function(){try{return new RegExp('^("(\\\\.|[^"\\\\\\n\\r])*?"|[,:{}\\[\\]0-9.\\-+Eaeflnr-u \\n\\r\\t])+?$')}catch(I){return(/^(true|false|null|\[.*\]|\{.*\}|".*"|\d+|\d+\.\d+)$/)}}()),b="jstore-html5-local",y="jstore-html5-sql",F="jstore-flash",G="jstore-google-gears",A="jstore-msie",u,E={},D={},C={},c=false,d={},q={project:undefined,flash:"jStore.Flash.html",json:"browser.json.js"},l;function z(I){switch(I){case b:case y:case F:case G:case A:return true;default:return false}}function g(I,J){return !I?false:I.constructor.toString().match(new RegExp(J+"\\(\\)","i"))!==null}function s(K,I,J){if(g(K,"Function")){return K.apply(I||E,g(J,"Array")?J:[J])}}function p(J,I){i.ajax({url:J,complete:I||i.noop(),type:"GET",dataType:"script",cache:false})}function x(I){if(
I===undefined){return""}if(g(I,"Object")||g(I,"Array")||g(I,"Function")){return JSON.stringify(I)}return I}function k(I){return f.test(I)?JSON.parse(I):I}function w(I){return I.replace(/^\s+|\s+$/g,"")}function e(I,J,K){if(!z(I)){throw o}if(K[I]!==undefined){throw r}if(s(K)===true){E.available[I]=true;J.flavor=I;D[I]=u.extend(J)}else{E.available[I]=false;E.enginePriority=i.map(E.enginePriority,function(L){if(L===I){return null}else{return L}})}}function v(){if(E.isReady){return}if((c&&E.isFlashReady)||!c){E.isReady=true;E.trigger("jstore-ready",[C[l]])}}function a(){E.create(E.enginePriority[0],undefined,"best-fit")}function H(){try{var J=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");try{J.AllowScriptAccess="always"}catch(L){return"6,0,0"}return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}catch(K){try{if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){return(navigator.plugins
["Shockwave Flash 2.0"]||navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g,",").match(/^,?(.+),?$/)[1]}}catch(I){}}return"0,0,0"}function B(I){var N=H().match(/\d+/g),L=I.match(/\d+/g),J=0,K,M;for(;J<3;J++){K=parseInt(N[J],10);M=parseInt(L[J],10);if(K<M){return false}else{if(K>M){return true}}}return true}i.extend(E,{enginePriority:[b,y,F,A],available:{},isReady:false,isFlashReady:false,flavors:{local:b,sql:y,flash:F,gears:G,msie:A},init:function(J,K,I){i.extend(q,{project:J},K);i(function(){if(n.JSON===undefined){p(q.json)}if(I!==undefined){E.create(I,J,"default")}else{a()}});return E},create:function(I,M,J){M=M||q.project||location.hostname.replace(/\./g,"-")||"unknown";if(!z(I)){throw o}if(D[I]===undefined){throw m}var L=(J!==undefined?J+".":"")+M+"."+I,K;if(C[L]!==undefined){throw j}K=C[L]=new D[I](M,L);K.ready(function(){E.trigger("jstore-engine-ready",[K])});if(I===F&&!E.isFlashReady){if(l===undefined){c=true}n.jstore_ready=function(){E.isFlashReady=true
;E.trigger("flash-ready");if(l===undefined){v()}n.flash_ready=undefined};n.jstore_error=function(N){E.trigger("jstore-error",["JSTORE_FLASH_EXCEPTION",null,N])};i('<iframe style="height:1px;width:1px;position:absolute;left:0;top:0;margin-left:-100px;" id="jStoreFlashFrame" src="'+q.flash+'"></iframe>').appendTo("body")}else{if(l===undefined){l=L;v()}}return K},engine:function(I){return C[I]},activeEngine:function(I){if(I!==undefined){if(C[I]===undefined){throw t}else{l=I}}return C[l]},bind:function(J,K,I){I=I||"jstore";if(d[I]===undefined){d[I]={}}if(d[I][J]===undefined){d[I][J]=[K]}else{d[I][J].push(K)}return E},trigger:function(K,J,I){I=I||"jstore";if(d[I]!==undefined){if(d[I][K]!==undefined){i.each(d[I][K],function(){s(this,E,J)})}}return E},error:function(I){E.bind("jstore-error",I)},ready:function(I){if(E.isReady){s(I)}else{E.bind("jstore-ready",I)}return E},engineReady:function(I){if(E.isReady){s(I)}else{E.bind("jstore-engine-ready",I)}return E},store:function(I,J){ret
urn J===undefined?E.get(I):E.set(I,J)},remove:function(I){return E.activeEngine().remove(I)},get:function(I){return E.activeEngine().get(I)},set:function(I,J){return E.activeEngine().set(I,J)}});u=Class.extend({project:undefined,jri:undefined,flavor:undefined,database:undefined,data:undefined,limit:undefined,isReady:undefined,init:function(J,I){this.project=J;this.jri=I;this.data={};this.isReady=false;this.updateCache()},updateCache:function(){this.isReady=true;this.trigger("engine-ready",[this])},bind:function(I,J){E.bind(I,J,this.jri)},trigger:function(J,I){E.trigger(J,I,this.jri)},ready:function(I){if(this.isReady){s(I,this)}else{this.bind("engine-ready",I)}},get:function(I){this.__interruptAccess();return this.data[I]},set:function(I,J){this.__interruptAccess();I=w(I);try{this.__set(I,J)}catch(K){E.trigger("jstore-error",["JSTORE_STORAGE_FAILURE",this.jri,K])}this.data[I]=J;return J},remove:function(J){this.__interruptAccess();J=w(J);try{this.__remove(J)}catch(K){E.trigg
er("jstore-error",["JSTORE_REMOVE_FAILURE",this.jri,K])}var I=this.data[J];this.data[J]=undefined;return I},__interruptAccess:function(){if(!this.isReady){throw h}},__set:function(I,J){return},__remove:function(I){return}});i.extend(i.fn,{store:function(I,J){if(J===undefined){E.get(I)}else{E.set(I,J)}return this},removeStore:function(I){E.activeEngine().remove(I);return this},getStore:function(I){return E.activeEngine().get(I)},setStore:function(I,J){E.activeEngine().set(I,J);return this}});n.jStore=i.jStore=E;e(b,{limit:parseInt(500000,16),init:function(J,I){this.database=n.globalStorage===undefined?n.localStorage:n.globalStorage[location.hostname];this._super(J,I)},updateCache:function(){var J,K;for(J in this.database){var I=false;if(this.database.hasOwnProperty){if(this.database.hasOwnProperty(J)){I=true}}else{if(this.database.getItem(J)!==null){I=true}}if(I){K=this.database.getItem(J);this.data[J]=k(K&&K.value?K.value:K)}}this._super()},__set:function(I,J){this.database.
setItem(I,x(J))},__remove:function(I){this.database.removeItem(I)}},function(){return n.localStorage!==undefined||n.globalStorage!==undefined});e(y,{limit:parseInt(32000,16),init:function(J,I){this.database=n.openDatabase("jstore-"+J,"1.0",J,this.limit);if(!this.database){throw"JSTORE_SQL_NO_DB"}this.database.transaction(function(K){K.executeSql("CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)")});this._super(J,I)},updateCache:function(){var I=this,J=this._super;this.database.transaction(function(K){K.executeSql("SELECT k,v FROM jstore",[],function(O,L){var N=L.rows,M=0,P;for(;M<N.length;++M){P=N.item(M);I.data[P.k]=k(P.v)}J.apply(I)})})},__set:function(I,J){this.database.transaction(function(K){K.executeSql("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[I,x(J)])})},__remove:function(I){this.database.transaction(function(J){J.executeSql("DELETE FROM jstore WHERE k = ?",[I])})}},function(){return n.openDatabase!==undefined});e(F,{
limit:-1,init:function(K,J){var I=this;E.bind("flash-ready",function(){I.__flashReadyListener()});this._super(K,J)},updateCache:function(I){if(I===true){var J,K=this.database.jstore_get_all();for(J in K){if(K.hasOwnProperty(J)){this.data[J]=k(this.database.jstore_get(J))}}this._super()}},__set:function(I,J){if(!this.database.jstore_set(I,x(J))){E.trigger("jstore-error",["JSTORE_STORAGE_FAILURE",this.jri,"Flash Exception"])}},__remove:function(I){this.database.jstore_remove(I)},__flashReadyListener:function(){var I=i("#jStoreFlashFrame")[0],J;if(I.Document!==undefined&&g(I.Document.jStoreFlash.jstore_get,"Function")){this.database=I.Document.jStoreFlash}else{if(I.contentWindow&&I.contentWindow.document){J=i(I.contentWindow.document);if(g(i("object",J)[0].jstore_get,"Function")){this.database=i("object",J)[0]}else{if(g(i("embed",J)[0].jstore_get,"Function")){this.database=i("embed",J)[0]}}}}if(this.database===undefined){throw"JSTORE_FLASH_REFERENCE_ISSUE"}else{this.updateCache
(true)}}},function(){return B("9.0.0")});e(G,{limit:-1,init:function(J,I){this.database=google.gears.factory.create("beta.database");this.database.open("jstore-"+J);this.database.execute("CREATE TABLE IF NOT EXISTS jstore (k TEXT UNIQUE NOT NULL PRIMARY KEY, v TEXT NOT NULL)");this._super(J,I)},updateCache:function(){var I=this.database.execute("SELECT k,v FROM jstore");while(I.isValidRow()){this.data[I.field(0)]=k(I.field(1));I.next()}I.close();this._super()},__set:function(I,J){this.database.execute("BEGIN");this.database.execute("INSERT OR REPLACE INTO jstore(k, v) VALUES (?, ?)",[I,x(J)]);this.database.execute("COMMIT")},__remove:function(I){this.database.execute("BEGIN");this.database.execute("DELETE FROM jstore WHERE k = ?",[I]);this.database.execute("COMMIT")}},function(){return n.google!==undefined&&n.google.gears!==undefined});e(A,{limit:parseInt(10000,16),init:function(J,I){this.database=i('<div style="display:none;behavior:url(\'#default#userData\')" id="jstore-'+
J+'"></div>').appendTo(document.body).get(0);this._super(J,I)},updateCache:function(){this.database.load(this.project);var K=document.getElementById("jstore-"+this.project),L=K.XMLDocument,I,J=0;if(L&&L.documentElement&&L.documentElement.attributes){I=L.documentElement;for(;J<I.attributes.length;++J){this.data[I.attributes.item(J).nodeName]=k(I.attributes.item(J).nodeValue)}}this._super()},__set:function(I,J){this.database.setAttribute(I,x(J));this.database.save(this.project)},__remove:function(I){this.database.removeAttribute(I);this.database.save(this.project)}},function(){return n.ActiveXObject!==undefined})}(jQuery,window));
--- a/static/scripts/packed/class.js
+++ b/static/scripts/packed/class.js
@@ -4,4 +4,4 @@
* Copyright (c) 2008 John Resig (http://ejohn.org/blog/simple-javascript-inheritance/)
* Inspired by base2 and Prototype
*/
-"use strict";(function(){var a=false,b=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;this.Class=function(){};Class.extend=function(g){var f=this.prototype;a=true;var e=new this();a=false;for(var d in g){e[d]=(typeof g[d]==="function"&&typeof f[d]==="function"&&b.test(g[d])?(function(h,i){return function(){var k=this._super;this._super=f[h];var j=i.apply(this,arguments);this._super=k;return j}}(d,g[d])):g[d])}function c(){if(!a&&this.init){this.init.apply(this,arguments)}}c.prototype=e;c.constructor=c;c.extend=arguments.callee;return c}}());
+(function(){var a=false,b=/xyz/.test(function(){xyz})?/\b_super\b/:/.*/;this.Class=function(){};Class.extend=function(g){var f=this.prototype;a=true;var e=new this();a=false;for(var d in g){e[d]=(typeof g[d]==="function"&&typeof f[d]==="function"&&b.test(g[d])?(function(h,i){return function(){var k=this._super;this._super=f[h];var j=i.apply(this,arguments);this._super=k;return j}}(d,g[d])):g[d])}function c(){if(!a&&this.init){this.init.apply(this,arguments)}}c.prototype=e;c.constructor=c;c.extend=arguments.callee;return c}}());
1
0
galaxy-dist commit 7bded9108bd8: More miscellaneous Sample Tracking cleanup and bug fixes, move supported form_builder field types from form_builder.BaseField to Request.model and Sample.model.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Greg Von Kuster <greg(a)bx.psu.edu>
# Date 1290007512 18000
# Node ID 7bded9108bd8297ea609e9ec06bbe516b5f0b83a
# Parent a68c74ec8cfbc641db4b6fe424e3f77b9f3c5d3c
More miscellaneous Sample Tracking cleanup and bug fixes, move supported form_builder field types from form_builder.BaseField to Request.model and Sample.model.
--- a/templates/admin/requests/edit_request_type.mako
+++ b/templates/admin/requests/edit_request_type.mako
@@ -28,7 +28,7 @@
</div><div class="form-row"><label>
- Sequencing Request Form definition:
+ Sequencing request form definition:
</label><select name="form_id">
%for form in forms:
@@ -42,7 +42,7 @@
</div><div class="form-row"><label>
- Sample Form definition:
+ Sample form definition:
</label><select name="form_id">
%for form in forms:
--- a/lib/galaxy/web/form_builder.py
+++ b/lib/galaxy/web/form_builder.py
@@ -18,12 +18,6 @@ class BaseField(object):
return ' disabled="disabled"'
else:
return ''
- @staticmethod
- def form_field_types():
- return ['TextField', 'TextArea', 'SelectField', 'CheckboxField', 'AddressField', 'WorkflowField']
- @staticmethod
- def sample_field_types():
- return ['TextField', 'SelectField', 'CheckboxField', 'WorkflowField']
class TextField(BaseField):
"""
@@ -559,8 +553,8 @@ class AddressField(BaseField):
self.select_address.add_option( 'Add a new address', 'new' )
return self.select_address.get_html( disabled=disabled ) + address_html
-class WorkflowField(BaseField):
- def __init__(self, name, user=None, value=None, params=None):
+class WorkflowField( BaseField ):
+ def __init__( self, name, user=None, value=None, params=None ):
self.name = name
self.user = user
self.value = value
@@ -580,7 +574,7 @@ class WorkflowField(BaseField):
else:
self.select_workflow.add_option( a.name, str( a.id ) )
return self.select_workflow.get_html( disabled=disabled )
-
+
def get_suite():
"""Get unittest suite for this module"""
import doctest, sys
@@ -592,11 +586,11 @@ def build_select_field( trans, objs, lab
selected_value='none', refresh_on_change=False, multiple=False, display=None, size=None ):
"""
Build a SelectField given a set of objects. The received params are:
- - objs: the set of object used to populate the option list
+ - objs: the set of objects used to populate the option list
- label_attr: the attribute of each obj (e.g., name, email, etc ) whose value is used to populate each option label. If the string
'self' is passed as label_attr, each obj in objs is assumed to be a string, so the obj itself is used
- select_field_name: the name of the SelectField
- - initial_value: the vlaue of the first option in the SelectField - allows for an option telling the user to select something
+ - initial_value: the value of the first option in the SelectField - allows for an option telling the user to select something
- selected_value: the value of the currently selected option
- refresh_on_change: True if the SelectField should perform a refresh_on_change
"""
--- a/templates/admin/requests/view_request_type.mako
+++ b/templates/admin/requests/view_request_type.mako
@@ -38,7 +38,7 @@
<div style="clear: both"></div></div><div class="form-row">
- <label>Sequencing Request form definition</label>
+ <label>Sequencing request form definition</label>
${request_type.request_form.name}
</div><div class="form-row">
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1495,12 +1495,11 @@ class MetadataFile( object ):
class FormDefinition( object ):
# The following form_builder classes are supported by the FormDefinition class.
- # AddressField, CheckboxField, SelectField, TextArea, TextField, WorkflowField
supported_field_types = [ AddressField, CheckboxField, SelectField, TextArea, TextField, WorkflowField ]
types = Bunch( REQUEST = 'Sequencing Request Form',
SAMPLE = 'Sequencing Sample Form',
LIBRARY_INFO_TEMPLATE = 'Library information template',
- USER_INFO = 'User Information' )
+ USER_INFO = 'User Information' )
def __init__( self, name=None, desc=None, fields=[], form_definition_current=None, form_type=None, layout=None ):
self.name = name
self.desc = desc
@@ -1792,6 +1791,8 @@ class RequestTypePermissions( object ):
self.role = role
class Sample( object ):
+ # The following form_builder classes are supported by the Sample class.
+ supported_field_types = [ CheckboxField, SelectField, TextField, WorkflowField ]
bulk_operations = Bunch( CHANGE_STATE = 'Change state',
SELECT_LIBRARY = 'Select data library and folder' )
api_collection_visible_keys = ( 'id', 'name' )
--- a/lib/galaxy/web/controllers/requests_common.py
+++ b/lib/galaxy/web/controllers/requests_common.py
@@ -588,12 +588,8 @@ class RequestsCommon( BaseController, Us
request = trans.sa_session.query( trans.model.Request ).get( trans.security.decode_id( request_id ) )
except:
return invalid_id_redirect( trans, cntrller, request_id )
- events_list = []
- for event in request.events:
- events_list.append( ( event.state, time_ago( event.update_time ), event.comment ) )
return trans.fill_template( '/requests/common/view_request_history.mako',
cntrller=cntrller,
- events_list=events_list,
request=request )
@web.expose
@web.require_login( "edit email notification settings" )
@@ -777,7 +773,7 @@ class RequestsCommon( BaseController, Us
search_box=search_box )
@web.expose
@web.require_login( "sample events" )
- def sample_events( self, trans, cntrller, **kwd ):
+ def view_sample_history( self, trans, cntrller, **kwd ):
params = util.Params( kwd )
status = params.get( 'status', 'done' )
message = util.restore_text( params.get( 'message', '' ) )
@@ -786,15 +782,8 @@ class RequestsCommon( BaseController, Us
sample = trans.sa_session.query( trans.model.Sample ).get( trans.security.decode_id( sample_id ) )
except:
return invalid_id_redirect( trans, cntrller, sample_id )
- events_list = []
- for event in sample.events:
- events_list.append( ( event.state.name,
- event.state.desc,
- time_ago( event.update_time ),
- event.comment ) )
- return trans.fill_template( '/requests/common/sample_events.mako',
+ return trans.fill_template( '/requests/common/view_sample_history.mako',
cntrller=cntrller,
- events_list=events_list,
sample=sample )
@web.expose
@web.require_login( "add sample" )
@@ -1054,9 +1043,9 @@ class RequestsCommon( BaseController, Us
# selected sets of samples. If samples are selected, the sample_operation param
# will have a value other than 'none', and the samples param will be a list of
# encoded sample ids. There are currently only 2 multi-select operations;
- # 'Change state' and 'Select data library and folder'. If sample_operation is
- # 'none, then the samples param will be a list of sample objects.
- if sample_operation == 'Change state':
+ # model.Sample.bulk_operations.CHANGE_STATE and model.sample.bulk_operations.SELECT_LIBRARY.
+ # If sample_operation is 'none, then the samples param will be a list of sample objects.
+ if sample_operation == trans.model.Sample.bulk_operations.CHANGE_STATE:
sample_state_id = params.get( 'sample_state_id', None )
if sample_state_id in [ None, 'none' ]:
message = "Select a new state from the <b>Change current state</b> list before clicking the <b>Save</b> button."
@@ -1090,7 +1079,7 @@ class RequestsCommon( BaseController, Us
cntrller=cntrller,
action='update_request_state',
request_id=trans.security.encode_id( request.id ) ) )
- elif sample_operation == 'Select data library and folder':
+ elif sample_operation == trans.model.sample.bulk_operations.SELECT_LIBRARY:
# TODO: fix the code so that the sample_operation_select_field does not use
# sample_0_library_id as it's name. it should use something like sample_operation_library_id
# and sample_operation_folder_id because the name sample_0_library_id should belong to the
--- a/lib/galaxy/web/controllers/forms.py
+++ b/lib/galaxy/web/controllers/forms.py
@@ -64,12 +64,12 @@ class FormsGrid( grids.Grid ):
]
class Forms( BaseController ):
- # Empty form field
+ # Empty TextField
empty_field = { 'label': '',
'helptext': '',
'visible': True,
'required': False,
- 'type': BaseField.form_field_types()[0],
+ 'type': model.TextField.__name__,
'selectlist': [],
'layout': 'none',
'default': '' }
@@ -597,12 +597,12 @@ class Forms( BaseController ):
self.selectbox_options = []
# if the form is for defining samples, then use the sample field types
# which does not include TextArea & AddressField
- if form_type == trans.app.model.FormDefinition.types.SAMPLE:
- for ft in BaseField.sample_field_types():
- self.fieldtype.add_option(ft, ft)
+ if form_type == trans.model.FormDefinition.types.SAMPLE:
+ for ft in trans.model.Sample.supported_field_types:
+ self.fieldtype.add_option( ft.__name__, ft.__name__ )
else:
- for ft in BaseField.form_field_types():
- self.fieldtype.add_option(ft, ft)
+ for ft in trans.model.Request.supported_field_types:
+ self.fieldtype.add_option( ft.__name__, ft__name__ )
self.required = SelectField('field_required_'+str(index), display='radio')
self.required.add_option('Required', 'required')
self.required.add_option('Optional', 'optional', selected=True)
@@ -632,22 +632,22 @@ class Forms( BaseController ):
field[ 'selectlist' ] = ['', '']
# if the form is for defining samples, then use the sample field types
# which does not include TextArea & AddressField
- if form_type == trans.app.model.FormDefinition.types.SAMPLE:
- for ft in BaseField.sample_field_types():
- if ft == field['type']:
- self.fieldtype.add_option(ft, ft, selected=True)
+ if form_type == trans.model.FormDefinition.types.SAMPLE:
+ for ft in trans.model.Sample.supported_field_types:
+ if ft.__name__ == field[ 'type' ]:
+ self.fieldtype.add_option( ft.__name__, ft__name__, selected=True )
if ft == 'SelectField':
- self.selectbox_ui(field)
+ self.selectbox_ui( field )
else:
- self.fieldtype.add_option(ft, ft)
+ self.fieldtype.add_option( ft.__name__, ft.__name__ )
else:
- for ft in BaseField.form_field_types():
- if ft == field['type']:
- self.fieldtype.add_option(ft, ft, selected=True)
+ for ft in trans.model.Request.supported_field_types:
+ if ft.__name__ == field[ 'type' ]:
+ self.fieldtype.add_option( ft.__name__, ft.__name__, selected=True )
if ft == 'SelectField':
- self.selectbox_ui(field)
+ self.selectbox_ui( field )
else:
- self.fieldtype.add_option(ft, ft)
+ self.fieldtype.add_option( ft.__name__, ft.__name__ )
# required/optional
if field['required'] == 'required':
self.required = SelectField('field_required_'+str(self.index), display='radio')
--- a/templates/admin/requests/create_request_type.mako
+++ b/templates/admin/requests/create_request_type.mako
@@ -39,7 +39,7 @@
<div style="clear: both"></div></div>
%endfor
- <div class="toolFormTitle">Possible sample states</div>
+ <div class="toolFormTitle">Sample states</div>
%if len(rt_states_widgets):
%for index, info in enumerate(rt_states_widgets):
${render_state( index, info[0], info[1] )}
--- a/templates/requests/common/common.mako
+++ b/templates/requests/common/common.mako
@@ -160,7 +160,7 @@
%if is_unsubmitted:
<td>Unsubmitted</td>
%else:
- <td valign="top"><a href="${h.url_for( controller='requests_common', action='sample_events', cntrller=cntrller, sample_id=trans.security.encode_id( sample.id ) )}">${sample.state.name}</a></td>
+ <td valign="top"><a href="${h.url_for( controller='requests_common', action='view_sample_history', cntrller=cntrller, sample_id=trans.security.encode_id( sample.id ) )}">${sample.state.name}</a></td>
%endif
%else:
<td></td>
@@ -334,7 +334,7 @@
%if is_unsubmitted:
<td>Unsubmitted</td>
%else:
- <td><a id="sampleState-${sample.id}" href="${h.url_for( controller='requests_common', action='sample_events', cntrller=cntrller, sample_id=trans.security.encode_id( sample.id ) )}">${render_sample_state( sample )}</a></td>
+ <td><a id="sampleState-${sample.id}" href="${h.url_for( controller='requests_common', action='view_sample_history', cntrller=cntrller, sample_id=trans.security.encode_id( sample.id ) )}">${render_sample_state( sample )}</a></td>
%endif
%if sample_widget_library and library_cntrller is not None:
<td><a href="${h.url_for( controller='library_common', action='browse_library', cntrller=library_cntrller, id=trans.security.encode_id( sample_widget_library.id ) )}">${sample_widget_library.name}</a></td>
--- a/test/base/twilltestcase.py
+++ b/test/base/twilltestcase.py
@@ -1536,7 +1536,7 @@ class TwillTestCase( unittest.TestCase )
self.visit_url( "%s/requests_common/view_request_history?cntrller=%s&id=%s" % ( self.url, cntrller, request_id ) )
self.check_page( strings_displayed, strings_displayed_count, strings_not_displayed )
def view_sample_history( self, cntrller, sample_id, strings_displayed=[], strings_displayed_count=[], strings_not_displayed=[] ):
- self.visit_url( "%s/requests_common/sample_events?cntrller=%s&sample_id=%s" % ( self.url, cntrller, sample_id ) )
+ self.visit_url( "%s/requests_common/view_sample_history?cntrller=%s&sample_id=%s" % ( self.url, cntrller, sample_id ) )
self.check_page( strings_displayed, strings_displayed_count, strings_not_displayed )
def edit_basic_request_info( self, cntrller, request_id, name, new_name='', new_desc='', new_fields=[],
strings_displayed=[], strings_displayed_after_submit=[] ):
--- a/templates/requests/common/edit_basic_request_info.mako
+++ b/templates/requests/common/edit_basic_request_info.mako
@@ -8,7 +8,6 @@
is_unsubmitted = request.is_unsubmitted
can_add_samples = is_unsubmitted
can_reject = is_admin and is_submitted
- can_select_datasets = is_admin and ( is_complete or is_submitted )
can_submit_request = request.samples and is_unsubmitted
%>
@@ -24,9 +23,6 @@
%if can_reject:
<a class="action-button" href="${h.url_for( controller='requests_admin', action='reject_request', cntrller=cntrller, id=trans.security.encode_id( request.id ) )}">Reject this request</a>
%endif
- %if can_select_datasets:
- <a class="action-button" href="${h.url_for( controller='requests_admin', action='select_datasets_to_transfer', request_id=trans.security.encode_id( request.id ) )}">Select datasets to transfer</a>
- %endif
</div></ul>
--- /dev/null
+++ b/templates/requests/common/view_sample_history.mako
@@ -0,0 +1,38 @@
+<%inherit file="/base.mako"/>
+<%namespace file="/message.mako" import="render_msg" />
+
+<% from galaxy.web.framework.helpers import time_ago %>
+
+<br/><br/>
+<ul class="manage-table-actions">
+ <li><a class="action-button" href="${h.url_for( controller='requests_common', action='view_request', cntrller=cntrller, id=trans.security.encode_id( sample.request.id ) )}">Browse this request</a></li>
+</ul>
+
+%if message:
+ ${render_msg( message, status )}
+%endif
+
+<h3>History of sample "${sample.name}"</h3>
+
+<div class="toolForm">
+ <table class="grid">
+ <thead>
+ <tr>
+ <th>State</th>
+ <th>Description</th>
+ <th>Last Updated</th>
+ <th>Comments</th>
+ </tr>
+ </thead>
+ <tbody>
+ %for event in sample.events:
+ <tr>
+ <td><b>${event.state.name}</b></td>
+ <td>${event.state.desc}</td>
+ <td>${time_ago( event.update_time )}</td>
+ <td>${event.comment}</td>
+ </tr>
+ %endfor
+ </tbody>
+ </table>
+</div>
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -44,8 +44,6 @@ class Configuration( object ):
# web API
self.enable_api = string_as_bool( kwargs.get( 'enable_api', False ) )
self.enable_openid = string_as_bool( kwargs.get( 'enable_openid', False ) )
- # Communication with a sequencer
- self.enable_sequencer_communication = string_as_bool( kwargs.get( 'enable_sequencer_communication', False ) )
# dataset Track files
self.track_store_path = kwargs.get( "track_store_path", "${extra_files_path}/tracks")
self.tool_path = resolve_path( kwargs.get( "tool_path", "tools" ), self.root )
--- a/templates/requests/common/view_request_history.mako
+++ b/templates/requests/common/view_request_history.mako
@@ -2,6 +2,8 @@
<%namespace file="/message.mako" import="render_msg" /><%
+ from galaxy.web.framework.helpers import time_ago
+
is_admin = cntrller == 'requests_admin' and trans.user_is_admin()
is_complete = request.is_complete
is_submitted = request.is_submitted
@@ -41,16 +43,16 @@
<thead><tr><th>State</th>
- <th>Last Update</th>
+ <th>Last Updated</th><th>Comments</th></tr></thead><tbody>
- %for state, updated, comments in events_list:
- <tr class="libraryRow libraryOrFolderRow" id="libraryRow">
- <td><b><a>${state}</a></b></td>
- <td><a>${updated}</a></td>
- <td><a>${comments}</a></td>
+ %for event in request.events:
+ <tr>
+ <td><b>${event.state}</b></td>
+ <td>${time_ago( event.update_time )}</td>
+ <td>${event.comment}</td></tr>
%endfor
</tbody>
--- a/templates/requests/common/sample_events.mako
+++ /dev/null
@@ -1,44 +0,0 @@
-<%inherit file="/base.mako"/>
-<%namespace file="/message.mako" import="render_msg" />
-
-<%def name="title()">Events for Sample ${sample.name}</%def>
-
-<h2>Events for Sample "${sample.name}"</h2>
-<ul class="manage-table-actions">
- <li><a class="action-button" href="${h.url_for( controller='requests_common', action='view_request', cntrller=cntrller, id=trans.security.encode_id( sample.request.id ) )}">Browse this request</a></li>
-</ul>
-<h3>Sequencing Request "${sample.request.name}"</h3>
-
-%if message:
- ${render_msg( message, status )}
-%endif
-
-<div class="toolForm">
- <div class="form-row">
- <div class="toolParamHelp" style="clear: both;">
- <b>Possible states: </b>
- <% states = " > ".join([ ss.name for ss in sample.request.type.states ]) %>
- ${states}
- </div>
- </div>
- <table class="grid">
- <thead>
- <tr>
- <th>State</th>
- <th>Description</th>
- <th>Last Update</th>
- <th>Comments</th>
- </tr>
- </thead>
- <tbody>
- %for state, desc, updated, comments in events_list:
- <tr class="libraryRow libraryOrFolderRow" id="libraryRow">
- <td><b><a>${state}</a></b></td>
- <td><a>${desc}</a></td>
- <td><a>${updated}</a></td>
- <td><a>${comments}</a></td>
- </tr>
- %endfor
- </tbody>
- </table>
-</div>
1
0
galaxy-dist commit a68c74ec8cfb: OpenID support for Galaxy.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Nate Coraor <nate(a)bx.psu.edu>
# Date 1290006822 18000
# Node ID a68c74ec8cfbc641db4b6fe424e3f77b9f3c5d3c
# Parent 56431b214df16653a966b96bf399c7646da267b8
OpenID support for Galaxy.
--- a/eggs.ini
+++ b/eggs.ini
@@ -44,6 +44,7 @@ Paste = 1.6
PasteDeploy = 1.3.3
PasteScript = 1.7.3
pexpect = 2.4
+python_openid = 2.2.5
Routes = 1.12.3
SQLAlchemy = 0.5.6
sqlalchemy_migrate = 0.5.4
--- /dev/null
+++ b/templates/user/openid_manage.mako
@@ -0,0 +1,17 @@
+## Template generates a grid that enables user to select items.
+<%namespace file="../grid_base.mako" import="make_grid" />
+<%namespace file="login.mako" import="render_openid_form" />
+
+<%inherit file="../grid_base.mako" />
+
+<%def name="grid_body( grid )">
+ ${make_grid( grid )}
+ <h2>Associate more OpenIDs</h2>
+ ${render_openid_form( kwargs['referer'], True, kwargs['openid_providers'] )}
+</%def>
+
+<%def name="center_panel()">
+ <div style="margin: 1em;">
+ ${grid_body( grid )}
+ </div>
+</%def>
Binary file static/images/openid-16x16.gif has changed
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1953,6 +1953,12 @@ class UserAddress( object ):
html = html + '<br/>' + 'Phone: ' + self.phone
return html
+class UserOpenID( object ):
+ def __init__( self, user=None, session=None, openid=None ):
+ self.user = user
+ self.session = session
+ self.openid = openid
+
class Page( object ):
def __init__( self ):
self.id = None
--- a/templates/user/index.mako
+++ b/templates/user/index.mako
@@ -15,6 +15,9 @@
%if trans.app.config.enable_api:
<li><a href="${h.url_for( controller='user', action='api_keys' )}">${_('Manage your API Keys')}</a> for new histories</li>
%endif
+ %if trans.app.config.enable_openid:
+ <li><a href="${h.url_for( controller='user', action='openid_manage' )}">${ ('Manage OpenIDs')}</a> linked to your account</li>
+ %endif
%else:
<li><a href="${h.url_for( controller='user', action='show_info', webapp='community' )}">${_('Manage your information')}</a></li>
%endif
--- /dev/null
+++ b/lib/galaxy/model/migrate/versions/0062_user_openid_table.py
@@ -0,0 +1,48 @@
+"""
+Migration script to create table for associating sessions and users with
+OpenIDs.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import datetime
+now = datetime.datetime.utcnow
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData( migrate_engine )
+db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+# Table to add
+
+UserOpenID_table = Table( "galaxy_user_openid", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, index=True, default=now, onupdate=now ),
+ Column( "session_id", Integer, ForeignKey( "galaxy_session.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "openid", TEXT, index=True, unique=True ),
+ )
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+
+ # Create galaxy_user_openid table
+ try:
+ UserOpenID_table.create()
+ except Exception, e:
+ log.debug( "Creating galaxy_user_openid table failed: %s" % str( e ) )
+
+def downgrade():
+ metadata.reflect()
+
+ # Drop galaxy_user_openid table
+ try:
+ UserOpenID_table.drop()
+ except Exception, e:
+ log.debug( "Dropping galaxy_user_openid table failed: %s" % str( e ) )
--- a/templates/user/login.mako
+++ b/templates/user/login.mako
@@ -1,23 +1,77 @@
-<%inherit file="/base.mako"/>
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ if context.get('webapp'):
+ webapp = context.get('webapp')
+ else:
+ webapp = 'galaxy'
+ return '/webapps/%s/base_panels.mako' % webapp
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
+<%def name="init()">
+<%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.active_view=active_view
+ self.message_box_visible=False
+%>
+</%def>
+
<%namespace file="/message.mako" import="render_msg" />
-%if redirect_url:
- <script type="text/javascript">
- top.location.href = '${redirect_url}';
- </script>
-%endif
+<%def name="center_panel()">
+ ${body()}
+</%def>
-%if not redirect_url and message:
- ${render_msg( message, status )}
-%endif
+<%def name="body()">
-%if not trans.user:
+ %if redirect_url:
+ <script type="text/javascript">
+ top.location.href = '${redirect_url}';
+ </script>
+ %endif
+
+ %if context.get('use_panels'):
+ <div style="margin: 1em;">
+ %else:
+ <div>
+ %endif
+
+ %if message:
+ ${render_msg( message, status )}
+ %endif
+
+ %if not trans.user:
+
+ ${render_login_form()}
+
+ %if trans.app.config.enable_openid:
+ <br/>
+ ${render_openid_form( referer, False, openid_providers )}
+ %endif
+
+ %endif
+
+ </div>
+
+</%def>
+
+<%def name="render_login_form( form_action=None )">
+
+ <%
+ if form_action is None:
+ form_action = h.url_for( controller='user', action='login', use_panels=use_panels )
+ %>
+
%if header:
${header}
%endif
<div class="toolForm"><div class="toolFormTitle">Login</div>
- <form name="login" id="login" action="${h.url_for( controller='user', action='login' )}" method="post" >
+ <form name="login" id="login" action="${form_action}" method="post" ><div class="form-row"><label>Email address:</label><input type="text" name="email" value="${email}" size="40"/>
@@ -36,4 +90,32 @@
</div></form></div>
-%endif
+
+</%def>
+
+<%def name="render_openid_form( referer, auto_associate, openid_providers )">
+
+ <div class="toolForm">
+ <div class="toolFormTitle">OpenID Login</div>
+ <form name="openid" id="openid" action="${h.url_for( controller='user', action='openid_auth' )}" method="post" >
+ <div class="form-row">
+ <label>OpenID URL:</label>
+ <input type="text" name="openid_url" size="60" style="background-image:url('${h.url_for( '/static/images/openid-16x16.gif' )}' ); background-repeat: no-repeat; padding-right: 20px; background-position: 99% 50%;"/>
+ <input type="hidden" name="webapp" value="${webapp}" size="40"/>
+ <input type="hidden" name="referer" value="${referer}" size="40"/>
+ <input type="hidden" name="auto_associate" value="${auto_associate}" size="40"/>
+ </div>
+ <div class="form-row">
+ Or, authenticate with your <select name="openid_provider">
+ %for provider in openid_providers.keys():
+ <option>${provider}</option>
+ %endfor
+ </select> account.
+ </div>
+ <div class="form-row">
+ <input type="submit" name="login_button" value="Login"/>
+ </div>
+ </form>
+ </div>
+
+</%def>
--- a/lib/galaxy/eggs/__init__.py
+++ b/lib/galaxy/eggs/__init__.py
@@ -321,6 +321,7 @@ class GalaxyConfig( object ):
"pbs_python": lambda: "pbs" in self.config.get( "app:main", "start_job_runners" ).split(","),
"threadframe": lambda: self.config.get( "app:main", "use_heartbeat" ),
"guppy": lambda: self.config.get( "app:main", "use_memdump" ),
+ "python_openid": lambda: self.config.get( "app:main", "enable_openid" ),
"GeneTrack": lambda: sys.version_info[:2] >= ( 2, 5 ),
"pysam": check_pysam()
}.get( egg_name, lambda: True )()
--- /dev/null
+++ b/templates/user/openid_associate.mako
@@ -0,0 +1,75 @@
+<%!
+ def inherit(context):
+ if context.get('use_panels'):
+ if context.get('webapp'):
+ webapp = context.get('webapp')
+ else:
+ webapp = 'galaxy'
+ return '/webapps/%s/base_panels.mako' % webapp
+ else:
+ return '/base.mako'
+%>
+<%inherit file="${inherit(context)}"/>
+
+<%def name="init()">
+<%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.active_view=active_view
+ self.message_box_visible=False
+%>
+</%def>
+
+<%namespace file="/message.mako" import="render_msg" />
+<%namespace file="login.mako" import="render_login_form" />
+<%namespace file="register.mako" import="render_registration_form" />
+
+<%def name="center_panel()">
+ ${body()}
+</%def>
+
+<%def name="body()">
+
+ %if context.get('use_panels'):
+ <div style="margin: 1em;">
+ %else:
+ <div>
+ %endif
+
+ %if message:
+ ${render_msg( message, status )}
+ %endif
+
+ <h2>OpenID Account Association</h2>
+ <div>
+ OpenIDs must be associated with a Galaxy account before they can be used for authentication. This only needs to be done once per OpenID. You may associate your OpenID with an existing Galaxy account, or create a new one.
+ </div>
+ <br/>
+
+ %if len( openids ) > 1:
+ <div>
+ The following OpenIDs will be associated with the account chosen or created below.
+ <ul>
+ %for openid in openids:
+ <li>${openid.openid}</li>
+ %endfor
+ </ul>
+ </div>
+ %else:
+ <div>
+ The OpenID <strong>${openids[0].openid}</strong> will be associated with the account chosen or created.
+ </div>
+ %endif
+ <br/>
+
+ <% form_action = h.url_for( use_panels=use_panels ) %>
+
+ ${render_login_form( form_action=form_action )}
+
+ <br/>
+
+ ${render_registration_form( form_action=form_action )}
+
+ </div>
+
+</%def>
--- a/templates/user/register.mako
+++ b/templates/user/register.mako
@@ -22,8 +22,18 @@
## An admin user may be creating a new user account, in which case we want to display the registration form.
## But if the current user is not an admin user, then don't display the registration form.
%if trans.user_is_admin() or not trans.user:
+ ${render_registration_form()}
+%endif
+
+<%def name="render_registration_form( form_action=None )">
+
+ <%
+ if form_action is None:
+ form_action = h.url_for( controller='user', action='create', admin_view=admin_view )
+ %>
+
<div class="toolForm">
- <form name="registration" id="registration" action="${h.url_for( controller='user', action='create', admin_view=admin_view )}" method="post" >
+ <form name="registration" id="registration" action="${form_action}" method="post" ><div class="toolFormTitle">Create account</div><div class="form-row"><label>Email address:</label>
@@ -83,4 +93,5 @@
</div></form></div>
-%endif
+
+</%def>
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -324,6 +324,10 @@ use_interactive = True
# WYSIWYG editor that is very similar to a word processor.
#enable_pages = False
+# Enable authentication via OpenID. Allows users to log in to their Galaxy
+# account by authenticating with an OpenID provider.
+#enable_openid = False
+
# Enable the (experimental! beta!) Web API. Documentation forthcoming.
#enable_api = False
--- a/lib/galaxy/model/mapping.py
+++ b/lib/galaxy/model/mapping.py
@@ -68,6 +68,15 @@ UserAddress.table = Table( "user_address
Column( "deleted", Boolean, index=True, default=False ),
Column( "purged", Boolean, index=True, default=False ) )
+UserOpenID.table = Table( "galaxy_user_openid", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "create_time", DateTime, default=now ),
+ Column( "update_time", DateTime, index=True, default=now, onupdate=now ),
+ Column( "session_id", Integer, ForeignKey( "galaxy_session.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "openid", TEXT, index=True, unique=True ),
+ )
+
History.table = Table( "history", metadata,
Column( "id", Integer, primary_key=True),
Column( "create_time", DateTime, default=now ),
@@ -968,6 +977,17 @@ assign_mapper( context, UserAddress, Use
order_by=desc(UserAddress.table.c.update_time)),
) )
+assign_mapper( context, UserOpenID, UserOpenID.table,
+ properties=dict(
+ session=relation( GalaxySession,
+ primaryjoin=( UserOpenID.table.c.session_id == GalaxySession.table.c.id ),
+ backref='openids',
+ order_by=desc( UserOpenID.table.c.update_time ) ),
+ user=relation( User,
+ primaryjoin=( UserOpenID.table.c.user_id == User.table.c.id ),
+ backref='openids',
+ order_by=desc( UserOpenID.table.c.update_time ) ) ) )
+
assign_mapper( context, ValidationError, ValidationError.table )
--- a/templates/display_common.mako
+++ b/templates/display_common.mako
@@ -85,6 +85,8 @@
class_plural = "Forms"
elif a_class == model.RequestType:
class_plural = "sequencer configurations"
+ elif a_class == model.UserOpenID:
+ class_plural = "OpenIDs"
else:
class_plural = a_class.__name__ + "s"
return class_plural
--- a/lib/galaxy/app.py
+++ b/lib/galaxy/app.py
@@ -60,6 +60,10 @@ class UniverseApplication( object ):
self.heartbeat = None
self.memdump = None
self.memory_usage = None
+ # Container for OpenID authentication routines
+ if self.config.enable_openid:
+ from galaxy.web.framework import openid_manager
+ self.openid_manager = openid_manager.OpenIDManager( self.config.openid_consumer_cache_path )
# Start the heartbeat process if configured and available
if self.config.use_heartbeat:
from galaxy.util import heartbeat
--- /dev/null
+++ b/lib/galaxy/web/framework/openid_manager.py
@@ -0,0 +1,53 @@
+"""
+Mange the OpenID consumer and related data stores.
+"""
+
+import os, pickle, logging
+
+from galaxy import eggs
+eggs.require( 'python-openid' )
+
+import openid
+from openid import oidutil
+from openid.store import filestore
+from openid.consumer import consumer
+from openid.extensions import sreg
+
+log = logging.getLogger( __name__ )
+def oidlog( message, level=0 ):
+ log.debug( message )
+oidutil.log = oidlog
+
+class OpenIDManager( object ):
+ def __init__( self, cache_path ):
+ self.session_path = os.path.join( cache_path, 'session' )
+ self.store_path = os.path.join( cache_path, 'store' )
+ for dir in self.session_path, self.store_path:
+ if not os.path.exists( dir ):
+ os.makedirs( dir )
+ self.store = filestore.FileOpenIDStore( self.store_path )
+ def get_session( self, trans ):
+ session_file = os.path.join( self.session_path, str( trans.galaxy_session.id ) )
+ if not os.path.exists( session_file ):
+ pickle.dump( dict(), open( session_file, 'w' ) )
+ return pickle.load( open( session_file ) )
+ def persist_session( self, trans, oidconsumer ):
+ session_file = os.path.join( self.session_path, str( trans.galaxy_session.id ) )
+ pickle.dump( oidconsumer.session, open( session_file, 'w' ) )
+ def get_consumer( self, trans ):
+ return consumer.Consumer( self.get_session( trans ), self.store )
+ def add_sreg( self, trans, request, required=None, optional=None ):
+ if required is None:
+ required = []
+ if optional is None:
+ optional = []
+ sreg_request = sreg.SRegRequest( required=required, optional=optional )
+ request.addExtension( sreg_request )
+ def get_sreg( self, info ):
+ return sreg.SRegResponse.fromSuccessResponse( info )
+
+ # so I don't have to expose all of openid.consumer.consumer
+ FAILURE = consumer.FAILURE
+ SUCCESS = consumer.SUCCESS
+ CANCEL = consumer.CANCEL
+ SETUP_NEEDED = consumer.SETUP_NEEDED
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -39,9 +39,11 @@ class Configuration( object ):
# Where dataset files are stored
self.file_path = resolve_path( kwargs.get( "file_path", "database/files" ), self.root )
self.new_file_path = resolve_path( kwargs.get( "new_file_path", "database/tmp" ), self.root )
+ self.openid_consumer_cache_path = resolve_path( kwargs.get( "openid_consumer_cache_path", "database/openid_consumer_cache" ), self.root )
self.cookie_path = kwargs.get( "cookie_path", "/" )
# web API
self.enable_api = string_as_bool( kwargs.get( 'enable_api', False ) )
+ self.enable_openid = string_as_bool( kwargs.get( 'enable_openid', False ) )
# Communication with a sequencer
self.enable_sequencer_communication = string_as_bool( kwargs.get( 'enable_sequencer_communication', False ) )
# dataset Track files
@@ -161,7 +163,17 @@ class Configuration( object ):
if not os.path.isdir( path ):
raise ConfigurationError("Directory does not exist: %s" % path )
# Create the directories that it makes sense to create
- for path in self.file_path, self.new_file_path, self.job_working_directory, self.cluster_files_directory, self.template_cache, self.ftp_upload_dir, self.library_import_dir, self.user_library_import_dir, self.nginx_upload_store, './static/genetrack/plots', os.path.join( self.tool_data_path, 'shared', 'jars' ):
+ for path in self.file_path, \
+ self.new_file_path, \
+ self.job_working_directory, \
+ self.cluster_files_directory, \
+ self.template_cache, \
+ self.ftp_upload_dir, \
+ self.library_import_dir, \
+ self.user_library_import_dir, \
+ self.nginx_upload_store, \
+ './static/genetrack/plots', \
+ os.path.join( self.tool_data_path, 'shared', 'jars' ):
if path not in [ None, False ] and not os.path.isdir( path ):
try:
os.makedirs( path )
--- a/lib/galaxy/web/controllers/user.py
+++ b/lib/galaxy/web/controllers/user.py
@@ -1,9 +1,10 @@
"""
Contains the user interface in the Universe class
"""
+from galaxy.web.framework.helpers import time_ago, grids
from galaxy.web.base.controller import *
from galaxy.model.orm import *
-from galaxy import util
+from galaxy import util, model
import logging, os, string, re, smtplib, socket
from random import choice
from email.MIMEText import MIMEText
@@ -26,48 +27,337 @@ require_login_creation_template = requir
VALID_USERNAME_RE = re.compile( "^[a-z0-9\-]+$" )
+OPENID_PROVIDERS = { 'Google' : 'https://www.google.com/accounts/o8/id',
+ 'Yahoo!' : 'http://yahoo.com',
+ 'AOL/AIM' : 'http://openid.aol.com',
+ 'Flickr' : 'http://flickr.com',
+ 'Launchpad' : 'http://login.launchpad.net',
+ }
+
+class UserOpenIDGrid( grids.Grid ):
+ use_panels = False
+ title = "OpenIDs linked to your account"
+ model_class = model.UserOpenID
+ template = '/user/openid_manage.mako'
+ default_filter = { "openid" : "All" }
+ default_sort_key = "-create_time"
+ columns = [
+ grids.TextColumn( "OpenID URL", key="openid" ),
+ grids.GridColumn( "Created", key="create_time", format=time_ago ),
+ ]
+ operations = [
+ grids.GridOperation( "Delete", async_compatible=True ),
+ ]
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( self.model_class ).filter( self.model_class.user_id == trans.user.id )
+
class User( BaseController, UsesFormDefinitionWidgets ):
+ user_openid_grid = UserOpenIDGrid()
@web.expose
def index( self, trans, webapp='galaxy', **kwd ):
return trans.fill_template( '/user/index.mako', webapp=webapp )
@web.expose
+ def openid_auth( self, trans, webapp='galaxy', **kwd ):
+ if not trans.app.config.enable_openid:
+ return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' )
+ message = 'Unspecified failure authenticating via OpenID'
+ status = kwd.get( 'status', 'done' )
+ openid_url = kwd.get( 'openid_url', '' )
+ openid_provider = kwd.get( 'openid_provider', '' )
+ referer = kwd.get( 'referer', trans.request.referer )
+ auto_associate = util.string_as_bool( kwd.get( 'auto_associate', False ) )
+ use_panels = util.string_as_bool( kwd.get( 'use_panels', False ) )
+ action = 'login'
+ if auto_associate:
+ action = 'openid_manage'
+ if not referer:
+ referer = url_for( '/' )
+ consumer = trans.app.openid_manager.get_consumer( trans )
+ process_url = trans.request.base.rstrip( '/' ) + url_for( controller='user', action='openid_process', referer=referer, auto_associate=auto_associate )
+ if not openid_url and openid_provider and openid_provider in OPENID_PROVIDERS:
+ openid_url = OPENID_PROVIDERS[openid_provider]
+ if openid_url:
+ request = None
+ try:
+ request = consumer.begin( openid_url )
+ if request is None:
+ message = 'No OpenID services are available at %s' % openid_url
+ except Exception, e:
+ message = 'Failed to begin OpenID authentication: %s' % str( e )
+ if request is not None:
+ trans.app.openid_manager.add_sreg( trans, request, optional=[ 'nickname', 'email' ] )
+ if request.shouldSendRedirect():
+ redirect_url = request.redirectURL(
+ trans.request.base, process_url )
+ trans.app.openid_manager.persist_session( trans, consumer )
+ trans.response.send_redirect( redirect_url )
+ return
+ else:
+ form = request.htmlMarkup( trans.request.base, process_url, form_tag_attrs={'id':'openid_message','target':'_top'} )
+ trans.app.openid_manager.persist_session( trans, consumer )
+ return form
+ return trans.response.send_redirect( url_for( controller='user',
+ action=action,
+ use_panels=use_panels,
+ message=message,
+ status='error' ) )
+ @web.expose
+ def openid_process( self, trans, webapp='galaxy', **kwd ):
+ if not trans.app.config.enable_openid:
+ return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' )
+ auto_associate = util.string_as_bool( kwd.get( 'auto_associate', False ) )
+ action = 'login'
+ if auto_associate:
+ action = 'openid_manage'
+ if trans.app.config.bugs_email is not None:
+ contact = '<a href="mailto:%s">contact support</a>' % trans.app.config.bugs_email
+ else:
+ contact = 'contact support'
+ message = 'Verification failed for an unknown reason. Please contact support for assistance.'
+ status = 'error'
+ consumer = trans.app.openid_manager.get_consumer( trans )
+ info = consumer.complete( kwd, trans.request.url )
+ display_identifier = info.getDisplayIdentifier()
+ redirect_url = kwd.get( 'referer', url_for( '/' ) )
+ if info.status == trans.app.openid_manager.FAILURE and display_identifier:
+ message = "Login via OpenID failed. The technical reason for this follows, please include this message in your email if you need to %s to resolve this problem: %s" % ( contact, info.message )
+ return trans.response.send_redirect( url_for( controller='user',
+ action=action,
+ use_panels=True,
+ message=message,
+ status='error' ) )
+ elif info.status == trans.app.openid_manager.SUCCESS:
+ if info.endpoint.canonicalID:
+ display_identifier = info.endpoint.canonicalID
+ user_openid = trans.sa_session.query( trans.app.model.UserOpenID ).filter( trans.app.model.UserOpenID.table.c.openid == display_identifier ).first()
+ if not user_openid:
+ user_openid = trans.app.model.UserOpenID( session=trans.galaxy_session, openid=display_identifier )
+ elif not user_openid.user and user_openid.session.id != trans.galaxy_session.id:
+ user_openid.session = trans.galaxy_session
+ elif user_openid.user and not auto_associate:
+ trans.handle_user_login( user_openid.user, webapp )
+ trans.log_event( "User logged in via OpenID: %s" % display_identifier )
+ trans.response.send_redirect( redirect_url )
+ return
+ if auto_associate and trans.user:
+ # The user is already logged in and requested association from
+ # the user prefs as opposed to using the OpenID form on the
+ # login page.
+ if user_openid.user and user_openid.user.id != trans.user.id:
+ message = "The OpenID <strong>%s</strong> is already associated with another Galaxy account, <strong>%s</strong>. Please disassociate it from that account before attempting to associate it with a new account." % ( display_identifier, user_openid.user.email )
+ status = "error"
+ elif user_openid.user and user_openid.user.id == trans.user.id:
+ message = "The OpenID <strong>%s</strong> is already associated with your Galaxy account, <strong>%s</strong>." % ( display_identifier, trans.user.email )
+ status = "warning"
+ else:
+ user_openid.user_id = trans.user.id
+ trans.sa_session.add( user_openid )
+ trans.sa_session.flush()
+ trans.log_event( "User associated OpenID: %s" % display_identifier )
+ message = "The OpenID <strong>%s</strong> has been associated with your Galaxy account, <strong>%s</strong>." % ( display_identifier, trans.user.email )
+ status = "done"
+ trans.response.send_redirect( url_for( controller='user',
+ action='openid_manage',
+ use_panels=True,
+ message=message,
+ status=status ) )
+ return
+ trans.sa_session.add( user_openid )
+ trans.sa_session.flush()
+ message = "OpenID authentication was successful, but you need to associate your OpenID with a Galaxy account."
+ sreg_resp = trans.app.openid_manager.get_sreg( info )
+ try:
+ username = sreg_resp.get( 'nickname', '' )
+ except AttributeError:
+ username = ''
+ try:
+ email = sreg_resp.get( 'email', '' )
+ except AttributeError:
+ email = ''
+ trans.response.send_redirect( url_for( controller='user',
+ action='openid_associate',
+ use_panels=True,
+ username=username,
+ email=email,
+ message=message,
+ status='warning' ) )
+ elif info.status == trans.app.openid_manager.CANCEL:
+ message = "Login via OpenID was cancelled by an action at the OpenID provider's site."
+ status = "warning"
+ elif info.status == trans.app.openid_manager.SETUP_NEEDED:
+ if info.setup_url:
+ return trans.response.send_redirect( info.setup_url )
+ else:
+ message = "Unable to log in via OpenID. Setup at the provider is required before this OpenID can be used. Please visit your provider's site to complete this step."
+ return trans.response.send_redirect( url_for( controller='user',
+ action=action,
+ use_panels=True,
+ message=message,
+ status=status ) )
+ @web.expose
+ def openid_associate( self, trans, webapp='galaxy', **kwd ):
+ if not trans.app.config.enable_openid:
+ return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' )
+ use_panels = util.string_as_bool( kwd.get( 'use_panels', False ) )
+ message = kwd.get( 'message', '' )
+ status = kwd.get( 'status', 'done' )
+ email = kwd.get( 'email', '' )
+ username = kwd.get( 'username', '' )
+ referer = kwd.get( 'referer', trans.request.referer )
+ params = util.Params( kwd )
+ admin_view = util.string_as_bool( params.get( 'admin_view', False ) )
+ openids = trans.galaxy_session.openids
+ if not openids:
+ return trans.show_error_message( 'You have not successfully completed an OpenID authentication in this session. You can do so on the <a href="%s">login</a> page.' % url_for( controller='user', action='login', use_panels=use_panels ) )
+ elif admin_view:
+ return trans.show_error_message( 'Associating OpenIDs with accounts cannot be done by administrators.' )
+ if kwd.get( 'login_button', False ):
+ message, status, user, success = self.__validate_login( trans, webapp, **kwd )
+ if success:
+ for openid in openids:
+ openid.user = user
+ trans.sa_session.add( openid )
+ trans.sa_session.flush()
+ for openid in openids:
+ trans.log_event( "User associated OpenID: %s" % openid.openid )
+ redirect_url = referer
+ if not redirect_url:
+ redirect_url = url_for( '/' )
+ trans.response.send_redirect( redirect_url )
+ return
+ if kwd.get( 'create_user_button', False ):
+ password = kwd.get( 'password', '' )
+ confirm = kwd.get( 'confirm', '' )
+ subscribe = params.get( 'subscribe', '' )
+ subscribe_checked = CheckboxField.is_checked( subscribe )
+ error = ''
+ if not trans.app.config.allow_user_creation and not trans.user_is_admin():
+ error = 'User registration is disabled. Please contact your Galaxy administrator for an account.'
+ else:
+ # Check email and password validity
+ error = self.__validate( trans, params, email, password, confirm, username, webapp )
+ if not error:
+ # all the values are valid
+ message, status, user, success = self.__register( trans, webapp, email, password, username, subscribe_checked, kwd )
+ if success:
+ trans.handle_user_login( user, webapp )
+ trans.log_event( "User created a new account" )
+ trans.log_event( "User logged in" )
+ for openid in openids:
+ openid.user = user
+ trans.sa_session.add( openid )
+ trans.sa_session.flush()
+ for openid in openids:
+ trans.log_event( "User associated OpenID: %s" % openid.openid )
+ redirect_url = referer
+ if not redirect_url:
+ redirect_url = url_for( '/' )
+ trans.response.send_redirect( redirect_url )
+ else:
+ message = error
+ status = 'error'
+ if webapp == 'galaxy':
+ user_info_select, user_info_form, widgets = self.__user_info_ui( trans, **kwd )
+ else:
+ user_info_select = []
+ user_info_form = []
+ widgets = []
+ return trans.fill_template( '/user/openid_associate.mako',
+ webapp=webapp,
+ email=email,
+ password='',
+ confirm='',
+ username=username,
+ header='',
+ use_panels=use_panels,
+ redirect_url='',
+ referer='',
+ refresh_frames=[],
+ message=message,
+ status=status,
+ active_view="user",
+ subscribe_checked=False,
+ admin_view=False,
+ user_info_select=user_info_select,
+ user_info_form=user_info_form,
+ widgets=widgets,
+ openids=openids )
+ @web.expose
+ @web.require_login( 'manage OpenIDs' )
+ def openid_disassociate( self, trans, webapp='galaxy', **kwd ):
+ if not trans.app.config.enable_openid:
+ return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' )
+ params = util.Params( kwd )
+ ids = params.get( 'id', None )
+ message = params.get( 'message', None )
+ status = params.get( 'status', None )
+ use_panels = params.get( 'use_panels', False )
+ user_openids = []
+ if not ids:
+ message = 'You must select at least one OpenID to disassociate from your Galaxy account.'
+ status = 'error'
+ else:
+ ids = util.listify( params.id )
+ for id in ids:
+ id = trans.security.decode_id( id )
+ user_openid = trans.sa_session.query( trans.app.model.UserOpenID ).get( int( id ) )
+ if not user_openid or ( trans.user.id != user_openid.user_id ):
+ message = 'The selected OpenID(s) are not associated with your Galaxy account.'
+ status = 'error'
+ user_openids = []
+ break
+ user_openids.append( user_openid )
+ if user_openids:
+ deleted_urls = []
+ for user_openid in user_openids:
+ trans.sa_session.delete( user_openid )
+ deleted_urls.append( user_openid.openid )
+ trans.sa_session.flush()
+ for deleted_url in deleted_urls:
+ trans.log_event( "User disassociated OpenID: %s" % deleted_url )
+ message = '%s OpenIDs were disassociated from your Galaxy account.' % len( ids )
+ status = 'done'
+ trans.response.send_redirect( url_for( controller='user',
+ action='openid_manage',
+ use_panels=use_panels,
+ message=message,
+ status=status ) )
+ @web.expose
+ @web.require_login( 'manage OpenIDs' )
+ def openid_manage( self, trans, webapp='galaxy', **kwd ):
+ if not trans.app.config.enable_openid:
+ return trans.show_error_message( 'OpenID authentication is not enabled in this instance of Galaxy' )
+ use_panels = kwd.get( 'use_panels', False )
+ if 'operation' in kwd:
+ operation = kwd['operation'].lower()
+ if operation == "delete":
+ trans.response.send_redirect( url_for( controller='user',
+ action='openid_disassociate',
+ use_panels=use_panels,
+ id=kwd['id'] ) )
+ kwd['referer'] = url_for( controller='user', action='openid_manage', use_panels=True )
+ kwd['openid_providers'] = OPENID_PROVIDERS
+ return self.user_openid_grid( trans, **kwd )
+ @web.expose
def login( self, trans, webapp='galaxy', redirect_url='', refresh_frames=[], **kwd ):
referer = kwd.get( 'referer', trans.request.referer )
- use_panels = util.string_as_bool( kwd.get( 'use_panels', True ) )
+ use_panels = util.string_as_bool( kwd.get( 'use_panels', False ) )
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
header = ''
user = None
email = kwd.get( 'email', '' )
if kwd.get( 'login_button', False ):
- password = kwd.get( 'password', '' )
- referer = kwd.get( 'referer', '' )
if webapp == 'galaxy' and not refresh_frames:
if trans.app.config.require_login:
refresh_frames = [ 'masthead', 'history', 'tools' ]
else:
refresh_frames = [ 'masthead', 'history' ]
- user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email==email ).first()
- if not user:
- message = "No such user"
- status = 'error'
- elif user.deleted:
- message = "This account has been marked deleted, contact your Galaxy administrator to restore the account."
- status = 'error'
- elif user.external:
- message = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it."
- status = 'error'
- elif not user.check_password( password ):
- message = "Invalid password"
- status = 'error'
- else:
- trans.handle_user_login( user, webapp )
- trans.log_event( "User logged in" )
- message = 'You are now logged in as %s.<br>You can <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \
- ( user.email, referer, url_for( '/' ) )
- if trans.app.config.require_login:
- message += ' <a target="_top" href="%s">Click here</a> to continue to the home page.' % web.url_for( '/static/welcome.html' )
+ message, status, user, success = self.__validate_login( trans, webapp, **kwd )
+ if success and referer:
redirect_url = referer
+ elif success:
+ redirect_url = url_for( '/' )
if not user and trans.app.config.require_login:
if trans.app.config.allow_user_creation:
header = require_login_creation_template % web.url_for( action='create' )
@@ -83,7 +373,37 @@ class User( BaseController, UsesFormDefi
refresh_frames=refresh_frames,
message=message,
status=status,
+ openid_providers=OPENID_PROVIDERS,
active_view="user" )
+ def __validate_login( self, trans, webapp='galaxy', **kwd ):
+ message = kwd.get( 'message', '' )
+ status = kwd.get( 'status', 'done' )
+ email = kwd.get( 'email', '' )
+ password = kwd.get( 'password', '' )
+ referer = kwd.get( 'referer', trans.request.referer )
+ success = False
+ user = trans.sa_session.query( trans.app.model.User ).filter( trans.app.model.User.table.c.email==email ).first()
+ if not user:
+ message = "No such user"
+ status = 'error'
+ elif user.deleted:
+ message = "This account has been marked deleted, contact your Galaxy administrator to restore the account."
+ status = 'error'
+ elif user.external:
+ message = "This account was created for use with an external authentication method, contact your local Galaxy administrator to activate it."
+ status = 'error'
+ elif not user.check_password( password ):
+ message = "Invalid password"
+ status = 'error'
+ else:
+ trans.handle_user_login( user, webapp )
+ trans.log_event( "User logged in" )
+ message = 'You are now logged in as %s.<br>You can <a target="_top" href="%s">go back to the page you were visiting</a> or <a target="_top" href="%s">go to the home page</a>.' % \
+ ( user.email, referer, url_for( '/' ) )
+ if trans.app.config.require_login:
+ message += ' <a target="_top" href="%s">Click here</a> to continue to the home page.' % web.url_for( '/static/welcome.html' )
+ success = True
+ return ( message, status, user, success )
@web.expose
def logout( self, trans, webapp='galaxy' ):
if webapp == 'galaxy':
@@ -138,54 +458,25 @@ class User( BaseController, UsesFormDefi
error = self.__validate( trans, params, email, password, confirm, username, webapp )
if not error:
# all the values are valid
- user = trans.app.model.User( email=email )
- user.set_password_cleartext( password )
- user.username = username
- trans.sa_session.add( user )
- trans.sa_session.flush()
- trans.app.security_agent.create_private_user_role( user )
- message = 'Now logged in as %s.<br><a target="_top" href="%s">Return to the home page.</a>' % ( user.email, url_for( '/' ) )
- if webapp == 'galaxy':
- # We set default user permissions, before we log in and set the default history permissions
- trans.app.security_agent.user_set_default_permissions( user,
- default_access_private=trans.app.config.new_user_dataset_access_role_default_private )
- # save user info
- self.__save_user_info( trans, user, action='create', new_user=True, **kwd )
- if subscribe_checked:
- # subscribe user to email list
- if trans.app.config.smtp_server is None:
- error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed because mail is not configured for this Galaxy instance."
- else:
- msg = MIMEText( 'Join Mailing list.\n' )
- to = msg[ 'To' ] = trans.app.config.mailing_join_addr
- frm = msg[ 'From' ] = email
- msg[ 'Subject' ] = 'Join Mailing List'
- try:
- s = smtplib.SMTP()
- s.connect( trans.app.config.smtp_server )
- s.sendmail( frm, [ to ], msg.as_string() )
- s.close()
- except:
- error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed."
- if not error and not admin_view:
- # The handle_user_login() method has a call to the history_set_default_permissions() method
- # (needed when logging in with a history), user needs to have default permissions set before logging in
- trans.handle_user_login( user, webapp )
- trans.log_event( "User created a new account" )
- trans.log_event( "User logged in" )
- elif not error:
- trans.response.send_redirect( web.url_for( controller='admin',
- action='users',
- message='Created new user account (%s)' % user.email,
- status='done' ) )
- elif not admin_view:
+ message, status, user, success = self.__register( trans, webapp, email, password, username, subscribe_checked, kwd )
+ if success and not admin_view and webapp != 'galaxy':
# Must be logging into the community space webapp
trans.handle_user_login( user, webapp )
- if not error:
- redirect_url = referer
- if error:
- message=error
- status='error'
+ redirect_url = referer
+ if success and not admin_view:
+ # The handle_user_login() method has a call to the history_set_default_permissions() method
+ # (needed when logging in with a history), user needs to have default permissions set before logging in
+ trans.handle_user_login( user, webapp )
+ trans.log_event( "User created a new account" )
+ trans.log_event( "User logged in" )
+ elif success:
+ trans.response.send_redirect( web.url_for( controller='admin',
+ action='users',
+ message='Created new user account (%s)' % user.email,
+ status='done' ) )
+ else:
+ message = error
+ status = 'error'
if webapp == 'galaxy':
user_info_select, user_info_form, widgets = self.__user_info_ui( trans, **kwd )
else:
@@ -209,6 +500,57 @@ class User( BaseController, UsesFormDefi
refresh_frames=refresh_frames,
message=message,
status=status )
+ def __register( self, trans, webapp, email, password, username, subscribe_checked, kwd ):
+ status = kwd.get( 'status', 'done' )
+ admin_view = util.string_as_bool( kwd.get( 'admin_view', False ) )
+ user = trans.app.model.User( email=email )
+ user.set_password_cleartext( password )
+ user.username = username
+ trans.sa_session.add( user )
+ trans.sa_session.flush()
+ trans.app.security_agent.create_private_user_role( user )
+ error = ''
+ if webapp == 'galaxy':
+ # We set default user permissions, before we log in and set the default history permissions
+ trans.app.security_agent.user_set_default_permissions( user,
+ default_access_private=trans.app.config.new_user_dataset_access_role_default_private )
+ # save user info
+ self.__save_user_info( trans, user, action='create', new_user=True, **kwd )
+ if subscribe_checked:
+ # subscribe user to email list
+ if trans.app.config.smtp_server is None:
+ error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed because mail is not configured for this Galaxy instance."
+ else:
+ msg = MIMEText( 'Join Mailing list.\n' )
+ to = msg[ 'To' ] = trans.app.config.mailing_join_addr
+ frm = msg[ 'From' ] = email
+ msg[ 'Subject' ] = 'Join Mailing List'
+ try:
+ s = smtplib.SMTP()
+ s.connect( trans.app.config.smtp_server )
+ s.sendmail( frm, [ to ], msg.as_string() )
+ s.close()
+ except:
+ error = "Now logged in as " + user.email + ". However, subscribing to the mailing list has failed."
+ if not error and not admin_view:
+ # The handle_user_login() method has a call to the history_set_default_permissions() method
+ # (needed when logging in with a history), user needs to have default permissions set before logging in
+ trans.handle_user_login( user, webapp )
+ trans.log_event( "User created a new account" )
+ trans.log_event( "User logged in" )
+ elif not error:
+ trans.response.send_redirect( web.url_for( controller='admin',
+ action='users',
+ message='Created new user account (%s)' % user.email,
+ status='done' ) )
+ if error:
+ message = error
+ status = 'error'
+ success = False
+ else:
+ message = 'Now logged in as %s.<br><a target="_top" href="%s">Return to the home page.</a>' % ( user.email, url_for( '/' ) )
+ success = True
+ return ( message, status, user, success )
def __save_user_info(self, trans, user, action, new_user=True, **kwd):
'''
This method saves the user information for new users as well as editing user
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -29,12 +29,19 @@
##
<%def name="center_panel()">
- ${make_grid( grid )}
+ ${self.grid_body( grid )}
</%def>
## Render the grid's basic elements. Each of these elements can be subclassed.
<%def name="body()">
- ${make_grid( grid )}
+ ${self.grid_body( grid )}
+</%def>
+
+## Because body() is special and always exists even if not explicitly defined,
+## it's not possible to override body() in the topmost template in the chain.
+## Because of this, override grid_body() instead.
+<%def name="grid_body( grid )">
+ ${self.make_grid( grid )}
</%def><%def name="title()">${grid.title}</%def>
1
0
galaxy-dist commit 394d8186f666: tool_form: Make radio and select box labels explicitly inline. Workflow: add colons after parameter names where appropriate. Fixes #419
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Kanwei Li <kanwei(a)gmail.com>
# Date 1289929775 18000
# Node ID 394d8186f666b506cd0a93aefb7a079e0c9ec59b
# Parent 1bf064c8ab88621dd58890f6cd56ad4900d10d6b
tool_form: Make radio and select box labels explicitly inline. Workflow: add colons after parameter names where appropriate. Fixes #419
--- a/static/june_2007_style/base.css.tmpl
+++ b/static/june_2007_style/base.css.tmpl
@@ -210,6 +210,10 @@ div.form-row label {
margin-bottom: .2em;
}
+div.form-row label.inline {
+ display: inline;
+}
+
div.form-row-input {
float: left;
}
--- a/templates/workflow/editor_tool_form.mako
+++ b/templates/workflow/editor_tool_form.mako
@@ -7,8 +7,8 @@ from galaxy.util.expressions import Expr
<% ctx = ExpressionContext( values, ctx ) %>
%for input_index, input in enumerate( inputs.itervalues() ):
%if input.type == "repeat":
- <div class="repeat-group">
- <div class="form-title-row"><b>${input.title_plural}</b></div>
+ <div class="repeat-group form-row">
+ <label>${input.title_plural}:</label><% repeat_values = values[input.name] %>
%for i in range( len( repeat_values ) ):
<%
@@ -19,7 +19,7 @@ from galaxy.util.expressions import Expr
index = repeat_values[i]['__index__']
%><div class="repeat-group-item">
- <div class="form-title-row"><b>${input.title} ${i + 1}</b></div>
+ <div class="form-title-row"><label>${input.title} ${i + 1}</label></div>
${do_inputs( input.inputs, repeat_values[ i ], rep_errors, prefix + input.name + "_" + str(index) + "|", ctx )}
<div class="form-row"><input type="submit" name="${prefix}${input.name}_${index}_remove" value="Remove ${input.title} ${i+1}"></div></div>
@@ -63,7 +63,7 @@ from galaxy.util.expressions import Expr
%else:
%if isinstance( value, RuntimeValue ):
<label>
- ${param.get_label()}
+ ${param.get_label()}:
<span class="popupmenu"><button type="submit" name="make_buildtime" value="${prefix}${param.name}">Set in advance</button></span>
@@ -73,7 +73,7 @@ from galaxy.util.expressions import Expr
</div>
%else:
<label>
- ${param.get_label()}
+ ${param.get_label()}:
%if allow_runtime:
<span class="popupmenu"><button type="submit" name="make_runtime" value="${prefix}${param.name}">Set at runtime</button>
--- a/lib/galaxy/web/form_builder.py
+++ b/lib/galaxy/web/form_builder.py
@@ -248,16 +248,16 @@ class SelectField(BaseField):
>>> t.add_option( "tuti", 1 )
>>> t.add_option( "fruity", "x" )
>>> print t.get_html()
- <div><input type="radio" name="foo" value="1" id="foo|1"><label for="foo|1">tuti</label></div>
- <div><input type="radio" name="foo" value="x" id="foo|x"><label for="foo|x">fruity</label></div>
+ <div><input type="radio" name="foo" value="1" id="foo|1"><label class="inline" for="foo|1">tuti</label></div>
+ <div><input type="radio" name="foo" value="x" id="foo|x"><label class="inline" for="foo|x">fruity</label></div>
>>> t = SelectField( "bar", multiple=True, display="checkboxes" )
>>> t.add_option( "automatic", 3 )
>>> t.add_option( "bazooty", 4, selected=True )
>>> print t.get_html()
<div class="checkUncheckAllPlaceholder" checkbox_name="bar"></div>
- <div><input type="checkbox" name="bar" value="3" id="bar|3"><label for="bar|3">automatic</label></div>
- <div><input type="checkbox" name="bar" value="4" id="bar|4" checked='checked'><label for="bar|4">bazooty</label></div>
+ <div><input type="checkbox" name="bar" value="3" id="bar|3"><label class="inline" for="bar|3">automatic</label></div>
+ <div><input type="checkbox" name="bar" value="4" id="bar|4" checked='checked'><label class="inline" for="bar|4">bazooty</label></div>
"""
def __init__( self, name, multiple=None, display=None, refresh_on_change=False, refresh_on_change_values=[], size=None ):
self.name = name
@@ -302,7 +302,7 @@ class SelectField(BaseField):
selected_text = ""
if selected:
selected_text = " checked='checked'"
- rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" id="%s"%s%s><label for="%s">%s</label></div>' % \
+ rval.append( '<div%s><input type="checkbox" name="%s%s" value="%s" id="%s"%s%s><label class="inline" for="%s">%s</label></div>' % \
( style, prefix, self.name, escaped_value, uniq_id, selected_text, self.get_disabled_str( disabled ), uniq_id, text ) )
ctr += 1
return "\n".join( rval )
@@ -318,7 +318,7 @@ class SelectField(BaseField):
selected_text = ""
if selected:
selected_text = " checked='checked'"
- rval.append( '<div%s><input type="radio" name="%s%s"%s value="%s" id="%s"%s%s><label for="%s">%s</label></div>' % \
+ rval.append( '<div%s><input type="radio" name="%s%s"%s value="%s" id="%s"%s%s><label class="inline" for="%s">%s</label></div>' % \
( style,
prefix,
self.name,
--- a/static/june_2007_style/blue/base.css
+++ b/static/june_2007_style/blue/base.css
@@ -39,6 +39,7 @@ div.form-title-row{padding:5px 10px;}
div.repeat-group-item{border-left:solid #d8b365 5px;margin-left:10px;margin-bottom:10px;}
div.form-row-error{background:#FFCCCC;}
div.form-row label{font-weight:bold;display:block;margin-bottom:.2em;}
+div.form-row label.inline{display:inline;}
div.form-row-input{float:left;}
div.form-row-input label{font-weight:normal;display:inline;}
div.form-row-error-message{width:300px;float:left;color:red;font-weight:bold;padding:3px 0 0 1em;}
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -515,14 +515,14 @@ class SelectToolParameter( ToolParameter
blah
>>> print p.get_html()
<div class="checkUncheckAllPlaceholder" checkbox_name="blah"></div>
- <div><input type="checkbox" name="blah" value="x" id="blah|x"><label for="blah|x">I am X</label></div>
- <div class="odd_row"><input type="checkbox" name="blah" value="y" id="blah|y" checked='checked'><label for="blah|y">I am Y</label></div>
- <div><input type="checkbox" name="blah" value="z" id="blah|z" checked='checked'><label for="blah|z">I am Z</label></div>
+ <div><input type="checkbox" name="blah" value="x" id="blah|x"><label class="inline" for="blah|x">I am X</label></div>
+ <div class="odd_row"><input type="checkbox" name="blah" value="y" id="blah|y" checked='checked'><label class="inline" for="blah|y">I am Y</label></div>
+ <div><input type="checkbox" name="blah" value="z" id="blah|z" checked='checked'><label class="inline" for="blah|z">I am Z</label></div>
>>> print p.get_html( value=["x","y"])
<div class="checkUncheckAllPlaceholder" checkbox_name="blah"></div>
- <div><input type="checkbox" name="blah" value="x" id="blah|x" checked='checked'><label for="blah|x">I am X</label></div>
- <div class="odd_row"><input type="checkbox" name="blah" value="y" id="blah|y" checked='checked'><label for="blah|y">I am Y</label></div>
- <div><input type="checkbox" name="blah" value="z" id="blah|z"><label for="blah|z">I am Z</label></div>
+ <div><input type="checkbox" name="blah" value="x" id="blah|x" checked='checked'><label class="inline" for="blah|x">I am X</label></div>
+ <div class="odd_row"><input type="checkbox" name="blah" value="y" id="blah|y" checked='checked'><label class="inline" for="blah|y">I am Y</label></div>
+ <div><input type="checkbox" name="blah" value="z" id="blah|z"><label class="inline" for="blah|z">I am Z</label></div>
>>> print p.to_param_dict_string( ["y", "z"] )
y,z
"""
1
0
galaxy-dist commit 1bf064c8ab88: Fixed functional tests and samples grid alignment bug
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1289928056 18000
# Node ID 1bf064c8ab88621dd58890f6cd56ad4900d10d6b
# Parent 2e2ee0289d67d244954aa05bfe315dbb5ff413eb
Fixed functional tests and samples grid alignment bug
--- a/test/functional/test_sample_tracking.py
+++ b/test/functional/test_sample_tracking.py
@@ -341,7 +341,7 @@ class TestFormsAndRequests( TwillTestCas
request_id=self.security.encode_id( request1.id ),
strings_displayed=[ 'History of sequencing request "%s"' % request1.name,
request1.states.NEW,
- 'Request created' ],
+ 'Sequencing request created' ],
strings_not_displayed=[ request1.states.SUBMITTED,
request1.states.COMPLETE,
request1.states.REJECTED ] )
@@ -412,7 +412,7 @@ class TestFormsAndRequests( TwillTestCas
self.add_samples( cntrller='requests',
request_id=self.security.encode_id( request1.id ),
sample_value_tuples=sample_value_tuples,
- strings_displayed=[ 'Add Samples to Request "%s"' % request1.name,
+ strings_displayed=[ 'Add Samples to Sequencing Request "%s"' % request1.name,
'<input type="text" name="sample_0_name" value="Sample_1" size="10"/>' ], # sample name input field
strings_displayed_after_submit=strings_displayed_after_submit )
# check the new sample field values on the request page
@@ -446,7 +446,7 @@ class TestFormsAndRequests( TwillTestCas
self.edit_samples( cntrller='requests',
request_id=self.security.encode_id( request1.id ),
sample_value_tuples=new_sample_value_tuples,
- strings_displayed=[ 'Edit Current Samples of Request "%s"' % request1.name,
+ strings_displayed=[ 'Edit Current Samples of Sequencing Request "%s"' % request1.name,
'<input type="text" name="sample_0_name" value="Sample1" size="10"/>' ], # sample name input field
strings_displayed_after_submit=strings_displayed_after_submit )
# check the changed sample field values on the request page
@@ -465,14 +465,14 @@ class TestFormsAndRequests( TwillTestCas
self.submit_request( cntrller='requests',
request_id=self.security.encode_id( request1.id ),
request_name=request1.name,
- strings_displayed_after_submit=[ 'The request has been submitted.' ] )
+ strings_displayed_after_submit=[ 'The sequencing request has been submitted.' ] )
refresh( request1 )
# Make sure the request is showing in the 'submitted' filter
self.check_request_grid( cntrller='requests',
state=request1.states.SUBMITTED,
strings_displayed=[ request1.name ] )
# Make sure the request's state is now set to 'submitted'
- assert request1.state is not request1.states.SUBMITTED, "The state of the request '%s' should be set to '%s'" \
+ assert request1.state is not request1.states.SUBMITTED, "The state of the sequencing request '%s' should be set to '%s'" \
% ( request1.name, request1.states.SUBMITTED )
# the sample state should appear once for each sample
strings_displayed_count = [ ( request1.type.states[0].name, len( request1.samples ) ) ]
@@ -485,8 +485,8 @@ class TestFormsAndRequests( TwillTestCas
strings_displayed_count=strings_displayed_count,
strings_not_displayed=strings_not_displayed )
strings_displayed=[ 'History of sequencing request "%s"' % request1.name,
- 'Request submitted by %s' % regular_user1.email,
- 'Request created' ]
+ 'Sequencing request submitted by %s' % regular_user1.email,
+ 'Sequencing request created' ]
strings_displayed_count = [ ( request1.states.SUBMITTED, 1 ) ]
self.view_request_history( cntrller='requests',
request_id=self.security.encode_id( request1.id ),
@@ -519,7 +519,7 @@ class TestFormsAndRequests( TwillTestCas
self.add_bar_codes( cntrller='requests_admin',
request_id=self.security.encode_id( request1.id ),
bar_codes=bar_codes,
- strings_displayed=[ 'Edit Current Samples of Request "%s"' % request1.name ],
+ strings_displayed=[ 'Edit Current Samples of Sequencing Request "%s"' % request1.name ],
strings_displayed_after_submit=strings_displayed_after_submit )
# the second sample state should appear once for each sample
strings_displayed_count = [ ( request1.type.states[1].name, len( request1.samples ) ),
@@ -538,7 +538,7 @@ class TestFormsAndRequests( TwillTestCas
# check history of each sample
for sample in request1.samples:
strings_displayed = [ 'Events for Sample "%s"' % sample.name,
- 'Request submitted and sample state set to %s' % request1.type.states[0].name,
+ 'Sequencing request submitted and sample state set to %s' % request1.type.states[0].name,
request1.type.states[0].name,
request1.type.states[1].name ]
self.view_sample_history( cntrller='requests_admin',
@@ -558,9 +558,9 @@ class TestFormsAndRequests( TwillTestCas
if index > 1:
# status message
if index == len( request_type1.states ) - 1:
- status_msg = 'All samples of this request are in the final sample state (%s).' % state.name
+ status_msg = 'All samples of this sequencing request are in the final sample state (%s).' % state.name
else:
- status_msg = 'All samples of this request are in the (%s) sample state. ' % state.name
+ status_msg = 'All samples of this sequencing request are in the (%s) sample state. ' % state.name
# check email notification message
email_msg = ''
if state.id in [ email_state.id for email_state in email_notification_sample_states ]:
@@ -568,7 +568,7 @@ class TestFormsAndRequests( TwillTestCas
self.change_sample_state( request_id=self.security.encode_id( request1.id ),
sample_ids=[ sample.id for sample in request1.samples ],
new_sample_state_id=self.security.encode_id( state.id ),
- strings_displayed=[ 'Edit Current Samples of Request "%s"' % request1.name ],
+ strings_displayed=[ 'Edit Current Samples of Sequencing Request "%s"' % request1.name ],
strings_displayed_after_submit = [ status_msg, email_msg ] )
# check request history page
if index == len( request_type1.states ) - 1:
@@ -584,7 +584,7 @@ class TestFormsAndRequests( TwillTestCas
self.check_request_grid( cntrller='requests_admin',
state='Complete',
strings_displayed=[ request1.name ] )
- assert request1.state is not request1.states.COMPLETE, "The state of the request '%s' should be set to '%s'" \
+ assert request1.state is not request1.states.COMPLETE, "The state of the sequencing request '%s' should be set to '%s'" \
% ( request1.name, request1.states.COMPLETE )
# def test_045_admin_create_request_on_behalf_of_regular_user( self ):
--- a/templates/requests/common/common.mako
+++ b/templates/requests/common/common.mako
@@ -113,27 +113,23 @@
</script></%def>
-<%def name="render_editable_sample_row( cntrller, sample, sample_widget_index, sample_widget, encoded_selected_sample_ids )">
+<%def name="render_editable_sample_row( cntrller, request, sample, sample_widget_index, sample_widget, encoded_selected_sample_ids )"><%
+ trans.sa_session.refresh( request )
is_admin = cntrller == 'requests_admin' and trans.user_is_admin()
+ is_rejected = request.is_rejected
+ is_complete = request.is_complete
+ is_submitted = request.is_submitted
+ is_unsubmitted = request.is_unsubmitted
if sample:
- trans.sa_session.refresh( sample.request )
- is_complete = sample.request.is_complete
- is_rejected = request.is_rejected
- is_submitted = sample.request.is_submitted
- is_unsubmitted = sample.request.is_unsubmitted
can_delete_samples = editing_samples and request.samples and ( ( is_admin and not is_complete ) or is_unsubmitted )
display_checkboxes = editing_samples and ( is_complete or is_rejected or is_submitted )
- display_bar_code = request.samples and ( is_complete or is_rejected or is_submitted )
display_datasets = request.samples and ( is_complete or is_submitted )
else:
- is_complete = False
- is_submitted = False
- is_unsubmitted = False
can_delete_samples = False
display_checkboxes = False
- display_bar_code = False
display_datasets = False
+ display_bar_code = request.samples and ( is_complete or is_rejected or is_submitted )
%><%
if display_checkboxes and trans.security.encode_id( sample.id ) in encoded_selected_sample_ids:
@@ -152,15 +148,13 @@
</td>
%if display_bar_code:
<td valign="top">
- %if is_admin:
+ %if is_admin and is_submitted:
<input type="text" name="sample_${sample_widget_index}_bar_code" value="${sample_widget['bar_code']}" size="10"/>
%else:
${sample_widget['bar_code']}
<input type="hidden" name="sample_${sample_widget_index}_bar_code" value="${sample_widget['bar_code']}"/>
%endif
</td>
- %else:
- <td></td>
%endif
%if sample:
%if is_unsubmitted:
@@ -305,7 +299,7 @@
sample = None
%>
%if editing_samples:
- <tr>${render_editable_sample_row( cntrller, sample, sample_widget_index, sample_widget, encoded_selected_sample_ids )}</tr>
+ <tr>${render_editable_sample_row( cntrller, request, sample, sample_widget_index, sample_widget, encoded_selected_sample_ids )}</tr>
%elif sample:
<tr><td>
@@ -401,7 +395,7 @@
</tr>
%else:
## The Add sample button was clicked for this sample_widget
- <tr>${render_editable_sample_row( cntrller, None, sample_widget_index, sample_widget, encoded_selected_sample_ids )}</tr>
+ <tr>${render_editable_sample_row( cntrller, request, None, sample_widget_index, sample_widget, encoded_selected_sample_ids )}</tr>
%endif
%endfor
</tbody>
1
0
galaxy-dist commit 2bfb046649f0: Cleaned up the remote file size method so that only the file size is stored.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1289848701 18000
# Node ID 2bfb046649f059734e2709643785a95af3b85e81
# Parent 796201bc8dbc531ddaec5d75fadb88e858adfbc4
Cleaned up the remote file size method so that only the file size is stored.
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1864,20 +1864,21 @@ class Sample( object ):
untransferred_datasets.append( dataset )
return untransferred_datasets
def get_untransferred_dataset_size( self, filepath ):
- # TODO: RC: If rsh keys are not set, this method will return something like the following:
- # greg(a)scofield.bx.psu.edu's password: 46M /afs/bx.psu.edu/home/greg/chr22/chr21.fa
- # This method should return the number of bytes in the file. I believe du
- # displays the file system block usage which may not be the number of bytes in the file.
- # Would ls -l be better?
def print_ticks( d ):
pass
datatx_info = self.request.type.datatx_info
- cmd = 'ssh %s@%s "du -sh \'%s\'"' % ( datatx_info['username'], datatx_info['host'], filepath )
+ login_str = '%s@%s' % ( datatx_info['username'], datatx_info['host'] )
+ cmd = 'ssh %s "du -sh \'%s\'"' % ( login_str, filepath )
output = pexpect.run( cmd,
events={ '.ssword:*': datatx_info['password']+'\r\n',
pexpect.TIMEOUT:print_ticks},
timeout=10 )
- return output.replace( filepath, '' ).strip()
+ # cleanup the output to get just the file size
+ return output.replace( filepath, '' )\
+ .replace( 'Password:', '' )\
+ .replace( "'s password:", '' )\
+ .replace( login_str, '' )\
+ .strip()
def get_api_value( self, view='collection' ):
rval = {}
try:
1
0
galaxy-dist commit 9a7482206be2: Tweaks to taxonomy tools
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User Anton Nekrutenko <anton(a)bx.psu.edu>
# Date 1289851499 18000
# Node ID 9a7482206be274678079271331171600a2023b03
# Parent 3868982a4eff5036f13650ab303e0b9a4fb30da8
Tweaks to taxonomy tools
--- a/tools/taxonomy/t2ps_wrapper.py
+++ b/tools/taxonomy/t2ps_wrapper.py
@@ -59,7 +59,7 @@ except OSError, e:
# Convert PS to PDF
try:
- ps2pdf_cmd = 'ps2pdf %s %s' % ( ps_file.name, pdf_file )
+ ps2pdf_cmd = 'pstopdf %s -o %s' % ( ps_file.name, pdf_file )
retcode = subprocess.call( ps2pdf_cmd, shell=True )
if retcode < 0:
print >>sys.stderr, "Execution of ps2pdf terminated by signal", -retcode
--- a/scripts/taxonomy/processTaxonomy.sh
+++ b/scripts/taxonomy/processTaxonomy.sh
@@ -11,7 +11,7 @@ echo "Sorting gi2tax files..."
sort -n -k 1 gi_taxid_all.dmp > gi_taxid_sorted.txt
rm gi_taxid_nucl.dmp gi_taxid_prot.dmp gi_taxid_all.dmp
echo "Removing parenthesis from names.dmp"
-cat names.dmp | sed s/\(/_/g | sed s/\)/_/g > names.temporary
+cat names.dmp | sed s/[\(\)\'\"]/_/g > names.temporary
mv names.dmp names.dmp.orig
mv names.temporary names.dmp
1
0
galaxy-dist commit def13f052a4a: Restored the function to stop the edit samples form from getting submitted when return key is pressed. This is needed in this form as the barcode scanner (when in keyboard emulation mode) may send a return key appended to the scanned barcode string.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1289853524 18000
# Node ID def13f052a4a22c46ec5be6481ad874ceb734799
# Parent 02f6c9dae26e9aef40a44bc151ed07b457715839
Restored the function to stop the edit samples form from getting submitted when return key is pressed. This is needed in this form as the barcode scanner (when in keyboard emulation mode) may send a return key appended to the scanned barcode string.
--- a/scripts/galaxy_messaging/server/amqp_consumer.py
+++ b/scripts/galaxy_messaging/server/amqp_consumer.py
@@ -68,7 +68,7 @@ def update_sample_state( message ):
api_key = get_value(dom, 'api_key')
log.debug('Barcode: ' + barcode)
log.debug('State: ' + state)
- log.debug('api_key: ' + api_key)
+ log.debug('API Key: ' + api_key)
# validate
if not barcode or not state or not api_key:
log.debug( 'Incomplete sample_state_update message received. Sample barcode, desired state and user API key is required.' )
--- a/templates/requests/common/edit_samples.mako
+++ b/templates/requests/common/edit_samples.mako
@@ -14,6 +14,18 @@
${common_javascripts()}
</%def>
+<script type="text/javascript">
+ // This function stops the form from getting submitted when return key is pressed
+ // This is needed in this form as the barcode scanner (when in keyboard emulation mode)
+ // may send a return key appended to the scanned barcode string.
+ function stopRKey(evt) {
+ var evt = (evt) ? evt : ((event) ? event : null);
+ var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
+ if ((evt.keyCode == 13) && (node.type=="text")) {return false;}
+ }
+ document.onkeypress = stopRKey
+</script>
+
<%
from galaxy.web.framework.helpers import time_ago
1
0
galaxy-dist commit 5a217a7ce999: Replaced request with 'sequencing request' in sample tracking ui.
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User rc
# Date 1289922517 18000
# Node ID 5a217a7ce999bbe218432a7442751b5b78684798
# Parent 33dacaafc62eac4a8940c4bc978da1d1a6c68af9
Replaced request with 'sequencing request' in sample tracking ui.
Show the request page instead of the request grid after submitting the request
--- a/templates/admin/requests/edit_request_type.mako
+++ b/templates/admin/requests/edit_request_type.mako
@@ -28,7 +28,7 @@
</div><div class="form-row"><label>
- Request Form definition:
+ Sequencing Request Form definition:
</label><select name="form_id">
%for form in forms:
--- a/templates/requests/common/edit_samples.mako
+++ b/templates/requests/common/edit_samples.mako
@@ -69,16 +69,16 @@
</div></ul>
-%if request.samples_without_library_destinations:
+%if request.is_rejected:
<p>
- <font color="red"><b><i>Select a target data library and folder for a sample before selecting it's datasets to transfer from the sequencer</i></b></font>
+ <font color="red"><b>${request.last_comment}</b></font></p>
%endif
-%if request.is_rejected:
- <br/>
- <font color="red"><b><i>Reason for rejection: </i></b></font><b>${request.last_comment}</b>
- <br/>
+%if request.samples_without_library_destinations:
+ <p>
+ <font color="red"><b><i>Select a target data library and folder for a sample before selecting it's datasets to transfer from the sequencer</i></b></font>
+ </p>
%endif
%if message:
@@ -90,9 +90,9 @@
%if displayable_sample_widgets:
<%
if editing_samples:
- grid_header = '<h3>Edit Current Samples of Request "%s"</h3>' % request.name
+ grid_header = '<h3>Edit Current Samples of Sequencing Request "%s"</h3>' % request.name
else:
- grid_header = '<h3>Add Samples to Request "%s"</h3>' % request.name
+ grid_header = '<h3>Add Samples to Sequencing Request "%s"</h3>' % request.name
%>
${render_samples_grid( cntrller, request, displayable_sample_widgets, action='edit_samples', editing_samples=editing_samples, encoded_selected_sample_ids=encoded_selected_sample_ids, render_buttons=False, grid_header=grid_header )}
%if editing_samples and len( sample_operation_select_field.options ) > 1 and not is_unsubmitted:
--- a/lib/galaxy/web/controllers/requests_common.py
+++ b/lib/galaxy/web/controllers/requests_common.py
@@ -157,7 +157,7 @@ class RequestsCommon( BaseController, Us
status = 'error'
else:
request = self.__save_request( trans, cntrller, **kwd )
- message = 'The request has been created.'
+ message = 'The sequencing request has been created.'
if params.get( 'create_request_button', False ):
return trans.response.send_redirect( web.url_for( controller=cntrller,
action='browse_requests',
@@ -316,7 +316,7 @@ class RequestsCommon( BaseController, Us
trans.sa_session.flush()
trans.sa_session.refresh( request )
# Create an event with state 'New' for this new request
- comment = "Request created by %s" % trans.user.email
+ comment = "Sequencing request created by %s" % trans.user.email
if request.user != trans.user:
comment += " on behalf of %s." % request.user.email
event = trans.model.RequestEvent( request, request.states.NEW, comment )
@@ -358,7 +358,7 @@ class RequestsCommon( BaseController, Us
status='error',
message=message ) )
# Change the request state to 'Submitted'
- comment = "Request submitted by %s" % trans.user.email
+ comment = "Sequencing request submitted by %s" % trans.user.email
if request.user != trans.user:
comment += " on behalf of %s." % request.user.email
event = trans.model.RequestEvent( request, request.states.SUBMITTED, comment )
@@ -373,7 +373,7 @@ class RequestsCommon( BaseController, Us
# request's RequestType configured by the admin.
initial_sample_state_after_request_submitted = request.type.states[0]
for sample in request.samples:
- event_comment = 'Request submitted and sample state set to %s.' % request.type.states[0].name
+ event_comment = 'Sequencing request submitted and sample state set to %s.' % request.type.states[0].name
event = trans.model.SampleEvent( sample,
initial_sample_state_after_request_submitted,
event_comment )
@@ -381,9 +381,10 @@ class RequestsCommon( BaseController, Us
trans.sa_session.add( request )
trans.sa_session.flush()
request.send_email_notification( trans, initial_sample_state_after_request_submitted )
- message = 'The request has been submitted.'
- return trans.response.send_redirect( web.url_for( controller=cntrller,
- action='browse_requests',
+ message = 'The sequencing request has been submitted.'
+ # show the request page after submitting the request
+ return trans.response.send_redirect( web.url_for( controller='requests_common',
+ action='view_request',
cntrller=cntrller,
id=request_id,
status=status,
@@ -528,7 +529,7 @@ class RequestsCommon( BaseController, Us
for s in request.samples:
s.deleted = True
trans.sa_session.add( s )
- comment = "Request marked deleted by %s." % trans.user.email
+ comment = "Sequencing request marked deleted by %s." % trans.user.email
# There is no DELETED state for a request, so keep the current request state
event = trans.model.RequestEvent( request, request.state, comment )
trans.sa_session.add( event )
@@ -568,7 +569,7 @@ class RequestsCommon( BaseController, Us
for s in request.samples:
s.deleted = False
trans.sa_session.add( s )
- comment = "Request marked undeleted by %s." % trans.user.email
+ comment = "Sequencing request marked undeleted by %s." % trans.user.email
event = trans.model.RequestEvent( request, request.state, comment )
trans.sa_session.add( event )
trans.sa_session.flush()
@@ -686,11 +687,11 @@ class RequestsCommon( BaseController, Us
request_type_state = request.type.final_sample_state
if common_state.id == request_type_state.id:
# since all the samples are in the final state, change the request state to 'Complete'
- comment = "All samples of this request are in the final sample state (%s). " % request_type_state.name
+ comment = "All samples of this sequencing request are in the final sample state (%s). " % request_type_state.name
state = request.states.COMPLETE
final_state = True
else:
- comment = "All samples of this request are in the (%s) sample state. " % common_state.name
+ comment = "All samples of this sequencing request are in the (%s) sample state. " % common_state.name
state = request.states.SUBMITTED
event = trans.model.RequestEvent( request, state, comment )
trans.sa_session.add( event )
--- a/templates/admin/requests/view_request_type.mako
+++ b/templates/admin/requests/view_request_type.mako
@@ -38,7 +38,7 @@
<div style="clear: both"></div></div><div class="form-row">
- <label>Request form definition</label>
+ <label>Sequencing Request form definition</label>
${request_type.request_form.name}
</div><div class="form-row">
--- a/lib/galaxy/web/controllers/requests_admin.py
+++ b/lib/galaxy/web/controllers/requests_admin.py
@@ -223,11 +223,11 @@ class RequestsAdmin( BaseController, Use
status=status,
message=message )
# Create an event with state 'Rejected' for this request
- event_comment = "Request marked rejected by %s. Reason: %s " % ( trans.user.email, comment )
+ event_comment = "Sequencing request marked rejected by %s. Reason: %s " % ( trans.user.email, comment )
event = trans.model.RequestEvent( request, request.states.REJECTED, event_comment )
trans.sa_session.add( event )
trans.sa_session.flush()
- message='Request (%s) has been rejected.' % request.name
+ message='Sequencing request (%s) has been rejected.' % request.name
return trans.response.send_redirect( web.url_for( controller='requests_admin',
action='browse_requests',
status=status,
--- a/templates/admin/requests/reject.mako
+++ b/templates/admin/requests/reject.mako
@@ -5,7 +5,6 @@
${render_msg( message, status )}
%endif
<br/><br/>
-##<h2>Reject Sequencing Request "${request.name}"</h2><ul class="manage-table-actions"><li><a class="action-button" href="${h.url_for( controller='requests_common', action='view_request_history', cntrller=cntrller, id=trans.security.encode_id(request.id) )}">View history</a>
--- a/templates/requests/common/view_request.mako
+++ b/templates/requests/common/view_request.mako
@@ -52,14 +52,14 @@
</ul>
%if request.is_rejected:
- <br/>
- <font color="red"><b><i>Reason for rejection: </i></b></font><b>${request.last_comment}</b>
- <br/>
+ <p>
+ <font color="red"><b>${request.last_comment}</b></font>
+ </p>
%endif
%if request.samples_without_library_destinations:
<p>
- <font color="red"><b><i>Select a target data library and folder for a sample before selecting it's datasets to transfer from the sequencer</i></b></font>
+ <font color="red"><b><i>Select a target data library and folder for a sample before selecting it's datasets to transfer from the sequencer</i></b></font></p>
%endif
--- a/templates/requests/common/common.mako
+++ b/templates/requests/common/common.mako
@@ -159,6 +159,8 @@
<input type="hidden" name="sample_${sample_widget_index}_bar_code" value="${sample_widget['bar_code']}"/>
%endif
</td>
+ %else:
+ <td></td>
%endif
%if sample:
%if is_unsubmitted:
1
0
galaxy-dist commit d2d0c199c20d: Improvements to annotation display when running workflows: (1) workflow annotation is shown at the top of the page; (2) step annotations are shown in the step header rather than at the bottom. Fixes Issue #420
by commits-noreply@bitbucket.org 20 Nov '10
by commits-noreply@bitbucket.org 20 Nov '10
20 Nov '10
# HG changeset patch -- Bitbucket.org
# Project galaxy-dist
# URL http://bitbucket.org/galaxy/galaxy-dist/overview
# User jeremy goecks <jeremy.goecks(a)emory.edu>
# Date 1289925819 18000
# Node ID d2d0c199c20ddf942e1e2587dc9aede8acd9cebc
# Parent 5a217a7ce999bbe218432a7442751b5b78684798
Improvements to annotation display when running workflows: (1) workflow annotation is shown at the top of the page; (2) step annotations are shown in the step header rather than at the bottom. Fixes Issue #420
--- a/lib/galaxy/web/controllers/workflow.py
+++ b/lib/galaxy/web/controllers/workflow.py
@@ -1333,6 +1333,7 @@ class WorkflowController( BaseController
# Connections by input name
step.input_connections_by_name = dict( ( conn.input_name, conn ) for conn in step.input_connections )
# Render the form
+ stored.annotation = self.get_item_annotation_str( trans.sa_session, trans.user, stored )
return trans.fill_template(
"workflow/run.mako",
steps=workflow.steps,
--- a/templates/workflow/run.mako
+++ b/templates/workflow/run.mako
@@ -20,6 +20,14 @@
margin-top: 10px;
margin-bottom: 10px;
}
+ .step-annotation {
+ margin-top: 0.25em;
+ font-weight: normal;
+ font-size: 97%;
+ }
+ .workflow-annotation {
+ margin-bottom: 1em;
+ }
</style></%def>
@@ -129,6 +137,11 @@ from galaxy.jobs.actions.post import Act
</div>
%endif
+%if workflow.annotation:
+ <div class="workflow-annotation">Annotation: ${workflow.annotation}</div>
+ <hr/>
+%endif
+
<form id="tool_form" name="tool_form" method="POST">
## <input type="hidden" name="workflow_name" value="${h.to_unicode( workflow.name ) | h}" />
%for i, step in enumerate( steps ):
@@ -136,7 +149,12 @@ from galaxy.jobs.actions.post import Act
<% tool = app.toolbox.tools_by_id[step.tool_id] %><input type="hidden" name="${step.id}|tool_state" value="${step.state.encode( tool, app )}"><div class="toolForm">
- <div class="toolFormTitle">Step ${int(step.order_index)+1}: ${tool.name}</div>
+ <div class="toolFormTitle">
+ Step ${int(step.order_index)+1}: ${tool.name}
+ % if step.annotations:
+ <div class="step-annotation">Annotation: ${h.to_unicode( step.annotations[0].annotation )}</div>
+ % endif
+ </div><div class="toolFormBody">
${do_inputs( tool.inputs, step.state.inputs, errors.get( step.id, dict() ), "", step )}
% if step.post_job_actions:
@@ -150,27 +168,21 @@ from galaxy.jobs.actions.post import Act
${'<br/>'.join([ActionBox.get_short_str(pja) for pja in step.post_job_actions])}
</div>
% endif
- % if step.annotations:
- <hr/>
- <div class='form-row'>
- <label>Annotation:</label> ${h.to_unicode( step.annotations[0].annotation )}
- </div>
- % endif
</div></div>
%else:
<% module = step.module %><input type="hidden" name="${step.id}|tool_state" value="${module.encode_runtime_state( t, step.state )}"><div class="toolForm">
- <div class="toolFormTitle">Step ${int(step.order_index)+1}: ${module.name}</div>
+ <div class="toolFormTitle">
+ Step ${int(step.order_index)+1}: ${module.name}
+ % if step.annotations:
+ <div class="step-annotation">Annotation: ${step.annotations[0].annotation}</div>
+ % endif
+
+ </div><div class="toolFormBody">
${do_inputs( module.get_runtime_inputs(), step.state.inputs, errors.get( step.id, dict() ), "", step )}
- % if step.annotations:
- <hr/>
- <div class='form-row'>
- <label>Annotation:</label> ${step.annotations[0].annotation}
- </div>
- % endif
</div></div>
%endif
1
0