Merge ssh://github.com/web2py/web2py

This commit is contained in:
Michele Comitini
2013-07-17 02:59:33 +02:00
44 changed files with 1396 additions and 1637 deletions
+1 -1
View File
@@ -1 +1 @@
Version 2.6.0-development+timestamp.2013.07.05.02.12.46
Version 2.6.0-development+timestamp.2013.07.16.13.14.21
+6 -3
View File
@@ -623,7 +623,10 @@ def manage():
orderby = 'role' if not request.args(3) or '.group_id' not in request.args(3) else None
elif table == auth.table_permission():
orderby = 'group_id'
grid = SQLFORM.smartgrid(table, args=request.args[:2], user_signature=True,
orderby=orderby, linked_tables=linked_tables,
maxtextlength=1000, formname=formname)
kwargs = dict(user_signature=True, maxtextlength=1000,
orderby=orderby, linked_tables=linked_tables)
smartgrid_args = manager_action.get('smartgrid_args', {})
kwargs.update(**smartgrid_args.get('DEFAULT', {}))
kwargs.update(**smartgrid_args.get(table._tablename, {}))
grid = SQLFORM.smartgrid(table, args=request.args[:2], formname=formname, **kwargs)
return grid
+6 -7
View File
@@ -561,11 +561,11 @@ def edit():
# Load json only if it is ajax edited...
app = get_app(request.vars.app)
if not(request.ajax):
if not(request.ajax):
# return the scaffolding, the rest will be through ajax requests
response.title = T('Editing %s' % app)
editarea_preferences = {}
editarea_preferences['FONT_SIZE'] = '10'
editarea_preferences['FONT_SIZE'] = '10'
editarea_preferences['FULL_SCREEN'] = 'false'
editarea_preferences['ALLOW_TOGGLE'] = 'true'
editarea_preferences['REPLACE_TAB_BY_SPACES'] = '4'
@@ -574,7 +574,7 @@ def edit():
if key in globals():
editarea_preferences[key] = globals()[key]
return response.render ('default/edit.html', dict(app=request.args[0], editarea_preferences=editarea_preferences))
""" File edit handler """
# Load json only if it is ajax edited...
app = get_app(request.vars.app)
@@ -722,7 +722,7 @@ def edit():
vf = os.path.split(v)[-1]
vargs = "/".join([viewpath.replace(os.sep, "/"), vf])
editviewlinks.append(A(vf.split(".")[0],
_class="editor_filelink",
_class="editor_filelink",
_href=URL('edit', args=[vargs])))
if len(request.args) > 2 and request.args[1] == 'controllers':
@@ -746,11 +746,11 @@ def edit():
view_link=view_link,
editviewlinks=editviewlinks,
id=IS_SLUG()(filename)[0],
force= True if (request.vars.restore or request.vars.revert) else False)
force= True if (request.vars.restore or request.vars.revert) else False)
plain_html = response.render('default/edit_js.html', file_details)
file_details['plain_html'] = plain_html
return response.json(file_details)
def resolve():
"""
@@ -1770,4 +1770,3 @@ def git_push():
session.flash = T("Push failed, there are unmerged entries in the cache. Resolve merge issues manually and try again.")
redirect(URL('site'))
return dict(app=app, form=form)
+24 -8
View File
@@ -8,6 +8,7 @@
'%Y-%m-%d': '%d/%m/%Y',
'%Y-%m-%d %H:%M:%S': '%d/%m/%Y %H:%M:%S',
'(requires internet access)': '(requires internet access)',
'(requires internet access, experimental)': '(requires internet access, experimental)',
'(something like "it-it")': '(qualcosa simile a "it-it")',
'@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(file **gluon/contrib/plural_rules/%s.py** is not found)',
'@markmin\x01Searching: **%s** %%{file}': 'Searching: **%s** files',
@@ -43,6 +44,7 @@
'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': "ATTENZIONE: L'accesso richiede una connessione sicura (HTTPS) o l'esecuzione di web2py in locale (connessione su localhost)",
'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ATTENTZIONE: NON ESEGUIRE PIÙ TEST IN PARALLELO (I TEST NON SONO "THREAD SAFE")',
'ATTENTION: you cannot edit the running application!': "ATTENZIONE: non puoi modificare l'applicazione correntemente in uso ",
'Autocomplete Python Code': 'Autocomplete Python Code',
'Available databases and tables': 'Database e tabelle disponibili',
'back': 'indietro',
'cache': 'cache',
@@ -113,10 +115,12 @@
'Edit': 'modifica',
'Edit application': 'Modifica applicazione',
'edit controller': 'modifica controller',
'edit controller:': 'edit controller:',
'Edit current record': 'Modifica record corrente',
'edit profile': 'modifica profilo',
'Edit This App': 'Modifica questa applicazione',
'edit views:': 'modifica viste (view):',
'Editing bigul': 'Editing bigul',
'Editing file "%s"': 'Modifica del file "%s"',
'Editing Language file': 'Modifica file linguaggio',
'Enterprise Web Framework': 'Enterprise Web Framework',
@@ -140,6 +144,8 @@
'file saved on %(time)s': "file salvato nell'istante %(time)s",
'file saved on %s': 'file salvato: %s',
'filter': 'filter',
'Find Next': 'Find Next',
'Find Previous': 'Find Previous',
'Frames': 'Frames',
'Functions with no doctests will result in [passed] tests.': 'I test delle funzioni senza "doctests" risulteranno sempre [passed].',
'Get from URL:': 'Get from URL:',
@@ -177,15 +183,16 @@
'License for': 'Licenza relativa a',
'loading...': 'caricamento...',
'locals': 'locals',
'login': 'accesso',
'Login': 'Accesso',
'login': 'accesso',
'Login to the Administrative Interface': "Accesso all'interfaccia amministrativa",
'Logout': 'uscita',
'Main Menu': 'Menu principale',
'Manage': 'Manage',
'Menu Model': 'Menu Modelli',
'merge': 'unisci',
'models': 'modelli',
'Models': 'Modelli',
'models': 'modelli',
'Modules': 'Moduli',
'modules': 'moduli',
'new application "%s" created': 'creata la nuova applicazione "%s"',
@@ -198,6 +205,7 @@
'NO': 'NO',
'No databases in this application': 'Nessun database presente in questa applicazione',
'no match': 'nessuna corrispondenza',
'online designer': 'online designer',
'or alternatively': 'or alternatively',
'Or Get from URL:': 'Or Get from URL:',
'or import from csv file': 'oppure importa da file CSV',
@@ -206,6 +214,7 @@
'Overwrite installed app': 'sovrascrivi applicazione installata',
'Pack all': 'crea pacchetto',
'Pack compiled': 'crea pacchetto del codice compilato',
'Pack custom': 'Pack custom',
'pack plugin': 'crea pacchetto del plugin',
'PAM authenticated user, cannot change password here': 'utente autenticato tramite PAM, impossibile modificare password qui',
'password changed': 'password modificata',
@@ -217,15 +226,19 @@
'Plural-Forms:': 'Plural-Forms:',
'Powered by': 'Powered by',
'previous 100 rows': '100 righe precedenti',
'private files': 'private files',
'Private files': 'Private files',
'private files': 'private files',
'Query:': 'Richiesta (query):',
'Rapid Search': 'Rapid Search',
'record': 'record',
'record does not exist': 'il record non esiste',
'record id': 'ID del record',
'register': 'registrazione',
'reload': 'reload',
'Reload routes': 'Reload routes',
'Remove compiled': 'rimozione codice compilato',
'Replace': 'Replace',
'Replace All': 'Replace All',
'request': 'request',
'Resolve Conflict file': 'File di risoluzione conflitto',
'response': 'response',
@@ -237,6 +250,8 @@
"Run tests in this file (to run all files, you may also use the button labelled 'test')": "Run tests in this file (to run all files, you may also use the button labelled 'test')",
'Running on %s': 'Running on %s',
'Save': 'Save',
'Save file:': 'Save file:',
'Save file: %s': 'Save file: %s',
'Save via Ajax': 'Save via Ajax',
'Saved file hash:': 'Hash del file salvato:',
'selected': 'selezionato',
@@ -245,23 +260,24 @@
'shell': 'shell',
'Site': 'sito',
'some files could not be removed': 'non è stato possibile rimuovere alcuni files',
'Start searching': 'Start searching',
'Start wizard': 'start wizard',
'state': 'stato',
'static': 'statico',
'Static': 'Static',
'Static files': 'Files statici',
'Stylesheet': 'Foglio di stile (stylesheet)',
'submit': 'invia',
'Submit': 'Submit',
'submit': 'invia',
'Sure you want to delete this object?': 'Vuoi veramente cancellare questo oggetto?',
'table': 'tabella',
'test': 'test',
'Testing application': 'Test applicazione in corsg',
'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'La richiesta (query) è una condizione come ad esempio "db.tabella1.campo1==\'valore\'". Una condizione come "db.tabella1.campo1==db.tabella2.campo2" produce un "JOIN" SQL.',
'The application logic, each URL path is mapped in one exposed function in the controller': 'The application logic, each URL path is mapped in one exposed function in the controller',
'the application logic, each URL path is mapped in one exposed function in the controller': 'logica dell\'applicazione, ogni percorso "URL" corrisponde ad una funzione esposta da un controller',
'The data representation, define database tables and sets': 'The data representation, define database tables and sets',
'The application logic, each URL path is mapped in one exposed function in the controller': 'The application logic, each URL path is mapped in one exposed function in the controller',
'the data representation, define database tables and sets': 'rappresentazione dei dati, definizione di tabelle di database e di "set" ',
'The data representation, define database tables and sets': 'The data representation, define database tables and sets',
'The presentations layer, views are also known as templates': 'The presentations layer, views are also known as templates',
'the presentations layer, views are also known as templates': 'Presentazione dell\'applicazione, viste (views, chiamate anche "templates")',
'There are no controllers': 'Non ci sono controller',
@@ -273,8 +289,8 @@
'There are no translators, only default language is supported': 'Non ci sono traduzioni, viene solo supportato il linguaggio di base',
'There are no views': 'Non ci sono viste ("view")',
'These files are not served, they are only available from within your app': 'These files are not served, they are only available from within your app',
'these files are served without processing, your images go here': 'questi files vengono serviti così come sono, le immagini vanno qui',
'These files are served without processing, your images go here': 'These files are served without processing, your images go here',
'these files are served without processing, your images go here': 'questi files vengono serviti così come sono, le immagini vanno qui',
'This is the %(filename)s template': 'Questo è il template %(filename)s',
'Ticket': 'Ticket',
'Ticket ID': 'Ticket ID',
@@ -322,8 +338,8 @@
'Version %s.%s.%s (%s) %s': 'Version %s.%s.%s (%s) %s',
'versioning': 'sistema di versioni',
'Versioning': 'Versioning',
'view': 'vista',
'View': 'Vista',
'view': 'vista',
'Views': 'viste',
'views': 'viste',
'Web Framework': 'Web Framework',
+46
View File
@@ -281,6 +281,52 @@ td.cbcentered>input, th.cbcentered>input { margin-top:-1px; }
.languageform input.untranslated { background-color:#FC0; }
/*=============================================================
MASKED UPLOAD INPUT (NO BOOTSTRAP RELATED)
==============================================================*/
#appupdate_file.masked {
margin: 0;
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; /* IE 8 */
filter: alpha(opacity=0); /* IE 7 */
font-size: 100px;
position: absolute;
top: 0;
right: 0;
z-index: 410;
}
#fileselect {
padding: 4px 6px;
border: 1px solid #ccc;
border-radius: 4px;
color: #555;
cursor: default;
position: relative;
z-index: 400;
font-size: 14px;
background-color: #fff;
margin-bottom: 10px;
overflow: hidden;
}
#fileselect span {
position: absolute;
left: 6px;
top: 4px;
}
.uploadbtn {
position: absolute;
top: 3px;
right: 3px;
}
.txtPlaceholder {
font-style: italic;
color: #ccc;
}
/*=============================================================
MEDIA QUERIES
==============================================================*/
@@ -90,6 +90,7 @@ div.controls select +.error_wrapper {margin-left:5px;}
.ie-lte7 div.error{color:#fff;}
/* beautify brand */
.navbar {margin-bottom:0}
.navbar-inverse .brand{color:#c6cecc;}
.navbar-inverse .brand b{display:inline-block;margin-top:-1px;}
.navbar-inverse .brand b>span{font-size:22px;color:white}
@@ -222,6 +223,10 @@ td.w2p_fw ul{margin-left:0px;}
/* auth_user_remember checkbox extrapadding in IE fix */
.ie-lte9 input#auth_user_remember.checkbox {padding-left:0;}
div.controls .error {
width: auto;
}
/*=============================================================
MEDIA QUERIES
==============================================================*/
+242 -223
View File
@@ -1,262 +1,281 @@
function prepareDataForSave(name,data) {
var obj = new Object();
obj.Name = name;
obj.Data = data;
return obj;
function prepareDataForSave(name, data) {
var obj = new Object();
obj.Name = name;
obj.Data = data;
return obj;
}
function prepareMultiPartPOST(data) {
// var boundary = 'sPlItME' + Math.floor(Math.random()*10000);
var boundary = '' + Math.floor(Math.random()*10000);
var reqdata = '--' + boundary + '\r\n';
//console.log(data.length);
for (var i=0;i < data.length;i++) {
reqdata += 'content-disposition: form-data; name="';
reqdata += data[i].Name + '"';
reqdata += "\r\n\r\n" ;
reqdata += data[i].Data;
reqdata += "\r\n" ;
reqdata += '--' + boundary + '\r\n';
}
return new Array(reqdata,boundary);
// var boundary = 'sPlItME' + Math.floor(Math.random()*10000);
var boundary = '' + Math.floor(Math.random() * 10000);
var reqdata = '--' + boundary + '\r\n';
//console.log(data.length);
for(var i = 0; i < data.length; i++) {
reqdata += 'content-disposition: form-data; name="';
reqdata += data[i].Name + '"';
reqdata += "\r\n\r\n";
reqdata += data[i].Data;
reqdata += "\r\n";
reqdata += '--' + boundary + '\r\n';
}
return new Array(reqdata, boundary);
}
function on_error() {
jQuery("input[name='saved_on']").attr('style','background-color:red');
jQuery("input[name='saved_on']").val('communication error');
jQuery("input[name='saved_on']").attr('style', 'background-color:red');
jQuery("input[name='saved_on']").val('communication error');
}
function doHighlight(highlight) {
// Put the cursor at the offending line:
editor.setCursor({line:highlight.lineno-1,
ch:highlight.offset+1});
}
// Put the cursor at the offending line:
editor.setCursor({
line: highlight.lineno - 1,
ch: highlight.offset + 1
});
}
function doClickSave() {
var currentTabID = '#' + jQuery('#edit_placeholder div.tab-pane.active').attr('id');
var editor = jQuery (currentTabID + ' textarea').data('editor');
var data = editor.getValue();
var dataForPost = prepareMultiPartPOST(new Array(
prepareDataForSave('data', data),
prepareDataForSave('file_hash',
jQuery(currentTabID + " input[name='file_hash']").val()),
prepareDataForSave('saved_on',
jQuery(currentTabID + " input[name='saved_on']").val()),
prepareDataForSave('saved_on',
jQuery(currentTabID + " input[name='saved_on']").val()),
prepareDataForSave('from_ajax','true')));
// console.info(area.textarea.value);
jQuery(currentTabID + " input[name='saved_on']").attr('style',
'background-color:yellow');
jQuery(currentTabID + " input[name='saved_on']").val('saving now...')
currentUrl = jQuery(currentTabID + ' form').attr('action');
jQuery.ajax({
type: "POST",
contentType: 'multipart/form-data;boundary="'
+ dataForPost[1] + '"',
url: currentUrl,
dataType: "json",
data: dataForPost[0],
timeout: 5000,
beforeSend: function(xhr) {
xhr.setRequestHeader('web2py-component-location',
document.location);
xhr.setRequestHeader('web2py-component-element',
'doClickSave');
},
success: function(json,text,xhr){
jQuery(editor).data('saved', true); // Set as saved
editor.on("change", store_changes_function); // Re-enable change watcher
// reenable disabled submit button
var t=jQuery("input[name='save']");
t.attr('class','');
t.attr('disabled','');
try {
if (json.error) {
window.location.href=json.redirect;
} else {
// console.info( json.file_hash );
jQuery(currentTabID + " input[name='file_hash']").val(json.file_hash);
jQuery(currentTabID + " input[name='saved_on']").val(json.saved_on);
if (json.highlight) {
doHighlight(json.highlight);
} else {
jQuery(currentTabID + " input[name='saved_on']").attr('style','background-color:#99FF99');
//jQuery(".flash").delay(1000).fadeOut('slow');
}
// console.info(jQuery("input[name='file_hash']").val());
var output = '<b>exposes:</b> ';
for ( var i in json.functions) {
output += ' <a target="_blank" href="/' + json.application + '/' + json.controller + '/' + json.functions[i] + '">' + json.functions[i] + '</a>,';
}
if(output!='<b>exposes:</b> ') {
jQuery(currentTabID + " .exposed").html( output.substring(0, output.length-1));
}
}
} catch(e) { on_error();}
},
error: function(json) { on_error(); }
});
return false;
var currentTabID = '#' + jQuery('#edit_placeholder div.tab-pane.active').attr('id');
var editor = jQuery(currentTabID + ' textarea').data('editor');
var data = editor.getValue();
var dataForPost = prepareMultiPartPOST(new Array(
prepareDataForSave('data', data),
prepareDataForSave('file_hash',
jQuery(currentTabID + " input[name='file_hash']").val()),
prepareDataForSave('saved_on',
jQuery(currentTabID + " input[name='saved_on']").val()),
prepareDataForSave('saved_on',
jQuery(currentTabID + " input[name='saved_on']").val()),
prepareDataForSave('from_ajax', 'true')));
// console.info(area.textarea.value);
jQuery(currentTabID + " input[name='saved_on']").attr('style',
'background-color:yellow');
jQuery(currentTabID + " input[name='saved_on']").val('saving now...')
currentUrl = jQuery(currentTabID + ' form').attr('action');
jQuery.ajax({
type: "POST",
contentType: 'multipart/form-data;boundary="' + dataForPost[1] + '"',
url: currentUrl,
dataType: "json",
data: dataForPost[0],
timeout: 5000,
beforeSend: function (xhr) {
xhr.setRequestHeader('web2py-component-location',
document.location);
xhr.setRequestHeader('web2py-component-element',
'doClickSave');
},
success: function (json, text, xhr) {
jQuery(editor).data('saved', true); // Set as saved
editor.on("change", store_changes_function); // Re-enable change watcher
// reenable disabled submit button
var t = jQuery("input[name='save']");
t.attr('class', '');
t.attr('disabled', '');
try {
if(json.error) {
window.location.href = json.redirect;
} else {
// console.info( json.file_hash );
jQuery(currentTabID + " input[name='file_hash']").val(json.file_hash);
jQuery(currentTabID + " input[name='saved_on']").val(json.saved_on);
if(json.highlight) {
doHighlight(json.highlight);
} else {
jQuery(currentTabID + " input[name='saved_on']").attr('style', 'background-color:#99FF99');
//jQuery(".flash").delay(1000).fadeOut('slow');
}
// console.info(jQuery("input[name='file_hash']").val());
var output = '<b>exposes:</b> ';
for(var i in json.functions) {
output += ' <a target="_blank" href="/' + json.application + '/' + json.controller + '/' + json.functions[i] + '">' + json.functions[i] + '</a>,';
}
if(output != '<b>exposes:</b> ') {
jQuery(currentTabID + " .exposed").html(output.substring(0, output.length - 1));
}
}
} catch(e) {
on_error();
}
},
error: function (json) {
on_error();
}
});
return false;
}
function getActiveEditor() {
var currentTabID = '#' + jQuery('#edit_placeholder div.tab-pane.active').attr('id');
var editor = jQuery (currentTabID + ' textarea').data('editor');
return editor;
var currentTabID = '#' + jQuery('#edit_placeholder div.tab-pane.active').attr('id');
var editor = jQuery(currentTabID + ' textarea').data('editor');
return editor;
}
function getSelectionRange() {
var editor = getActiveEditor();
var sel = {};
sel['start'] = editor.getCursor(true).line;
sel['end'] = editor.getCursor(false).line;
sel['data'] = '';
return sel;
var editor = getActiveEditor();
var sel = {};
sel['start'] = editor.getCursor(true).line;
sel['end'] = editor.getCursor(false).line;
sel['data'] = '';
return sel;
}
function doToggleBreakpoint(filename, url, sel) {
var editor = getActiveEditor();
if (sel==null) {
// use cursor position to determine the breakpoint line
// (gutter already tell us the selected line)
sel = getSelectionRange();
var editor = getActiveEditor();
if(sel == null) {
// use cursor position to determine the breakpoint line
// (gutter already tell us the selected line)
sel = getSelectionRange();
}
var dataForPost = prepareMultiPartPOST(new Array(
prepareDataForSave('filename', filename),
prepareDataForSave('sel_start', sel["start"]),
prepareDataForSave('sel_end', sel["end"]),
prepareDataForSave('data', sel['data'])));
jQuery.ajax({
type: "POST",
contentType: 'multipart/form-data;boundary="' + dataForPost[1] + '"',
url: url,
dataType: "json",
data: dataForPost[0],
timeout: 5000,
beforeSend: function (xhr) {
xhr.setRequestHeader('web2py-component-location',
document.location);
xhr.setRequestHeader('web2py-component-element',
'doSetBreakpoint');
},
success: function (json, text, xhr) {
// show flash message (if any)
var flash = xhr.getResponseHeader('web2py-component-flash');
if(flash) {
jQuery('.flash').html(decodeURIComponent(flash))
.append('<a href="#" class="close">&times;</a>')
.slideDown();
} else jQuery('.flash').hide();
try {
if(json.error) {
window.location.href = json.redirect;
} else {
if(json.ok == true) {
// mark the breakpoint if ok=True
editor.setGutterMarker(json.lineno - 1, "breakpoints", makeMarker());
} else if(json.ok == false) {
// remove mark if ok=False
editor.setGutterMarker(json.lineno - 1, "breakpoints", null);
}
}
} catch(e) {
on_error();
}
},
error: function (json) {
on_error();
}
var dataForPost = prepareMultiPartPOST(new Array(
prepareDataForSave('filename', filename),
prepareDataForSave('sel_start', sel["start"]),
prepareDataForSave('sel_end', sel["end"]),
prepareDataForSave('data', sel['data'])));
jQuery.ajax({
type: "POST",
contentType: 'multipart/form-data;boundary="'+dataForPost[1]+'"',
url: url,
dataType: "json",
data: dataForPost[0],
timeout: 5000,
beforeSend: function(xhr) {
xhr.setRequestHeader('web2py-component-location',
document.location);
xhr.setRequestHeader('web2py-component-element',
'doSetBreakpoint');},
success: function(json,text,xhr){
// show flash message (if any)
var flash=xhr.getResponseHeader('web2py-component-flash');
if (flash) {
jQuery('.flash').html(decodeURIComponent(flash))
.append('<a href="#" class="close">&times;</a>')
.slideDown();
}
else jQuery('.flash').hide();
try {
if (json.error) {
window.location.href=json.redirect;
} else {
if (json.ok==true) {
// mark the breakpoint if ok=True
editor.setGutterMarker(json.lineno-1, "breakpoints", makeMarker());
} else if (json.ok==false) {
// remove mark if ok=False
editor.setGutterMarker(json.lineno-1, "breakpoints", null);
}
}
} catch(e) { on_error(); }
},
error: function(json) { on_error(); }
});
return false;
});
return false;
}
// on load, update all breakpoints markers:
function doListBreakpoints(filename, url, editor) {
var dataForPost = prepareMultiPartPOST(new Array(
prepareDataForSave('filename', filename)
));
jQuery.ajax({
type: "POST",
contentType: 'multipart/form-data;boundary="'+dataForPost[1]+'"',
url: url,
dataType: "json",
data: dataForPost[0],
timeout: 5000,
beforeSend: function(xhr) {
xhr.setRequestHeader('web2py-component-location',
document.location);
xhr.setRequestHeader('web2py-component-element',
'doListBreakpoints');},
success: function(json,text,xhr){
try {
if (json.error) {
window.location.href=json.redirect;
} else {
var editor = getActiveEditor();
for (i in json.breakpoints) {
lineno = json.breakpoints[i];
// mark the breakpoint if ok=True
editor.setGutterMarker(lineno-1, "breakpoints",makeMarker());
}
}
} catch(e) { on_error(); }
},
error: function(json) { on_error(); }
});
return false;
var dataForPost = prepareMultiPartPOST(new Array(
prepareDataForSave('filename', filename)
));
jQuery.ajax({
type: "POST",
contentType: 'multipart/form-data;boundary="' + dataForPost[1] + '"',
url: url,
dataType: "json",
data: dataForPost[0],
timeout: 5000,
beforeSend: function (xhr) {
xhr.setRequestHeader('web2py-component-location',
document.location);
xhr.setRequestHeader('web2py-component-element',
'doListBreakpoints');
},
success: function (json, text, xhr) {
try {
if(json.error) {
window.location.href = json.redirect;
} else {
var editor = getActiveEditor();
for(i in json.breakpoints) {
lineno = json.breakpoints[i];
// mark the breakpoint if ok=True
editor.setGutterMarker(lineno - 1, "breakpoints", makeMarker());
}
}
} catch(e) {
on_error();
}
},
error: function (json) {
on_error();
}
});
return false;
}
function makeMarker() {
var marker = document.createElement("div");
marker.style.color = "#822";
marker.innerHTML = "●";
marker.className = "breakpoint";
return marker;
}
function makeMarker() {
var marker = document.createElement("div");
marker.style.color = "#822";
marker.innerHTML = "●";
marker.className = "breakpoint";
return marker;
}
function keepalive(url) {
jQuery.ajax({
type: "GET",
url: url,
timeout: 1000,
success: function(){},
error: function(x) { on_error(); } });
jQuery.ajax({
type: "GET",
url: url,
timeout: 1000,
success: function () {},
error: function (x) {
on_error();
}
});
}
function load_file (url) {
jQuery.ajax({
type: "GET",
dataType: 'json',
url: url,
timeout: 1000,
success: function(json){
if (typeof(json['plain_html']) !== undefined) {
if (jQuery('#' + json['id']).length === 0 || json['force'] === true) {
// Create a tab and put the code in it
var tab_header = '<li><a href="#'+json['id']+'" data-toggle="tab">'+json['filename']+'<button type="button" class="close">&times;</button></a></li>';
var tab_body = '<div id="' + json['id'] + '" class="tab-pane fade in " >' + json['plain_html'] + '</div>';
if (json['force'] === false) {
jQuery('#filesTab').append(jQuery(tab_header));
jQuery('#myTabContent').append(jQuery(tab_body));
} else {
jQuery('#' + json['id']).html(jQuery(tab_body));
}
}
jQuery("a[href='#" + json['id'] + "']" ).click();
}
},
error: function(x) { on_error(); }
});
function load_file(url) {
jQuery.ajax({
type: "GET",
dataType: 'json',
url: url,
timeout: 1000,
success: function (json) {
if(typeof (json['plain_html']) !== undefined) {
if(jQuery('#' + json['id']).length === 0 || json['force'] === true) {
// Create a tab and put the code in it
var tab_header = '<li><a href="#' + json['id'] + '" data-toggle="tab">' + json['filename'] + '<button type="button" class="close">&times;</button></a></li>';
var tab_body = '<div id="' + json['id'] + '" class="tab-pane fade in " >' + json['plain_html'] + '</div>';
if(json['force'] === false) {
jQuery('#filesTab').append(jQuery(tab_header));
jQuery('#myTabContent').append(jQuery(tab_body));
} else {
jQuery('#' + json['id']).html(jQuery(tab_body));
}
}
jQuery("a[href='#" + json['id'] + "']").click();
}
},
error: function (x) {
on_error();
}
});
}
function set_font(editor, incr) {
var fontSize = '';
if (incr !== 0) {
fontSize = parseInt(jQuery(editor.getWrapperElement()).css('font-size'));
fontSize = fontSize + incr + "px";
}
jQuery(editor.getWrapperElement()).css('font-size', fontSize);
editor.refresh();
var fontSize = '';
if(incr !== 0) {
fontSize = parseInt(jQuery(editor.getWrapperElement()).css('font-size'));
fontSize = fontSize + incr + "px";
}
jQuery(editor.getWrapperElement()).css('font-size', fontSize);
editor.refresh();
}
var template_js = '<p class="repo-name">{{{a_tag}}}</p><small>{{address}}</small>';
File diff suppressed because one or more lines are too long
+70 -61
View File
@@ -7,6 +7,10 @@
* Released under the MIT license
*
*/
if($.web2py !== undefined) {
$.error('web2py.js has already been loaded!');
}
String.prototype.reverse = function () {
return this.split('').reverse().join('');
@@ -36,12 +40,13 @@
}
} else {
pcs = [];
if(s != null && s != undefined) for(i = 0; i < s.length; i++) {
if(s != null && s != undefined)
for(i = 0; i < s.length; i++) {
q = $("[name=" + s[i] + "]").serialize();
if(q) {
pcs.push(q);
}
}
}
if(pcs.length > 0) {
query = pcs.join("&");
}
@@ -147,9 +152,9 @@
web2py.component_handler(target);
},
//manage errors in forms
manage_errors: function(target) {
manage_errors: function (target) {
$('.error', target).hide().slideDown('slow');
//$('.error', target).hide().fadeIn('slow');
//jQuery('.error', target).hide().fadeIn('slow');
},
event_handlers: function () {
/* This is called once for page
@@ -172,7 +177,8 @@
});
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
doc.on('click', "input[type='checkbox'].delete", function () {
if(this.checked) if(!web2py.confirm(confirm_message)) this.checked = false;
if(this.checked)
if(!web2py.confirm(confirm_message)) this.checked = false;
});
doc.ajaxSuccess(function (e, xhr) {
@@ -424,7 +430,7 @@
el.addClass('disabled');
var method = el.prop('type') == 'submit' ? 'val' : 'html';
// store enabled state
el.data('w2p:enable-with', el[method]);
el.data('w2p:enable-with', el[method]());
/* little addition by default*/
if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) {
el.data('w2p_disable_with', 'Working...');
@@ -441,7 +447,7 @@
enableElement: function (el) {
var method = el.prop('type') == 'submit' ? 'val' : 'html';
if(el.data('w2p:enable-with') !== undefined) {
// set to old enabled state
// set to old enabled state
el[method](el.data('w2p:enable-with'));
el.removeData('w2p:enable-with'); // clean up cache
}
@@ -453,39 +459,39 @@
web2py.component(action, target, 0, 1, element);
},
//helper for flash messages
flash: function(message, status) {
flash: function (message, status) {
var flash = $('.flash');
web2py.hide_flash();
flash.html(message).addClass(status);
if(flash.html()) flash.append('<span id="closeflash"> &times; </span>').slideDown();
},
hide_flash: function() {
hide_flash: function () {
$('.flash').hide().html('');
},
show_if_handler: function(target) {
var triggers = {};
var show_if = function () {
var t = $(this);
var id = t.attr('id');
t.attr('value', t.val());
for(var k = 0; k < triggers[id].length; k++) {
var dep = $('#' + triggers[id][k], target);
var tr = $('#' + triggers[id][k] + '__row', target);
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
else tr.hide();
}
};
$('[data-show-trigger]', target).each(function () {
var name = $(this).attr('data-show-trigger');
if(!triggers[name]) triggers[name] = [];
triggers[name].push($(this).attr('id'));
});
for(var name in triggers) {
$('#' + name, target).change(show_if).keyup(show_if);
show_if.call($('#' + name, target));
};
show_if_handler: function (target) {
var triggers = {};
var show_if = function () {
var t = $(this);
var id = t.attr('id');
t.attr('value', t.val());
for(var k = 0; k < triggers[id].length; k++) {
var dep = $('#' + triggers[id][k], target);
var tr = $('#' + triggers[id][k] + '__row', target);
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
else tr.hide();
}
};
$('[data-show-trigger]', target).each(function () {
var name = $(this).attr('data-show-trigger');
if(!triggers[name]) triggers[name] = [];
triggers[name].push($(this).attr('id'));
});
for(var name in triggers) {
$('#' + name, target).change(show_if).keyup(show_if);
show_if.call($('#' + name, target));
};
},
component_handler : function (target) {
component_handler: function (target) {
$('div[data-w2p_remote]', target).each(function () {
var remote, times, timeout, target;
var el = $(this);
@@ -494,8 +500,7 @@
timeout = el.data('w2p_timeout');
target = el.attr('id');
web2py.component(remote, target, timeout, times, $(this));
}
)
})
},
a_handler: function (el, e) {
e.preventDefault();
@@ -517,14 +522,16 @@
}
if(target == undefined) {
if(method == 'GET') {
web2py.simple_component(action, el.attr('id'), el); //not working with original
web2py.ajax_page('get', action, [], 'bogus', el); //fixme?
//web2py.simple_component(action, el.attr('id'), el); //not working with original
} else if(method == 'POST') {
//should be web2py.ajax(action, [], ''); but it's too simple
web2py.ajax_page('post', action, [], 'bogus', el); //fixme?
}
} else {
if(method == 'GET') {
web2py.simple_component(action, target, el);
web2py.ajax_page('get', action, [], target, el);
//web2py.simple_component(action, target, el);
} else if(method == 'POST') {
//should be web2py.ajax(action, [], target); but it's too simple
web2py.ajax_page('post', action, [], target, el);
@@ -539,7 +546,7 @@
toremove = el.closest(toremove);
if(!toremove.length) {
//this enables removal of whatever selector if a closest is not found
toremove = $(toremove);
toremove = jQuery(toremove);
}
toremove.remove();
}
@@ -571,16 +578,17 @@
web2py.enableElement($(this));
});
},
/* Disables form elements:
/* Disables form elements:
- Caches element value in 'ujs:enable-with' data store
- Replaces element text with value of 'data-disable-with' attribute
- Sets disabled property to true
*/
disableFormElements: function(form) {
form.find(web2py.disableSelector).each(function() {
var element = $(this), method = element.is('button') ? 'html' : 'val';
disableFormElements: function (form) {
form.find(web2py.disableSelector).each(function () {
var element = $(this),
method = element.is('button') ? 'html' : 'val';
var disable_with = element.data('w2p_disable_with');
if (disable_with == undefined) {
if(disable_with == undefined) {
element.data('w2p_disable_with', element[method]())
}
element.data('w2p:enable-with', element[method]());
@@ -593,14 +601,15 @@
- Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
- Sets disabled property to false
*/
enableFormElements: function(form) {
form.find(web2py.enableSelector).each(function() {
var element = $(this), method = element.is('button') ? 'html' : 'val';
if (element.data('w2p:enable-with')) element[method](element.data('w2p:enable-with'));
enableFormElements: function (form) {
form.find(web2py.enableSelector).each(function () {
var element = $(this),
method = element.is('button') ? 'html' : 'val';
if(element.data('w2p:enable-with')) element[method](element.data('w2p:enable-with'));
element.prop('disabled', false);
});
},
form_handlers: function() {
form_handlers: function () {
var el = $(document);
el.on('ajax:beforeSend', 'form[data-w2p_target]', function (e) {
web2py.disableFormElements($(this));
@@ -626,28 +635,28 @@
})(jQuery);
/* compatibility code - start */
ajax = $.web2py.ajax;
web2py_component = $.web2py.component;
web2py_websocket = $.web2py.websocket;
web2py_ajax_page = $.web2py.ajax_page;
ajax = jQuery.web2py.ajax;
web2py_component = jQuery.web2py.component;
web2py_websocket = jQuery.web2py.websocket;
web2py_ajax_page = jQuery.web2py.ajax_page;
//needed for IS_STRONG(entropy)
web2py_validate_entropy = $.web2py.validate_entropy;
web2py_validate_entropy = jQuery.web2py.validate_entropy;
//needed for crud.search and SQLFORM.grid's search
web2py_ajax_fields = $.web2py.ajax_fields;
web2py_ajax_fields = jQuery.web2py.ajax_fields;
//used for LOAD(ajax=False)
web2py_trap_form = $.web2py.trap_form;
web2py_trap_form = jQuery.web2py.trap_form;
/*undocumented - rare*/
popup = $.web2py.popup;
collapse = $.web2py.collapse;
fade = $.web2py.fade;
popup = jQuery.web2py.popup;
collapse = jQuery.web2py.collapse;
fade = jQuery.web2py.fade;
/* internals - shouldn't be needed
web2py_ajax_init = $.web2py.ajax_init;
web2py_event_handlers = $.web2py.event_handlers;
web2py_ajax_init = jQuery.web2py.ajax_init;
web2py_event_handlers = jQuery.web2py.event_handlers;
web2py_trap_link = $.web2py.trap_link;
web2py_calc_entropy = $.web2py.calc_entropy;
web2py_trap_link = jQuery.web2py.trap_link;
web2py_calc_entropy = jQuery.web2py.calc_entropy;
*/
/* compatibility code - end*/
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -31,7 +31,7 @@
<link rel="apple-touch-icon" href="{{=URL('static','favicon.png')}}">
<!-- For the less-enabled mobile browsers like Opera Mini -->
<link rel="stylesheet" href="{{=URL('static','plugin_jqmobile/jquery.mobile-1.2.0.min.css')}}">
<link rel="stylesheet" href="{{=URL('static','plugin_jqmobile/jquery.mobile-1.3.1.min.css')}}">
<!-- All JavaScript at the bottom, except for Modernizr which enables HTML5 elements & feature detects -->
<script src="{{=URL('static','js/modernizr.custom.js')}}"></script!>
@@ -61,7 +61,7 @@ $(document).bind("mobileinit", function(){
});
</script>
<script src="{{=URL('static','plugin_jqmobile/jquery.mobile-1.2.0.min.js')}}"></script>
<script src="{{=URL('static','plugin_jqmobile/jquery.mobile-1.3.1.min.js')}}"></script>
<style>
.error { color: red; }
+145 -140
View File
@@ -10,9 +10,9 @@
return files
def editfile(path,file,vars={}):
args=(path,file) if 'app' in vars else (app,path,file)
url = URL('edit', args=args, vars=vars)
return A(file, _class='editor_filelink', _href=url, _style='word-wrap: break-word;')
args=(path,file) if 'app' in vars else (app,path,file)
url = URL('edit', args=args, vars=vars)
return A(file, _class='editor_filelink', _href=url, _style='word-wrap: nowrap;')
}}
{{cm=URL('static','codemirror')}}
<link rel="stylesheet" href="{{=cm}}/lib/codemirror.css">
@@ -38,123 +38,123 @@
<link rel="stylesheet" href="{{=cm}}/addon/dialog/dialog.css">
<script src="{{=cm}}/addon/selection/active-line.js"></script>
<script src="{{=cm}}/emmet.min.js"></script>
<script language="Javascript" type="text/javascript" src="{{=URL('static','js/ajax_editor.js')}}"></script>
<script src="{{=URL('static','js/ajax_editor.js')}}"></script>
<link rel="stylesheet" href="{{=URL('static/css','typeahead.js-bootstrap.css')}}">
<link rel="stylesheet" href="{{=URL('static/css','web2py-codemirror.css')}}">
<script language="Javascript" type="text/javascript">
<script type="text/javascript">
var current_theme = "web2py"; //Default theme
var current_font_incr = 0; // Default font-size, 0 means don't set
var current_font_incr = 0; // Default font-size, 0 means don't set
jQuery(document).on('shown click', 'a[data-toggle="tab"]', function (e) {
var tab_id = jQuery(this).attr('href');
var editor = jQuery(tab_id + " textarea").data('editor');
if (editor) {
editor.setSize(jQuery(tab_id).width(), jQuery(tab_id).height());
editor.refresh();
}
//jQuery(function(){jQuery('.CodeMirror-scroll').css("height","auto").css("overflow-x","auto");});
var tab_id = jQuery(this).attr('href');
var editor = jQuery(tab_id + " textarea").data('editor');
if (editor) {
editor.setSize(jQuery(tab_id).width(), jQuery(tab_id).height());
editor.refresh();
}
//jQuery(function(){jQuery('.CodeMirror-scroll').css("height","auto").css("overflow-x","auto");});
});
// Close the selected tab
jQuery(document).on('click', '#filesTab button[class="close"]', function (e) {
var tab_body = jQuery(jQuery(this).parent().attr("href")); // it should be a div
var tab_header = jQuery(this).parent().parent(); // it should be a li
var saved = jQuery(tab_body.find('textarea').data('editor')).data('saved');
var close = true;
if (saved === false) {
close = confirm("You are closing an unsaved file")
}
if (close) {
if (tab_header.hasClass('active') === true) { //Set active an other tab
jQuery(tab_header).prev().children('a[data-toggle="tab"]').tab('show'); // Select first tab
}
tab_header.remove(); //remove li of tab
tab_body.remove(); //remove li of tab
}
var tab_body = jQuery(jQuery(this).parent().attr("href")); // it should be a div
var tab_header = jQuery(this).parent().parent(); // it should be a li
var saved = jQuery(tab_body.find('textarea').data('editor')).data('saved');
var close = true;
if (saved === false) {
close = confirm("You are closing an unsaved file")
}
if (close) {
if (tab_header.hasClass('active') === true) { //Set active an other tab
jQuery(tab_header).prev().children('a[data-toggle="tab"]').tab('show'); // Select first tab
}
tab_header.remove(); //remove li of tab
tab_body.remove(); //remove li of tab
}
});
// Revert current file
jQuery(document).on('click', '#revert', function (e) {
e.preventDefault();
load_file(jQuery(this).attr("href"));
e.preventDefault();
load_file(jQuery(this).attr("href"));
});
// Restore current file
jQuery(document).on('click', '#restore', function (e) {
e.preventDefault();
load_file(jQuery(this).attr("href"));
e.preventDefault();
load_file(jQuery(this).attr("href"));
});
// open the selected file
jQuery(document).on('click', 'a.editor_filelink', function (e) {
e.preventDefault();
var url = jQuery(this).attr("href");
load_file(url);
e.preventDefault();
var url = jQuery(this).attr("href");
load_file(url);
});
// change the codemirror theme
jQuery(document).on('click', '#themes a', function (e) {
e.preventDefault();
var href = jQuery(this).attr('href');
var name = jQuery(this).text().replace('.css', '');
var link = jQuery("<link>");
link.attr({
type: 'text/css',
rel: 'stylesheet',
href: href
});
jQuery("head").append( link );
jQuery('textarea[name="data"]') .each(function(id, ta) {
editor = jQuery(ta).data('editor');
editor.setOption("theme", name);
});
jQuery('#themeName').html(name);
current_theme = name;
e.preventDefault();
var href = jQuery(this).attr('href');
var name = jQuery(this).text().replace('.css', '');
var link = jQuery("<link>");
link.attr({
type: 'text/css',
rel: 'stylesheet',
href: href
});
jQuery("head").append( link );
jQuery('textarea[name="data"]') .each(function(id, ta) {
editor = jQuery(ta).data('editor');
editor.setOption("theme", name);
});
jQuery('#themeName').html(name);
current_theme = name;
//#TODO save on session
});
// incr/decr editor font-size
jQuery(document).on('click', 'a.font_button', function (e) {
e.preventDefault();
var id = jQuery(this).attr('id');
var new_font_incr;
switch (id) {
case 'incr': new_incr = 2; break;
case 'decr': new_incr = -2; break;
case 'default': new_incr = 0; break;
}
jQuery('textarea[name="data"]') .each(function(id, ta) {
editor = jQuery(ta).data('editor');
set_font(editor, new_incr);
});
current_font_incr = (new_incr !== 0) ? current_font_incr + new_incr : 0;
e.preventDefault();
var id = jQuery(this).attr('id');
var new_font_incr;
switch (id) {
case 'incr': new_incr = 2; break;
case 'decr': new_incr = -2; break;
case 'default': new_incr = 0; break;
}
jQuery('textarea[name="data"]') .each(function(id, ta) {
editor = jQuery(ta).data('editor');
set_font(editor, new_incr);
});
current_font_incr = (new_incr !== 0) ? current_font_incr + new_incr : 0;
});
function isFullScreen(instance) {
return /\bCodeMirror-fullscreen\b/.test(instance.getWrapperElement().className);
}
function winHeight() {
return window.innerHeight || (document.documentElement || document.body).clientHeight;
}
function setFullScreen(instance, full) {
var wrap = instance.getWrapperElement()
if (full) {
wrap.className += " CodeMirror-fullscreen";
wrap.style.height = winHeight() + "px";
document.documentElement.style.overflow = "hidden";
} else {
wrap.className = wrap.className.replace(" CodeMirror-fullscreen", "");
wrap.style.height = "";
document.documentElement.style.overflow = "";
}
instance.refresh();
}
CodeMirror.on(window, "resize", function() {
var showing = document.body.getElementsByClassName("CodeMirror-fullscreen")[0];
if (!showing) return;
showing.CodeMirror.getWrappererElement().style.height = winHeight() + "px";
});
function isFullScreen(instance) {
return /\bCodeMirror-fullscreen\b/.test(instance.getWrapperElement().className);
}
function winHeight() {
return window.innerHeight || (document.documentElement || document.body).clientHeight;
}
function setFullScreen(instance, full) {
var wrap = instance.getWrapperElement()
if (full) {
wrap.className += " CodeMirror-fullscreen";
wrap.style.height = winHeight() + "px";
document.documentElement.style.overflow = "hidden";
} else {
wrap.className = wrap.className.replace(" CodeMirror-fullscreen", "");
wrap.style.height = "";
document.documentElement.style.overflow = "";
}
instance.refresh();
}
CodeMirror.on(window, "resize", function() {
var showing = document.body.getElementsByClassName("CodeMirror-fullscreen")[0];
if (!showing) return;
showing.CodeMirror.getWrappererElement().style.height = winHeight() + "px";
});
{{if len(request.args) > 1:}}
load_file('{{=URL(f='edit', args=request.args, vars=request.get_vars)}}');
{{pass}}
{{if len(request.args) > 1:}}
load_file('{{=URL(f='edit', args=request.args, vars=request.get_vars)}}');
{{pass}}
</script>
@@ -163,18 +163,21 @@ jQuery(document).on('click', 'a.font_button', function (e) {
<div class='row-fluid'>
<div class="right controls btn-toolbar pull-right">
<div class="btn-group">
<a class="button btn" onclick="jQuery('#files').toggle(); return false" href="#">Files toggle</a>
</div>
<div class="dropdown btn-group pull-left">
<a class="dropdown-toggle button btn" data-target="themes" data-toggle="dropdown" href="#" >Theme: <span id="themeName" style="color: #E8953C">Web2py</span> <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu" id="themes">
{{for f in listfiles('admin', "static/codemirror/theme", regexp='.*\.css$' ):}}
<li class=""><a href="{{=URL('static/codemirror/theme', f, host=True)}}">{{=f[:-4]}}</a></li>
{{pass}}
</ul>
<a class="dropdown-toggle button btn" data-target="themes" data-toggle="dropdown" href="#" >Theme: <span id="themeName" style="color: #E8953C">Web2py</span> <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu" id="themes">
{{for f in listfiles('admin', "static/codemirror/theme", regexp='.*\.css$' ):}}
<li class=""><a href="{{=URL('static/codemirror/theme', f, host=True)}}">{{=f[:-4]}}</a></li>
{{pass}}
</ul>
</div>
<div class="btn-group">
<a id="decr" class="button btn font_button">-</a>
<a id="default" class="button btn font_button" >A</a>
<a id="incr" class="button btn font_button">+</a>
<a id="decr" class="button btn font_button">-</a>
<a id="default" class="button btn font_button" >A</a>
<a id="incr" class="button btn font_button">+</a>
</div>
<div class="btn-group">
{{=button(URL('design',args=request.vars.app if request.vars.app else request.args[0], anchor=request.vars.id), T('back'))}}
@@ -186,51 +189,53 @@ jQuery(document).on('click', 'a.font_button', function (e) {
</div>
</div>
<div id="editor_area" class="row-fluid">
<ul class="nav nav-list span2 well" rel="pagebookmark" id="filelist">
<li><input type="text" placeholder="{{=T('Rapid Search')}}" class="input-block-level typeahead-tw search-query"></li>
{{dirs=[{'name':'models', 'reg':'.*\.py$'},
{'name':'controllers', 'reg':'.*\.py$'},
{'name':'views', 'reg':'[\w/\-]+(\.\w+)+$'},
{'name':'modules', 'reg':'.*\.py$'},
{'name':'private', 'reg': '[^\.#].*'}]}}
{{auto_complete_list=[]}}
{{for dir in dirs:}}
<li class="nav-header component" onclick="collapse('{{="%s_files" % dir['name']}}');">{{=dir['name']}}</li>
<li id="{{="%s_files" % dir['name']}}">
<ul class="nav nav-list small-font">
{{for f in listfiles(app, dir['name'], regexp=dir['reg'] ):}}
{{id="%s__" % dir['name'] + f.replace('.','__')}}
{{current_file = request.args(len(request.args) - 1)}}
<li class="{{#='active' if current_file==f else ''}}">
{{a_tag=editfile(dir['name'], f, dict(id=id))}}
{{=a_tag}}
{{auto_complete_list.append({'value':f, 'tokens':f.split('/'), 'a_tag':a_tag})}}
</li>
{{pass}}
</ul>
</li>
{{pass}}
</ul>
<div class="span10" id="edit_placeholder">
<ul class="nav nav-tabs " id="filesTab">
</ul>
<div id="myTabContent" class="tab-content">
</div>
</div>
<div id="files">
<ul class="nav nav-list span2 well" rel="pagebookmark" id="filelist">
<li><input type="text" placeholder="{{=T('Rapid Search')}}" class="input-block-level typeahead-tw search-query"></li>
{{dirs=[{'name':'models', 'reg':'.*\.py$'},
{'name':'controllers', 'reg':'.*\.py$'},
{'name':'views', 'reg':'[\w/\-]+(\.\w+)+$'},
{'name':'modules', 'reg':'.*\.py$'},
{'name':'private', 'reg': '[^\.#].*'}]}}
{{auto_complete_list=[]}}
{{for dir in dirs:}}
<li class="nav-header component" onclick="collapse('{{="%s_files" % dir['name']}}');">{{=dir['name']}}</li>
<li id="{{="%s_files" % dir['name']}}">
<ul class="nav nav-list small-font">
{{for f in listfiles(app, dir['name'], regexp=dir['reg'] ):}}
{{id="%s__" % dir['name'] + f.replace('.','__')}}
{{current_file = request.args(len(request.args) - 1)}}
<li class="{{#='active' if current_file==f else ''}}" style="overflow:hidden">
{{a_tag=editfile(dir['name'], f, dict(id=id))}}
{{=a_tag}}
{{auto_complete_list.append({'value':f, 'tokens':f.split('/'), 'a_tag':a_tag})}}
</li>
{{pass}}
</ul>
</li>
{{pass}}
</ul>
</div>
<div class="span10" id="edit_placeholder">
<ul class="nav nav-tabs " id="filesTab">
</ul>
<div id="myTabContent" class="tab-content">
</div>
</div>
</div>
<!-- Typeahead scripts here so the page load faster -->
<script src="{{=URL('static/js', 'typeahead.min.js')}}"></script>
<script src="{{=URL('static/js', 'hogan-2.0.0.js')}}"></script>
<script>
jQuery('.typeahead-tw').typeahead({
name: 'files',
local:{{from gluon.serializers import json}}{{=XML(json(auto_complete_list))}},
template: template_js,
engine: Hogan,
});
jQuery(document).on("typeahead:selected", '.typeahead', function(e, datum) {
load_file(datum.link);
jQuery(this).val('');
});
jQuery('.typeahead-tw').typeahead({
name: 'files',
local:{{from gluon.serializers import json}}{{=XML(json(auto_complete_list))}},
template: template_js,
engine: Hogan,
});
jQuery(document).on("typeahead:selected", '.typeahead', function(e, datum) {
load_file(datum.link);
jQuery(this).val('');
});
</script>
<!-- end "edit" block -->
+137 -137
View File
@@ -4,168 +4,168 @@
<form action="{{=URL('edit', args=filename)}}" method="post" name="editform" id="editform" class="form-inline row-fluid">
<div class="span12 well well-small">
<label class="">{{=T('Save file:')}}</label>
<a value="save" title="{{=T('Save file: %s', filename)}}" href="#" name="save" onclick="return doClickSave();" class="icon saveicon" style="background-image: -webkit-linear-gradient(top,white,#E6E6E6);">{{=IMG(_src=URL('static', 'images/save_icon.png'), _alt=T('Save'))}}</a>
<label class="">{{=T('Saved file hash:')}}</label>
<input type="input" name="file_hash" value="{{=file_hash}}" class="input-long uneditable-input" readonly="readonly"/>
<label>{{=T('Last saved on:')}}</label>
<input type="input" name="saved_on" value="{{=saved_on}}" class="input-normal uneditable-input" readonly="readonly"/>
<label class="">{{=T('Save file:')}}</label>
<a value="save" title="{{=T('Save file: %s', filename)}}" href="#" name="save" onclick="return doClickSave();" class="icon saveicon" style="background-image: -webkit-linear-gradient(top,white,#E6E6E6);">{{=IMG(_src=URL('static', 'images/save_icon.png'), _alt=T('Save'))}}</a>
<label class="">{{=T('Saved file hash:')}}</label>
<input type="input" name="file_hash" value="{{=file_hash}}" class="input-long uneditable-input" readonly="readonly"/>
<label>{{=T('Last saved on:')}}</label>
<input type="input" name="saved_on" value="{{=saved_on}}" class="input-normal uneditable-input" readonly="readonly"/>
{{if filetype=='python':}}
{{=A(SPAN(T('toggle breakpoint')),
_value="breakpoint", _name="breakpoint",
_onclick="return doToggleBreakpoint('%s','%s://%s%s',null);" % (filename,
_onclick="return doToggleBreakpoint('%s','%s://%s%s',null);" % (filename,
request.env['wsgi_url_scheme'], request.env['http_host'],
URL(c='debug', f='toggle_breakpoint')),
_class="button special btn btn-inverse")}}
{{pass}}
{{pass}}
{{if view_link:}}
{{=button(view_link, T('try view'))}}
{{=button(view_link, T('try view'))}}
{{pass}}
<p class="formfield">
{{if functions:}}
<span style="text-align:left;" class="exposed">
{{=B(T('exposes:'))}} {{=XML(', '.join([A(f,_target="_blank", _href=URL(a=app,c=controller,f=f)).xml() for f in functions]))}}
</span>
<span style="text-align:left;" class="exposed">
{{=B(T('exposes:'))}} {{=XML(', '.join([A(f,_target="_blank", _href=URL(a=app,c=controller,f=f)).xml() for f in functions]))}}
</span>
{{if editviewlinks:}}<br/>
{{=B(T('edit views:'))}}
{{=XML(', '.join([v.xml() for v in editviewlinks]))}}
{{=B(T('edit views:'))}}
{{=XML(', '.join([v.xml() for v in editviewlinks]))}}
{{pass}}
{{pass}}
{{if edit_controller:}}
{{=B(T('edit controller:'))}}
{{=A(request.args[2]+'.py', _class="editor_filelink", _target="_blank", _href=edit_controller)}}
{{=B(T('edit controller:'))}}
{{=A(request.args[2]+'.py', _class="editor_filelink", _target="_blank", _href=edit_controller)}}
{{pass}}
</p>
</div>
<textarea style=" height:100%; direction:ltr;" id="textarea_{{=id}}" class="input-block-level" name="data" >{{=data}}</textarea>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("textarea_{{=id}}"),{
{{if filetype=='html':}}
mode : "text/html",
profile: 'xhtml',
{{else:}}
mode: { name: '{{=filetype}}'{{if filetype=='python':}},version: 2,singleLineStringErrors: false, {{pass}} },
{{pass}}
lineNumbers: true,
indentUnit: 4,
styleActiveLine: true,
autoCloseTags: true,
theme: current_theme,
tabMode: "shift",
lineWrapping: true,
gutters: ["CodeMirror-linenumbers", "breakpoints"],
{{if TEXT_EDITOR_KEYBINDING == 'emacs':}}keyMap: "emacs",{{pass}}
{{if TEXT_EDITOR_KEYBINDING == 'vi':}}keyMap: "vim",{{pass}}
matchBrackets: true,
autofocus: false,
height: "350px",
showTrailingSpace: true
});
editor.on("gutterClick", function(cm, n) {
var info = cm.lineInfo(n);
cm.setGutterMarker(n, "breakpoints", info.gutterMarkers ? null : makeMarker());
sel = {start: n, end: n, data: ''};
doToggleBreakpoint({{=XML("'%s','%s://%s%s'" % (filename,
request.env['wsgi_url_scheme'], request.env['http_host'],
URL(c='debug', f='toggle_breakpoint')))}}, sel);
});
function makeMarker() {
var marker = document.createElement("div");
marker.style.color = "#822";
marker.innerHTML = "●";
marker.className = "breakpoint";
return marker;
}
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("textarea_{{=id}}"),{
{{if filetype=='html':}}
mode : "text/html",
profile: 'xhtml',
{{else:}}
mode: { name: '{{=filetype}}'{{if filetype=='python':}},version: 2,singleLineStringErrors: false, {{pass}} },
{{pass}}
lineNumbers: true,
indentUnit: 4,
styleActiveLine: true,
autoCloseTags: true,
theme: current_theme,
tabMode: "shift",
lineWrapping: true,
gutters: ["CodeMirror-linenumbers", "breakpoints"],
{{if TEXT_EDITOR_KEYBINDING == 'emacs':}}keyMap: "emacs",{{pass}}
{{if TEXT_EDITOR_KEYBINDING == 'vi':}}keyMap: "vim",{{pass}}
matchBrackets: true,
autofocus: false,
height: "350px",
showTrailingSpace: true
});
{{if filetype=='html':}}
// must be here or break emmet/zencoding for html
CodeMirror.defaults.extraKeys["Ctrl-S"] =
function(instance) {
doClickSave();};
CodeMirror.defaults.extraKeys["Ctrl-F11"]=
function(instance) {
setFullScreen(instance, !isFullScreen(instance));};
CodeMirror.defaults.extraKeys["Tab"] = "indentMore";
CodeMirror.defaults.extraKeys["Esc"]=
function(instance) {
if (isFullScreen(instance)) {
setFullScreen(instance, false);};}
{{pass}}
{{if filetype=='python':}}
// must be here or break emmet/zencoding for python
CodeMirror.defaults.extraKeys["Ctrl-S"] =
function(instance) {
doClickSave();};
CodeMirror.defaults.extraKeys["Ctrl-Space"] =
"autocomplete";
CodeMirror.defaults.extraKeys["Ctrl-F11"]=
function(instance) {
setFullScreen(instance, !isFullScreen(instance));};
CodeMirror.defaults.extraKeys["Tab"] = "indentMore";
CodeMirror.defaults.extraKeys["Esc"]=
function(instance) {
if (isFullScreen(instance)) {
setFullScreen(instance, false);};}
//for autocomplete
CodeMirror.commands.autocomplete = function(cm) {
editor.on("gutterClick", function(cm, n) {
var info = cm.lineInfo(n);
cm.setGutterMarker(n, "breakpoints", info.gutterMarkers ? null : makeMarker());
sel = {start: n, end: n, data: ''};
doToggleBreakpoint({{=XML("'%s','%s://%s%s'" % (filename,
request.env['wsgi_url_scheme'], request.env['http_host'],
URL(c='debug', f='toggle_breakpoint')))}}, sel);
});
function makeMarker() {
var marker = document.createElement("div");
marker.style.color = "#822";
marker.innerHTML = "●";
marker.className = "breakpoint";
return marker;
}
{{if filetype=='html':}}
// must be here or break emmet/zencoding for html
CodeMirror.defaults.extraKeys["Ctrl-S"] =
function(instance) {
doClickSave();};
CodeMirror.defaults.extraKeys["Ctrl-F11"]=
function(instance) {
setFullScreen(instance, !isFullScreen(instance));};
CodeMirror.defaults.extraKeys["Tab"] = "indentMore";
CodeMirror.defaults.extraKeys["Esc"]=
function(instance) {
if (isFullScreen(instance)) {
setFullScreen(instance, false);};}
{{pass}}
{{if filetype=='python':}}
// must be here or break emmet/zencoding for python
CodeMirror.defaults.extraKeys["Ctrl-S"] =
function(instance) {
doClickSave();};
CodeMirror.defaults.extraKeys["Ctrl-Space"] =
"autocomplete";
CodeMirror.defaults.extraKeys["Ctrl-F11"]=
function(instance) {
setFullScreen(instance, !isFullScreen(instance));};
CodeMirror.defaults.extraKeys["Tab"] = "indentMore";
CodeMirror.defaults.extraKeys["Esc"]=
function(instance) {
if (isFullScreen(instance)) {
setFullScreen(instance, false);};}
//for autocomplete
CodeMirror.commands.autocomplete = function(cm) {
CodeMirror.showHint(cm, CodeMirror.pythonHint);
}
{{pass}}
store_changes_function = function(instance, changeObj) {
jQuery(instance).data('saved', false);
instance.off("change", store_changes_function);
}
editor.on("change", store_changes_function);
// save the editor as textarea data attribute
jQuery("#{{=id}} textarea").data('editor', editor);
var hlLine = editor.addLineClass(0, "background", "activeline");
window.mirror = editor; //backward compatibility
set_font(editor, current_font_incr);
doListBreakpoints({{=XML("'%s','%s://%s%s'" % (filename,
request.env['wsgi_url_scheme'], request.env['http_host'],
URL(c='debug', f='list_breakpoints')))}}, editor);
{{pass}}
store_changes_function = function(instance, changeObj) {
jQuery(instance).data('saved', false);
instance.off("change", store_changes_function);
}
editor.on("change", store_changes_function);
// save the editor as textarea data attribute
jQuery("#{{=id}} textarea").data('editor', editor);
var hlLine = editor.addLineClass(0, "background", "activeline");
window.mirror = editor; //backward compatibility
set_font(editor, current_font_incr);
doListBreakpoints({{=XML("'%s','%s://%s%s'" % (filename,
request.env['wsgi_url_scheme'], request.env['http_host'],
URL(c='debug', f='list_breakpoints')))}}, editor);
</script>
<div class="editor-bar-bottom" style="margin-top:9px;">
<a class="editbutton btn" href="{{=URL('edit', args=request.args, vars={'restore':True})}}" id="restore">{{=T('restore')}}</a>
{{=T('currently saved or')}}
<a class="editbutton btn" href="{{=URL('edit', args=request.args, vars={'revert':True})}}" id="revert">{{=T('revert')}}</a>
{{=T('to previous version.')}}
</div>
</script>
<div class="editor-bar-bottom" style="margin-top:9px;">
<a class="editbutton btn" href="{{=URL('edit', args=request.args, vars={'restore':True})}}" id="restore">{{=T('restore')}}</a>
{{=T('currently saved or')}}
<a class="editbutton btn" href="{{=URL('edit', args=request.args, vars={'revert':True})}}" id="revert">{{=T('revert')}}</a>
{{=T('to previous version.')}}
</div>
<br/>
</form>
<div class="row-fluid">
<div class="help alert alert-block alert-info">
{{if TEXT_EDITOR == 'codemirror' and filetype=='html':}}
<h3>{{=T('Key bindings for ZenCoding Plugin')}}</h3>
<ul class="keybindings unstyled">
{{=shortcut('Ctrl+S', T('Save via Ajax'))}}
{{=shortcut('Ctrl+F11', T('Toggle Fullscreen'))}}
{{=shortcut('Ctrl-F / Cmd-F', T('Start searching'))}}
{{=shortcut('Ctrl-G / Cmd-G', T('Find Next'))}}
{{=shortcut('Shift-Ctrl-G / Shift-Cmd-G', T('Find Previous'))}}
{{=shortcut('Shift-Ctrl-F / Cmd-Option-F', T('Replace'))}}
{{=shortcut('Shift-Ctrl-R / Shift-Cmd-Option-F', T('Replace All'))}}
{{=shortcut('Tab', T('Expand Abbreviation'))}}
</ul>
{{elif TEXT_EDITOR == 'codemirror':}}
<h3>{{=T("Key bindings")}}</h3>
<ul class="keybindings unstyled">
{{=shortcut('Ctrl+S', T('Save via Ajax'))}}
{{=shortcut('Ctrl+F11', T('Toggle Fullscreen'))}}
{{if filetype=='python':}}
{{=shortcut('Ctrl-Space', T('Autocomplete Python Code'))}}
{{pass}}
{{=shortcut('Ctrl-F / Cmd-F', T('Start searching'))}}
{{=shortcut('Ctrl-G / Cmd-G', T('Find Next'))}}
{{=shortcut('Shift-Ctrl-G / Shift-Cmd-G', T('Find Previous'))}}
{{=shortcut('Shift-Ctrl-F / Cmd-Option-F', T('Replace'))}}
{{=shortcut('Shift-Ctrl-R / Shift-Cmd-Option-F', T('Replace All'))}}
</ul>
{{pass}}
</div>
<div class="help alert alert-block alert-info">
{{if TEXT_EDITOR == 'codemirror' and filetype=='html':}}
<h3>{{=T('Key bindings for ZenCoding Plugin')}}</h3>
<ul class="keybindings unstyled">
{{=shortcut('Ctrl+S', T('Save via Ajax'))}}
{{=shortcut('Ctrl+F11', T('Toggle Fullscreen'))}}
{{=shortcut('Ctrl-F / Cmd-F', T('Start searching'))}}
{{=shortcut('Ctrl-G / Cmd-G', T('Find Next'))}}
{{=shortcut('Shift-Ctrl-G / Shift-Cmd-G', T('Find Previous'))}}
{{=shortcut('Shift-Ctrl-F / Cmd-Option-F', T('Replace'))}}
{{=shortcut('Shift-Ctrl-R / Shift-Cmd-Option-F', T('Replace All'))}}
{{=shortcut('Tab', T('Expand Abbreviation'))}}
</ul>
{{elif TEXT_EDITOR == 'codemirror':}}
<h3>{{=T("Key bindings")}}</h3>
<ul class="keybindings unstyled">
{{=shortcut('Ctrl+S', T('Save via Ajax'))}}
{{=shortcut('Ctrl+F11', T('Toggle Fullscreen'))}}
{{if filetype=='python':}}
{{=shortcut('Ctrl-Space', T('Autocomplete Python Code'))}}
{{pass}}
{{=shortcut('Ctrl-F / Cmd-F', T('Start searching'))}}
{{=shortcut('Ctrl-G / Cmd-G', T('Find Next'))}}
{{=shortcut('Shift-Ctrl-G / Shift-Cmd-G', T('Find Previous'))}}
{{=shortcut('Shift-Ctrl-F / Cmd-Option-F', T('Replace'))}}
{{=shortcut('Shift-Ctrl-R / Shift-Cmd-Option-F', T('Replace All'))}}
</ul>
{{pass}}
</div>
</div>
@@ -7,7 +7,7 @@ function delkey(id) {
return false;
}
function hideShowTranslated(){
jQuery(".translated").closest("div.row-fluid").toggle();
jQuery(".translated").closest("div.row-fluid").toggle();
}
</script>
+112 -112
View File
@@ -3,122 +3,122 @@
{{block sectionclass}}errors{{end}}
<!-- begin "errors" block -->
{{if db_ready['status'] == False:
switchbutton = A(SPAN("switch to : db"), _href=db_ready['errlink'], _class="button unavailable btn btn-danger", _title="%s" % (db_ready['errmessage']))
switchbutton = A(SPAN("switch to : db"), _href=db_ready['errlink'], _class="button unavailable btn btn-danger", _title="%s" % (db_ready['errmessage']))
else:
switchbutton = A(SPAN("switch to : db"), _href=URL(args=[app, 'dbnew']), _class="button btn")
switchbutton = A(SPAN("switch to : db"), _href=URL(args=[app, 'dbnew']), _class="button btn")
pass}}
<h2>{{=T('Error logs for "%(app)s"',dict(app=app))}}</h2>
<div class="errorform">
<form name="myform" method="post">
{{ if 'new' in method: }}
{{base_url = 'db' in method and 'ticketdb' or 'ticket' }}
<p class="controls row-fluid">
<div class="controls controls-row">
{{if 'db' in method:}}
<span class="uneditable-input">source : db</span>
<a class="button btn" href="{{=URL(args=[app, 'new'])}}"><span>switch to : filesystem</span></a>
<a class="button btn" href="{{=URL(args=[app, 'dbold'])}}"><span>lists by ticket</span></a>
{{else:}}
<span class="uneditable-input">source : filesystem</span>
{{=switchbutton}}
<a class="button btn" href="{{=URL(args=[app, 'old'])}}"><span>lists by ticket</span></a>
{{pass}}
</div>
</p>
<div class="tablebar">
<input value="{{=T('delete all checked')}}" type="submit" class="btn"/>
<span class="help label label-info">{{=T('Click row to expand traceback')}}</span>
</div>
<div class="row-fluid">
<div class="span6">
<table id="trck_errors" class="sortable table table-hover table-condensed">
<thead>
<tr>
<th class="column1 cbcentered"><input type="checkbox" name="delete_all}" /></th>
<th class="column2">{{=T("Count")}}</th>
<th class="column3">{{=T("File")}}</th>
<th>{{=T("Error")}}</th>
<th class="columnN"></th>
</tr>
</thead>
<tbody>
{{for e in errors:}}
<tr class="error_ticket">
<td class="cbcentered"><input type="checkbox" name="delete_{{=e['hash']}}" /></td>
<td>{{=e['count']}}</td>
<td>{{=e['causer']}}</td>
<td>{{=A(e['last_line'],_href="#",_onclick="collapse('%s');return false;"%e['hash'])}}</td>
<td>+&nbsp;{{=A(T('details'),_href=URL(base_url,args=[app,e['ticket']]))}}</td>
</tr>
<tr id="{{=e['hash']}}" class="traceback">
<td colspan="5">
<div class="ticket_code">
{{=CODE(e['pickel']['traceback'])}}
</div>
</td>
</tr>
{{pass}}
</tbody>
</table>
</div>
</div>
{{ else: }}
<p class="controls row-fluid">
<div class="controls controls-row">
{{if 'db' in method:}}
<span class="uneditable-input">source : db</span>
<a class="button btn" href="{{=URL(args=[app, 'old'])}}"><span>switch to : filesystem</span></a>
<a class="button btn" href="{{=URL(args=[app, 'dbnew'])}}"><span>lists by exception</span></a>
{{else:}}
<span class="uneditable-input">source : filesystem</span>
{{=switchbutton}}
<a class="button btn" href="{{=URL(args=[app, 'new'])}}"><span>lists by exception</span></a>
{{pass}}
</div>
</p>
<div class="tablebar">
<input value="{{=T('delete all checked')}}" type="submit" class="btn"/>
<span class="help label label-info">{{=T('Click row to expand traceback')}}</span>
</div>
<div class="row-fluid">
<div class="span6">
<table id="trck_errors" class="sortable table table-hover table-condensed">
<thead>
<tr>
<th class="column1 cbcentered"><input type="checkbox" name="delete_all}" /></th>
<th>{{=T("Ticket")}}</th>
<th class="columnN1">{{=T("Date and Time")}}</th>
</tr>
</thead>
<tbody>
{{for ticket in tickets:}}
<tr>
<td class="cbcentered"><input type="checkbox" name="delete_{{=ticket}}"/></td>
{{if 'db' in method:}}
<td><a href="{{=URL('ticketdb',args=[app,ticket])}}">{{=ticket}}</a></td>
<td>{{=time.strftime('%Y-%m-%d %H:%M:%S',times[ticket].timetuple())}}</td>
{{else:}}
<td><a href="{{=URL('ticket',args=[app,ticket])}}">{{=ticket}}</a></td>
<td>{{=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(os.stat(os.path.join(request.folder,'../%s/errors/%s' % (app,ticket)))[stat.ST_CTIME]))}}</td>
{{pass}}
</tr>
{{pass}}
</tbody>
</table>
</div>
</div>
{{ pass }}
</form><!-- /errorform -->
<form name="myform" method="post">
{{ if 'new' in method: }}
{{base_url = 'db' in method and 'ticketdb' or 'ticket' }}
<p class="controls row-fluid">
<div class="controls controls-row">
{{if 'db' in method:}}
<span class="uneditable-input">source : db</span>
<a class="button btn" href="{{=URL(args=[app, 'new'])}}"><span>switch to : filesystem</span></a>
<a class="button btn" href="{{=URL(args=[app, 'dbold'])}}"><span>lists by ticket</span></a>
{{else:}}
<span class="uneditable-input">source : filesystem</span>
{{=switchbutton}}
<a class="button btn" href="{{=URL(args=[app, 'old'])}}"><span>lists by ticket</span></a>
{{pass}}
</div>
</p>
<div class="tablebar">
<input value="{{=T('delete all checked')}}" type="submit" class="btn"/>
<span class="help label label-info">{{=T('Click row to expand traceback')}}</span>
</div>
<div class="row-fluid">
<div class="span6">
<table id="trck_errors" class="sortable table table-hover table-condensed">
<thead>
<tr>
<th class="column1 cbcentered"><input type="checkbox" name="delete_all}" /></th>
<th class="column2">{{=T("Count")}}</th>
<th class="column3">{{=T("File")}}</th>
<th>{{=T("Error")}}</th>
<th class="columnN"></th>
</tr>
</thead>
<tbody>
{{for e in errors:}}
<tr class="error_ticket">
<td class="cbcentered"><input type="checkbox" name="delete_{{=e['hash']}}" /></td>
<td>{{=e['count']}}</td>
<td>{{=e['causer']}}</td>
<td>{{=A(e['last_line'],_href="#",_onclick="collapse('%s');return false;"%e['hash'])}}</td>
<td>+&nbsp;{{=A(T('details'),_href=URL(base_url,args=[app,e['ticket']]))}}</td>
</tr>
<tr id="{{=e['hash']}}" class="traceback">
<td colspan="5">
<div class="ticket_code">
{{=CODE(e['pickel']['traceback'])}}
</div>
</td>
</tr>
{{pass}}
</tbody>
</table>
</div>
</div>
{{ else: }}
<p class="controls row-fluid">
<div class="controls controls-row">
{{if 'db' in method:}}
<span class="uneditable-input">source : db</span>
<a class="button btn" href="{{=URL(args=[app, 'old'])}}"><span>switch to : filesystem</span></a>
<a class="button btn" href="{{=URL(args=[app, 'dbnew'])}}"><span>lists by exception</span></a>
{{else:}}
<span class="uneditable-input">source : filesystem</span>
{{=switchbutton}}
<a class="button btn" href="{{=URL(args=[app, 'new'])}}"><span>lists by exception</span></a>
{{pass}}
</div>
</p>
<div class="tablebar">
<input value="{{=T('delete all checked')}}" type="submit" class="btn"/>
<span class="help label label-info">{{=T('Click row to expand traceback')}}</span>
</div>
<div class="row-fluid">
<div class="span6">
<table id="trck_errors" class="sortable table table-hover table-condensed">
<thead>
<tr>
<th class="column1 cbcentered"><input type="checkbox" name="delete_all}" /></th>
<th>{{=T("Ticket")}}</th>
<th class="columnN1">{{=T("Date and Time")}}</th>
</tr>
</thead>
<tbody>
{{for ticket in tickets:}}
<tr>
<td class="cbcentered"><input type="checkbox" name="delete_{{=ticket}}"/></td>
{{if 'db' in method:}}
<td><a href="{{=URL('ticketdb',args=[app,ticket])}}">{{=ticket}}</a></td>
<td>{{=time.strftime('%Y-%m-%d %H:%M:%S',times[ticket].timetuple())}}</td>
{{else:}}
<td><a href="{{=URL('ticket',args=[app,ticket])}}">{{=ticket}}</a></td>
<td>{{=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(os.stat(os.path.join(request.folder,'../%s/errors/%s' % (app,ticket)))[stat.ST_CTIME]))}}</td>
{{pass}}
</tr>
{{pass}}
</tbody>
</table>
</div>
</div>
{{ pass }}
</form><!-- /errorform -->
</div>
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('.traceback').hide();
jQuery("#trck_errors thead tr th:first input[type=checkbox]").click(function() {
var checkedStatus = this.checked;
jQuery("#trck_errors tbody tr td:first-child input[type=checkbox]").each(function() {
this.checked = checkedStatus;
});
});
});
jQuery(document).ready(function() {
jQuery('.traceback').hide();
jQuery("#trck_errors thead tr th:first input[type=checkbox]").click(function() {
var checkedStatus = this.checked;
jQuery("#trck_errors tbody tr td:first-child input[type=checkbox]").each(function() {
this.checked = checkedStatus;
});
});
});
</script>
<!-- end "errors" block -->
<!-- end "errors" block -->
@@ -9,18 +9,18 @@
<ul class="collapsible">
{{for file in files[path]['files']:}}
<li style="list-style-type: none;">
{{p = os.path.relpath(os.path.join(path,file),base)}}
<input type="checkbox" value="{{=p}}" name="file" checked="checked"/>
{{=file}}
{{p = os.path.relpath(os.path.join(path,file),base)}}
<input type="checkbox" value="{{=p}}" name="file" checked="checked"/>
{{=file}}
</li>
{{pass}}
{{for dir in files[path]['folders']:}}
<li style="list-style-type: none;">
{{tree(os.path.join(path,dir))}}
{{tree(os.path.join(path,dir))}}
</li>
{{pass}}
</ul>
{{return}}
</ul>
{{return}}
<form action="{{=URL(args=request.args)}}" method="POST">
<h2>{{=T('Select Files to Package')}}</h2>
+107 -108
View File
@@ -7,57 +7,57 @@
<div class="applist_inner">
<h2>{{=T("Installed applications")}}</h2>
<table width="100%" class="table">
{{for a in apps:}}
<tr>{{buttons = []}}
<td>
{{if a==request.application:}}
<h4 class="currentapp">{{=a}} ({{=T('currently running')}})</h4>
{{else:}}
<h4 class="editableapp">{{=A(a,_href=URL(a,'default','index'))}}</h4>
{{if MULTI_USER_MODE and db.app(name=a):}}(created by {{="%(first_name)s %(last_name)s" % db.auth_user[db.app(name=a).owner]}}){{pass}}
{{if not os.path.exists('applications/%s/compiled' % a):}}
{{buttons.append((URL('design',args=a), T("Edit")))}}
{{else:}}
{{buttons.append((URL(a,'appadmin','index'), T("appadmin")))}}
{{pass}}
{{buttons.append((URL('about',args=a), T("About")))}}
{{pass}}
{{buttons.append((URL('errors',args=a), T("Errors")))}}
{{buttons.append((URL('cleanup',args=a), T("Clean")))}}
{{buttons.append((URL('pack',args=a), T("Pack all")))}}
{{buttons.append((URL('pack_custom',args=a), T("Pack custom")))}}
{{if not os.path.exists('applications/%s/compiled' % a):}}
{{for a in apps:}}
<tr>{{buttons = []}}
<td>
{{if a==request.application:}}
<h4 class="currentapp">{{=a}} ({{=T('currently running')}})</h4>
{{else:}}
<h4 class="editableapp">{{=A(a,_href=URL(a,'default','index'))}}</h4>
{{if MULTI_USER_MODE and db.app(name=a):}}(created by {{="%(first_name)s %(last_name)s" % db.auth_user[db.app(name=a).owner]}}){{pass}}
{{if not os.path.exists('applications/%s/compiled' % a):}}
{{buttons.append((URL('design',args=a), T("Edit")))}}
{{else:}}
{{buttons.append((URL(a,'appadmin','index'), T("appadmin")))}}
{{pass}}
{{buttons.append((URL('about',args=a), T("About")))}}
{{pass}}
{{buttons.append((URL('errors',args=a), T("Errors")))}}
{{buttons.append((URL('cleanup',args=a), T("Clean")))}}
{{buttons.append((URL('pack',args=a), T("Pack all")))}}
{{buttons.append((URL('pack_custom',args=a), T("Pack custom")))}}
{{if not os.path.exists('applications/%s/compiled' % a):}}
{{buttons.append((URL('compile_app',args=a), T("Compile")))}}
{{else:}}
{{buttons.append((URL('pack',args=(a, 'compiled')), T("Pack compiled")))}}
{{if glob.glob('applications/%s/controllers/*.py' % a):}}
{{buttons.append((URL('remove_compiled_app',args=a), T("Remove compiled")))}}
{{pass}}
{{pass}}
{{if os.path.exists(os.path.join(apath(r=request),a,'.git')): }}
{{buttons.append((URL('git_pull',args=a), T("Git Pull")))}}
{{buttons.append((URL('git_push',args=a), T("Git Push")))}}
{{pass}}
{{if a!=request.application:}}
{{buttons.append((URL('uninstall',args=a), T("Uninstall")))}}
{{pass}}
</td>
<td>
<div class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
{{=T('Manage')}}
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
{{for link,name in buttons:}}
{{=LI(A(name,_href=link))}}
{{pass}}
</ul>
</div>
{{=button_enable(URL('enable',args=a), a)}}
</td>
</tr>
{{pass}}
{{else:}}
{{buttons.append((URL('pack',args=(a, 'compiled')), T("Pack compiled")))}}
{{if glob.glob('applications/%s/controllers/*.py' % a):}}
{{buttons.append((URL('remove_compiled_app',args=a), T("Remove compiled")))}}
{{pass}}
{{pass}}
{{if os.path.exists(os.path.join(apath(r=request),a,'.git')): }}
{{buttons.append((URL('git_pull',args=a), T("Git Pull")))}}
{{buttons.append((URL('git_push',args=a), T("Git Push")))}}
{{pass}}
{{if a!=request.application:}}
{{buttons.append((URL('uninstall',args=a), T("Uninstall")))}}
{{pass}}
</td>
<td>
<div class="btn-group">
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#">
{{=T('Manage')}}
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
{{for link,name in buttons:}}
{{=LI(A(name,_href=link))}}
{{pass}}
</ul>
</div>
{{=button_enable(URL('enable',args=a), a)}}
</td>
</tr>
{{pass}}
</table>
</div>
</div> <!-- /applist -->
@@ -65,85 +65,85 @@
<div class="sidebar_inner controls well well-small">
<!-- CHANGE ADMIN PWD -->
<div class="pwdchange pull-right">
{{if MULTI_USER_MODE:}}
{{=auth.navbar()}}
{{else:}}
{{=sp_button(URL('change_password'), T('Change admin password'))}}
{{=button(URL('default','reload_routes'), T('Reload routes'))}}
{{pass}}
{{if MULTI_USER_MODE:}}
{{=auth.navbar()}}
{{else:}}
{{=sp_button(URL('change_password'), T('Change admin password'))}}
{{=button(URL('default','reload_routes'), T('Reload routes'))}}
{{pass}}
</div> <!-- /CHANGE ADMIN PWD -->
{{if is_manager():}}
<!-- VERSION -->
<div class="box">
<h4>{{=T("Version")}}</h4>
<p>
<tt>{{=myversion}}</tt><br/>
({{=T("Running on %s", request.env.server_software)}})
</p>
<p id="check_version" class="row-buttons">
{{if session.check_version:}}
{{=T('Checking for upgrades...')}}
<script>ajax('{{=URL('check_version')}}',[],'check_version');</script>
{{session.check_version=False}}
{{else:}}
{{=button("javascript:ajax('"+URL('check_version')+"',[],'check_version')", T('Check for upgrades'))}}
{{pass}}
</p>
{{if session.is_mobile=='auto':}}
<p>{{=A(T('Try the mobile interface'),_href=URL('plugin_jqmobile','about'))}}</p>
{{pass}}
<h4>{{=T("Version")}}</h4>
<p>
<tt>{{=myversion}}</tt><br/>
({{=T("Running on %s", request.env.server_software)}})
</p>
<p id="check_version" class="row-buttons">
{{if session.check_version:}}
{{=T('Checking for upgrades...')}}
<script>ajax('{{=URL('check_version')}}',[],'check_version');</script>
{{session.check_version=False}}
{{else:}}
{{=button("javascript:ajax('"+URL('check_version')+"',[],'check_version')", T('Check for upgrades'))}}
{{pass}}
</p>
{{if session.is_mobile=='auto':}}
<p>{{=A(T('Try the mobile interface'),_href=URL('plugin_jqmobile','about'))}}</p>
{{pass}}
</div> <!-- /VERSION -->
{{pass}}
{{if MULTI_USER_MODE and is_manager():}}
<!-- MULTI_USER_INTERFACE -->
<div class="box">
<h4>{{=T("Multi User Mode")}}</h4>
<p class="row-buttons">
{{=button(URL('bulk_register'),T('Bulk Register'))}}
{{=button(URL('manage_students',vars={'order':'auth_user.id'}),T('Manage Students'))}}
</p>
<h4>{{=T("Multi User Mode")}}</h4>
<p class="row-buttons">
{{=button(URL('bulk_register'),T('Bulk Register'))}}
{{=button(URL('manage_students',vars={'order':'auth_user.id'}),T('Manage Students'))}}
</p>
</div> <!-- /MULTI_USER_INTERFACE -->
{{pass}}
<!-- SCAFFOLD APP -->
<div class="box">
<h4>{{=T("New simple application")}}</h4>
{{=form_create.custom.begin}}
{{=LABEL(T("Application name:"))}}
{{=form_create.custom.widget.name}}
<div class="controls"><button type="submit" class="btn">{{=T('Create')}}</button></div>
{{=form_create.custom.end}}
<h4>{{=T("New simple application")}}</h4>
{{=form_create.custom.begin}}
{{=LABEL(T("Application name:"))}}
{{=form_create.custom.widget.name}}
<div class="controls"><button type="submit" class="btn">{{=T('Create')}}</button></div>
{{=form_create.custom.end}}
</div> <!-- /SCAFFOLD APP -->
<!-- UPLOAD PACKAGE -->
<div class="box">
<h4>{{=T("Upload and install packed application")}}</h4>
{{=form_update.custom.begin}}
<label for="appupdate_name">{{=T("Application name:")}}</label>
{{=form_update.custom.widget.name}}
<label for="appupdate_file">{{=T("Upload a package:")}}</label>
{{=form_update.custom.widget.file}}
<label for="appupdate_url">{{=T("Or Get from URL:")}}</label>
{{=form_update.custom.widget.url}}<small class="help-block">({{=T('can be a git repo')}})</small>
<div class="controls">
<label class="checkbox">
{{=form_update.custom.widget.overwrite}} {{=T("Overwrite installed app")}}
</label>
<button type="submit" class='btn'>{{=T('Install')}}</button>
</div>
{{=form_update.custom.end}}
<h4>{{=T("Upload and install packed application")}}</h4>
{{=form_update.custom.begin}}
<label for="appupdate_name">{{=T("Application name:")}}</label>
{{=form_update.custom.widget.name}}
<label for="appupdate_file">{{=T("Upload a package:")}}</label>
{{=form_update.custom.widget.file}}
<label for="appupdate_url">{{=T("Or Get from URL:")}}</label>
{{=form_update.custom.widget.url}}<small class="help-block">({{=T('can be a git repo')}})</small>
<div class="controls">
<label class="checkbox">
{{=form_update.custom.widget.overwrite}} {{=T("Overwrite installed app")}}
</label>
<button type="submit" class='btn'>{{=T('Install')}}</button>
</div>
{{=form_update.custom.end}}
</div> <!-- /UPLOAD PACKAGE -->
<!-- DEPLOY ON GAE -->
<div class="box">
<h4>{{=T("Deploy")}}</h4>
<p class="row-buttons">
{{=button(URL('gae','deploy'), T('Deploy on Google App Engine'))}}
{{=button(URL('openshift','deploy'),T('Deploy to OpenShift'))}}
</p>
<h4>{{=T("Deploy")}}</h4>
<p class="row-buttons">
{{=button(URL('gae','deploy'), T('Deploy on Google App Engine'))}}
{{=button(URL('openshift','deploy'),T('Deploy to OpenShift'))}}
</p>
</div> <!-- /DEPLOY ON GAE -->
<!-- APP WIZARD -->
<div class="box">
<h4>{{=T("New application wizard")}}</h4>
<p>{{=button(URL('wizard','index'), T('Start wizard'))}}<br/>
{{=T("(requires internet access, experimental)")}}</p>
<h4>{{=T("New application wizard")}}</h4>
<p>{{=button(URL('wizard','index'), T('Start wizard'))}}<br/>
{{=T("(requires internet access, experimental)")}}</p>
</div> <!-- /APP WIZARD -->
<a class="twitter-timeline" href="https://twitter.com/web2py" data-widget-id="340456915207327745">Tweets by @web2py</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
@@ -151,4 +151,3 @@
</div> <!-- /sidebar -->
</div> <!-- /row-fluid
<!-- end "site" block -->
+39 -39
View File
@@ -16,7 +16,7 @@
<tr>
<th>Python</th>
<td>{{=snapshot.get('pyver','')}}</td>
</tr>
</tr>
{{pass}}
</tbody>
</table>
@@ -45,14 +45,14 @@
<div class="inspect">
<h4>{{=T("Exception instance attributes")}}</h4>
<table>
<tbody>
{{for k,v in snapshot['exception'].items():}}
<tr>
<th>{{=k}}</th>
<td>{{=v}}</td>
</tr>
{{pass}}
</tbody>
<tbody>
{{for k,v in snapshot['exception'].items():}}
<tr>
<th>{{=k}}</th>
<td>{{=v}}</td>
</tr>
{{pass}}
</tbody>
</table>
</div>
</div>
@@ -65,36 +65,36 @@
<li>
{{is_hidden = (i != len(snapshot['frames'])-1 and 'hide' or 'inspect')}}
<div class="framefile inspect controls">
<p>
<strong>File {{="%s in %s at line %s" % (frame['file'], frame['func'], frame['lnum'])}}</strong>
<a class="button tbbutton btn" onclick="collapse('{{='%s_code_inner' % i}}');"><span>{{=T("code")}}</span></a>
<a class="button tbbutton btn" onclick="collapse('{{='%s_args_inner' % i}}');"><span>{{=T("arguments")}}</span></a>
<a class="button tbbutton btn" onclick="collapse('{{='%s_vars_inner' % i}}');"><span>{{=T("variables")}}</span></a>
</p>
<div id="{{='%s_args_inner' % i}}" class="{{=is_hidden}}" style="width:100%;overflow:auto">
<h5>Function argument list</h5>
<p>{{=frame['call']}}</p>
</div>
<div id="{{='%s_code_inner' % i}}" class="{{=is_hidden}}" style="width:100%;overflow:auto">
<h5>Code listing</h5>
{{if frame['lines']:}}
<pre>{{=CODE('\n'.join([x[1] for x in sorted(frame['lines'].items(),key=lambda x: x[0])]),
language='python', link=None, counter=min(frame['lines'].keys()), highlight_line=frame['lnum'])}}</pre>
{{pass}}
</div>
<div id="{{='%s_vars_inner' % i}}" class="{{=is_hidden}}" style="width:100%;overflow:auto">
<h5>Variables</h5>
<table>
<tbody>
{{for k,v in frame['dump'].items():}}
<tr>
<th>{{=k}}</th>
<td>{{=v}}</td>
</tr>
{{pass}}
</tbody>
</table>
</div>
<p>
<strong>File {{="%s in %s at line %s" % (frame['file'], frame['func'], frame['lnum'])}}</strong>
<a class="button tbbutton btn" onclick="collapse('{{='%s_code_inner' % i}}');"><span>{{=T("code")}}</span></a>
<a class="button tbbutton btn" onclick="collapse('{{='%s_args_inner' % i}}');"><span>{{=T("arguments")}}</span></a>
<a class="button tbbutton btn" onclick="collapse('{{='%s_vars_inner' % i}}');"><span>{{=T("variables")}}</span></a>
</p>
<div id="{{='%s_args_inner' % i}}" class="{{=is_hidden}}" style="width:100%;overflow:auto">
<h5>Function argument list</h5>
<p>{{=frame['call']}}</p>
</div>
<div id="{{='%s_code_inner' % i}}" class="{{=is_hidden}}" style="width:100%;overflow:auto">
<h5>Code listing</h5>
{{if frame['lines']:}}
<pre>{{=CODE('\n'.join([x[1] for x in sorted(frame['lines'].items(),key=lambda x: x[0])]),
language='python', link=None, counter=min(frame['lines'].keys()), highlight_line=frame['lnum'])}}</pre>
{{pass}}
</div>
<div id="{{='%s_vars_inner' % i}}" class="{{=is_hidden}}" style="width:100%;overflow:auto">
<h5>Variables</h5>
<table>
<tbody>
{{for k,v in frame['dump'].items():}}
<tr>
<th>{{=k}}</th>
<td>{{=v}}</td>
</tr>
{{pass}}
</tbody>
</table>
</div>
</div>
</li>
{{pass}}
+37 -13
View File
@@ -17,7 +17,7 @@
<body class="{{=T('direction: ltr') == 'direction: rtl' and 'RTLbody' or ''}} {{block sectionclass}}home{{end}}">
<!-- NAVBAR
<!-- NAVBAR
============== -->
<div id="header" class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
@@ -43,7 +43,7 @@
</div><!-- /navbar-inner -->
</div><!-- /#header -->
<!-- MAIN
<!-- MAIN
=========== -->
<div id="main" class="container-fluid">
<div id="main_inner" class="row-fluid">
@@ -54,7 +54,7 @@
</div><!-- /main row-fluid -->
</div><!-- /#main -->
<!-- FOOTER
<!-- FOOTER
============== -->
<footer id="footer" class="fixed">
<p><span>{{=T('Powered by')}} {{=A('web2py', _href='http://www.web2py.com')}}&trade; {{=T('created by')}} Massimo Di Pierro &copy;2007-{{=request.now.year}}
@@ -70,19 +70,43 @@
</p>
</footer><!-- /#footer -->
<!-- BS JAVASCRIPT
<!-- BS JAVASCRIPT
====================== -->
<script src="{{=URL('static','js/bootstrap.min.js')}}"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery("[rel=tooltip]").tooltip();
<script type="text/javascript">
jQuery(document).ready(function(){
jQuery("[rel=tooltip]").tooltip();
});
</script>
{{if request.function in ('index','site'):}}
<a style="position:fixed;bottom:0;left:0;z-index:1000" href="https://groups.google.com/forum/?fromgroups#!forum/web2py" target="_blank">
<!-- http://webchat.freenode.net/?channels=web2py" //-->
<img src="{{=URL('static','images/questions.png')}}" />
</a>
{{pass}}
<script>
// ====================
// upload input mask
// ====================
function FileSelectHandler(e) {
e.stopPropagation();
var filename = e.target.value.split(/\\|\//).pop();
jQuery('#fileselect>span').removeClass('txtPlaceholder').text(filename)
}
jQuery(document).ready(function(){
var iupload = jQuery('#appupdate_file');
var ow = 300, oh = 20;
var iplaceholder = jQuery('<span class="txtPlaceholder">{{=T("no package selected")}}</span>'),
iuploadbtn = jQuery('<button class="btn btn-inverse btn-mini uploadbtn"><i class="icon-white icon-circle-arrow-up"></i></button>');
iupload
.addClass('masked')
.wrap('<div id="fileselect" style="width:'+ow+'px;height:'+oh+'px"></div>')
.on('change', function(event){FileSelectHandler(event)});
jQuery('#fileselect').append(iplaceholder, iuploadbtn);
});
</script>
{{if request.function in ('index','site'):}}
<a style="position:fixed;bottom:0;left:0;z-index:1000" href="https://groups.google.com/forum/?fromgroups#!forum/web2py" target="_blank">
<!-- http://webchat.freenode.net/?channels=web2py" //-->
<img src="{{=URL('static','images/questions.png')}}" />
</a>
{{pass}}
</body>
</html>
@@ -31,7 +31,7 @@
<link rel="apple-touch-icon" href="{{=URL('static','favicon.png')}}">
<!-- For the less-enabled mobile browsers like Opera Mini -->
<link rel="stylesheet" href="{{=URL('static','plugin_jqmobile/jquery.mobile-1.2.0.min.css')}}">
<link rel="stylesheet" href="{{=URL('static','plugin_jqmobile/jquery.mobile-1.3.1.min.css')}}">
<!-- All JavaScript at the bottom, except for Modernizr which enables HTML5 elements & feature detects -->
<script src="{{=URL('static','js/modernizr.custom.js')}}"></script!>
@@ -61,7 +61,7 @@ $(document).bind("mobileinit", function(){
});
</script>
<script src="{{=URL('static','plugin_jqmobile/jquery.mobile-1.2.0.min.js')}}"></script>
<script src="{{=URL('static','plugin_jqmobile/jquery.mobile-1.3.1.min.js')}}"></script>
<style>
.error { color: red; }
@@ -623,7 +623,10 @@ def manage():
orderby = 'role' if not request.args(3) or '.group_id' not in request.args(3) else None
elif table == auth.table_permission():
orderby = 'group_id'
grid = SQLFORM.smartgrid(table, args=request.args[:2], user_signature=True,
orderby=orderby, linked_tables=linked_tables,
maxtextlength=1000, formname=formname)
kwargs = dict(user_signature=True, maxtextlength=1000,
orderby=orderby, linked_tables=linked_tables)
smartgrid_args = manager_action.get('smartgrid_args', {})
kwargs.update(**smartgrid_args.get('DEFAULT', {}))
kwargs.update(**smartgrid_args.get(table._tablename, {}))
grid = SQLFORM.smartgrid(table, args=request.args[:2], formname=formname, **kwargs)
return grid
@@ -90,6 +90,7 @@ div.controls select +.error_wrapper {margin-left:5px;}
.ie-lte7 div.error{color:#fff;}
/* beautify brand */
.navbar {margin-bottom:0}
.navbar-inverse .brand{color:#c6cecc;}
.navbar-inverse .brand b{display:inline-block;margin-top:-1px;}
.navbar-inverse .brand b>span{font-size:22px;color:white}
@@ -222,6 +223,10 @@ td.w2p_fw ul{margin-left:0px;}
/* auth_user_remember checkbox extrapadding in IE fix */
.ie-lte9 input#auth_user_remember.checkbox {padding-left:0;}
div.controls .error {
width: auto;
}
/*=============================================================
MEDIA QUERIES
==============================================================*/
+70 -61
View File
@@ -7,6 +7,10 @@
* Released under the MIT license
*
*/
if($.web2py !== undefined) {
$.error('web2py.js has already been loaded!');
}
String.prototype.reverse = function () {
return this.split('').reverse().join('');
@@ -36,12 +40,13 @@
}
} else {
pcs = [];
if(s != null && s != undefined) for(i = 0; i < s.length; i++) {
if(s != null && s != undefined)
for(i = 0; i < s.length; i++) {
q = $("[name=" + s[i] + "]").serialize();
if(q) {
pcs.push(q);
}
}
}
if(pcs.length > 0) {
query = pcs.join("&");
}
@@ -147,9 +152,9 @@
web2py.component_handler(target);
},
//manage errors in forms
manage_errors: function(target) {
manage_errors: function (target) {
$('.error', target).hide().slideDown('slow');
//$('.error', target).hide().fadeIn('slow');
//jQuery('.error', target).hide().fadeIn('slow');
},
event_handlers: function () {
/* This is called once for page
@@ -172,7 +177,8 @@
});
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
doc.on('click', "input[type='checkbox'].delete", function () {
if(this.checked) if(!web2py.confirm(confirm_message)) this.checked = false;
if(this.checked)
if(!web2py.confirm(confirm_message)) this.checked = false;
});
doc.ajaxSuccess(function (e, xhr) {
@@ -424,7 +430,7 @@
el.addClass('disabled');
var method = el.prop('type') == 'submit' ? 'val' : 'html';
// store enabled state
el.data('w2p:enable-with', el[method]);
el.data('w2p:enable-with', el[method]());
/* little addition by default*/
if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) {
el.data('w2p_disable_with', 'Working...');
@@ -441,7 +447,7 @@
enableElement: function (el) {
var method = el.prop('type') == 'submit' ? 'val' : 'html';
if(el.data('w2p:enable-with') !== undefined) {
// set to old enabled state
// set to old enabled state
el[method](el.data('w2p:enable-with'));
el.removeData('w2p:enable-with'); // clean up cache
}
@@ -453,39 +459,39 @@
web2py.component(action, target, 0, 1, element);
},
//helper for flash messages
flash: function(message, status) {
flash: function (message, status) {
var flash = $('.flash');
web2py.hide_flash();
flash.html(message).addClass(status);
if(flash.html()) flash.append('<span id="closeflash"> &times; </span>').slideDown();
},
hide_flash: function() {
hide_flash: function () {
$('.flash').hide().html('');
},
show_if_handler: function(target) {
var triggers = {};
var show_if = function () {
var t = $(this);
var id = t.attr('id');
t.attr('value', t.val());
for(var k = 0; k < triggers[id].length; k++) {
var dep = $('#' + triggers[id][k], target);
var tr = $('#' + triggers[id][k] + '__row', target);
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
else tr.hide();
}
};
$('[data-show-trigger]', target).each(function () {
var name = $(this).attr('data-show-trigger');
if(!triggers[name]) triggers[name] = [];
triggers[name].push($(this).attr('id'));
});
for(var name in triggers) {
$('#' + name, target).change(show_if).keyup(show_if);
show_if.call($('#' + name, target));
};
show_if_handler: function (target) {
var triggers = {};
var show_if = function () {
var t = $(this);
var id = t.attr('id');
t.attr('value', t.val());
for(var k = 0; k < triggers[id].length; k++) {
var dep = $('#' + triggers[id][k], target);
var tr = $('#' + triggers[id][k] + '__row', target);
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
else tr.hide();
}
};
$('[data-show-trigger]', target).each(function () {
var name = $(this).attr('data-show-trigger');
if(!triggers[name]) triggers[name] = [];
triggers[name].push($(this).attr('id'));
});
for(var name in triggers) {
$('#' + name, target).change(show_if).keyup(show_if);
show_if.call($('#' + name, target));
};
},
component_handler : function (target) {
component_handler: function (target) {
$('div[data-w2p_remote]', target).each(function () {
var remote, times, timeout, target;
var el = $(this);
@@ -494,8 +500,7 @@
timeout = el.data('w2p_timeout');
target = el.attr('id');
web2py.component(remote, target, timeout, times, $(this));
}
)
})
},
a_handler: function (el, e) {
e.preventDefault();
@@ -517,14 +522,16 @@
}
if(target == undefined) {
if(method == 'GET') {
web2py.simple_component(action, el.attr('id'), el); //not working with original
web2py.ajax_page('get', action, [], 'bogus', el); //fixme?
//web2py.simple_component(action, el.attr('id'), el); //not working with original
} else if(method == 'POST') {
//should be web2py.ajax(action, [], ''); but it's too simple
web2py.ajax_page('post', action, [], 'bogus', el); //fixme?
}
} else {
if(method == 'GET') {
web2py.simple_component(action, target, el);
web2py.ajax_page('get', action, [], target, el);
//web2py.simple_component(action, target, el);
} else if(method == 'POST') {
//should be web2py.ajax(action, [], target); but it's too simple
web2py.ajax_page('post', action, [], target, el);
@@ -539,7 +546,7 @@
toremove = el.closest(toremove);
if(!toremove.length) {
//this enables removal of whatever selector if a closest is not found
toremove = $(toremove);
toremove = jQuery(toremove);
}
toremove.remove();
}
@@ -571,16 +578,17 @@
web2py.enableElement($(this));
});
},
/* Disables form elements:
/* Disables form elements:
- Caches element value in 'ujs:enable-with' data store
- Replaces element text with value of 'data-disable-with' attribute
- Sets disabled property to true
*/
disableFormElements: function(form) {
form.find(web2py.disableSelector).each(function() {
var element = $(this), method = element.is('button') ? 'html' : 'val';
disableFormElements: function (form) {
form.find(web2py.disableSelector).each(function () {
var element = $(this),
method = element.is('button') ? 'html' : 'val';
var disable_with = element.data('w2p_disable_with');
if (disable_with == undefined) {
if(disable_with == undefined) {
element.data('w2p_disable_with', element[method]())
}
element.data('w2p:enable-with', element[method]());
@@ -593,14 +601,15 @@
- Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
- Sets disabled property to false
*/
enableFormElements: function(form) {
form.find(web2py.enableSelector).each(function() {
var element = $(this), method = element.is('button') ? 'html' : 'val';
if (element.data('w2p:enable-with')) element[method](element.data('w2p:enable-with'));
enableFormElements: function (form) {
form.find(web2py.enableSelector).each(function () {
var element = $(this),
method = element.is('button') ? 'html' : 'val';
if(element.data('w2p:enable-with')) element[method](element.data('w2p:enable-with'));
element.prop('disabled', false);
});
},
form_handlers: function() {
form_handlers: function () {
var el = $(document);
el.on('ajax:beforeSend', 'form[data-w2p_target]', function (e) {
web2py.disableFormElements($(this));
@@ -626,28 +635,28 @@
})(jQuery);
/* compatibility code - start */
ajax = $.web2py.ajax;
web2py_component = $.web2py.component;
web2py_websocket = $.web2py.websocket;
web2py_ajax_page = $.web2py.ajax_page;
ajax = jQuery.web2py.ajax;
web2py_component = jQuery.web2py.component;
web2py_websocket = jQuery.web2py.websocket;
web2py_ajax_page = jQuery.web2py.ajax_page;
//needed for IS_STRONG(entropy)
web2py_validate_entropy = $.web2py.validate_entropy;
web2py_validate_entropy = jQuery.web2py.validate_entropy;
//needed for crud.search and SQLFORM.grid's search
web2py_ajax_fields = $.web2py.ajax_fields;
web2py_ajax_fields = jQuery.web2py.ajax_fields;
//used for LOAD(ajax=False)
web2py_trap_form = $.web2py.trap_form;
web2py_trap_form = jQuery.web2py.trap_form;
/*undocumented - rare*/
popup = $.web2py.popup;
collapse = $.web2py.collapse;
fade = $.web2py.fade;
popup = jQuery.web2py.popup;
collapse = jQuery.web2py.collapse;
fade = jQuery.web2py.fade;
/* internals - shouldn't be needed
web2py_ajax_init = $.web2py.ajax_init;
web2py_event_handlers = $.web2py.event_handlers;
web2py_ajax_init = jQuery.web2py.ajax_init;
web2py_event_handlers = jQuery.web2py.event_handlers;
web2py_trap_link = $.web2py.trap_link;
web2py_calc_entropy = $.web2py.calc_entropy;
web2py_trap_link = jQuery.web2py.trap_link;
web2py_calc_entropy = jQuery.web2py.calc_entropy;
*/
/* compatibility code - end*/
+6 -3
View File
@@ -623,7 +623,10 @@ def manage():
orderby = 'role' if not request.args(3) or '.group_id' not in request.args(3) else None
elif table == auth.table_permission():
orderby = 'group_id'
grid = SQLFORM.smartgrid(table, args=request.args[:2], user_signature=True,
orderby=orderby, linked_tables=linked_tables,
maxtextlength=1000, formname=formname)
kwargs = dict(user_signature=True, maxtextlength=1000,
orderby=orderby, linked_tables=linked_tables)
smartgrid_args = manager_action.get('smartgrid_args', {})
kwargs.update(**smartgrid_args.get('DEFAULT', {}))
kwargs.update(**smartgrid_args.get(table._tablename, {}))
grid = SQLFORM.smartgrid(table, args=request.args[:2], formname=formname, **kwargs)
return grid
@@ -223,16 +223,21 @@ td.w2p_fw ul{margin-left:0px;}
/* auth_user_remember checkbox extrapadding in IE fix */
.ie-lte9 input#auth_user_remember.checkbox {padding-left:0;}
div.controls .error {
width: auto;
}
/*=============================================================
MEDIA QUERIES
==============================================================*/
@media only screen and (max-width:979px){
body{padding-top:0px;}
#navbar{top:5px;}
#navbar{/*top:5px;*/}
div.flash{right:5px;}
.dropdown-menu ul{visibility:visible;}
}
@media only screen and (max-width:479px){
body{
padding-left:10px;
@@ -246,3 +251,10 @@ td.w2p_fw ul{margin-left:0px;}
width:95%;
}
}
@media (max-width: 767px) {
.navbar {
margin-right: -20px;
margin-left: -20px;
}
}
+70 -61
View File
@@ -7,6 +7,10 @@
* Released under the MIT license
*
*/
if($.web2py !== undefined) {
$.error('web2py.js has already been loaded!');
}
String.prototype.reverse = function () {
return this.split('').reverse().join('');
@@ -36,12 +40,13 @@
}
} else {
pcs = [];
if(s != null && s != undefined) for(i = 0; i < s.length; i++) {
if(s != null && s != undefined)
for(i = 0; i < s.length; i++) {
q = $("[name=" + s[i] + "]").serialize();
if(q) {
pcs.push(q);
}
}
}
if(pcs.length > 0) {
query = pcs.join("&");
}
@@ -147,9 +152,9 @@
web2py.component_handler(target);
},
//manage errors in forms
manage_errors: function(target) {
manage_errors: function (target) {
$('.error', target).hide().slideDown('slow');
//$('.error', target).hide().fadeIn('slow');
//jQuery('.error', target).hide().fadeIn('slow');
},
event_handlers: function () {
/* This is called once for page
@@ -172,7 +177,8 @@
});
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
doc.on('click', "input[type='checkbox'].delete", function () {
if(this.checked) if(!web2py.confirm(confirm_message)) this.checked = false;
if(this.checked)
if(!web2py.confirm(confirm_message)) this.checked = false;
});
doc.ajaxSuccess(function (e, xhr) {
@@ -424,7 +430,7 @@
el.addClass('disabled');
var method = el.prop('type') == 'submit' ? 'val' : 'html';
// store enabled state
el.data('w2p:enable-with', el[method]);
el.data('w2p:enable-with', el[method]());
/* little addition by default*/
if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) {
el.data('w2p_disable_with', 'Working...');
@@ -441,7 +447,7 @@
enableElement: function (el) {
var method = el.prop('type') == 'submit' ? 'val' : 'html';
if(el.data('w2p:enable-with') !== undefined) {
// set to old enabled state
// set to old enabled state
el[method](el.data('w2p:enable-with'));
el.removeData('w2p:enable-with'); // clean up cache
}
@@ -453,39 +459,39 @@
web2py.component(action, target, 0, 1, element);
},
//helper for flash messages
flash: function(message, status) {
flash: function (message, status) {
var flash = $('.flash');
web2py.hide_flash();
flash.html(message).addClass(status);
if(flash.html()) flash.append('<span id="closeflash"> &times; </span>').slideDown();
},
hide_flash: function() {
hide_flash: function () {
$('.flash').hide().html('');
},
show_if_handler: function(target) {
var triggers = {};
var show_if = function () {
var t = $(this);
var id = t.attr('id');
t.attr('value', t.val());
for(var k = 0; k < triggers[id].length; k++) {
var dep = $('#' + triggers[id][k], target);
var tr = $('#' + triggers[id][k] + '__row', target);
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
else tr.hide();
}
};
$('[data-show-trigger]', target).each(function () {
var name = $(this).attr('data-show-trigger');
if(!triggers[name]) triggers[name] = [];
triggers[name].push($(this).attr('id'));
});
for(var name in triggers) {
$('#' + name, target).change(show_if).keyup(show_if);
show_if.call($('#' + name, target));
};
show_if_handler: function (target) {
var triggers = {};
var show_if = function () {
var t = $(this);
var id = t.attr('id');
t.attr('value', t.val());
for(var k = 0; k < triggers[id].length; k++) {
var dep = $('#' + triggers[id][k], target);
var tr = $('#' + triggers[id][k] + '__row', target);
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
else tr.hide();
}
};
$('[data-show-trigger]', target).each(function () {
var name = $(this).attr('data-show-trigger');
if(!triggers[name]) triggers[name] = [];
triggers[name].push($(this).attr('id'));
});
for(var name in triggers) {
$('#' + name, target).change(show_if).keyup(show_if);
show_if.call($('#' + name, target));
};
},
component_handler : function (target) {
component_handler: function (target) {
$('div[data-w2p_remote]', target).each(function () {
var remote, times, timeout, target;
var el = $(this);
@@ -494,8 +500,7 @@
timeout = el.data('w2p_timeout');
target = el.attr('id');
web2py.component(remote, target, timeout, times, $(this));
}
)
})
},
a_handler: function (el, e) {
e.preventDefault();
@@ -517,14 +522,16 @@
}
if(target == undefined) {
if(method == 'GET') {
web2py.simple_component(action, el.attr('id'), el); //not working with original
web2py.ajax_page('get', action, [], 'bogus', el); //fixme?
//web2py.simple_component(action, el.attr('id'), el); //not working with original
} else if(method == 'POST') {
//should be web2py.ajax(action, [], ''); but it's too simple
web2py.ajax_page('post', action, [], 'bogus', el); //fixme?
}
} else {
if(method == 'GET') {
web2py.simple_component(action, target, el);
web2py.ajax_page('get', action, [], target, el);
//web2py.simple_component(action, target, el);
} else if(method == 'POST') {
//should be web2py.ajax(action, [], target); but it's too simple
web2py.ajax_page('post', action, [], target, el);
@@ -539,7 +546,7 @@
toremove = el.closest(toremove);
if(!toremove.length) {
//this enables removal of whatever selector if a closest is not found
toremove = $(toremove);
toremove = jQuery(toremove);
}
toremove.remove();
}
@@ -571,16 +578,17 @@
web2py.enableElement($(this));
});
},
/* Disables form elements:
/* Disables form elements:
- Caches element value in 'ujs:enable-with' data store
- Replaces element text with value of 'data-disable-with' attribute
- Sets disabled property to true
*/
disableFormElements: function(form) {
form.find(web2py.disableSelector).each(function() {
var element = $(this), method = element.is('button') ? 'html' : 'val';
disableFormElements: function (form) {
form.find(web2py.disableSelector).each(function () {
var element = $(this),
method = element.is('button') ? 'html' : 'val';
var disable_with = element.data('w2p_disable_with');
if (disable_with == undefined) {
if(disable_with == undefined) {
element.data('w2p_disable_with', element[method]())
}
element.data('w2p:enable-with', element[method]());
@@ -593,14 +601,15 @@
- Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
- Sets disabled property to false
*/
enableFormElements: function(form) {
form.find(web2py.enableSelector).each(function() {
var element = $(this), method = element.is('button') ? 'html' : 'val';
if (element.data('w2p:enable-with')) element[method](element.data('w2p:enable-with'));
enableFormElements: function (form) {
form.find(web2py.enableSelector).each(function () {
var element = $(this),
method = element.is('button') ? 'html' : 'val';
if(element.data('w2p:enable-with')) element[method](element.data('w2p:enable-with'));
element.prop('disabled', false);
});
},
form_handlers: function() {
form_handlers: function () {
var el = $(document);
el.on('ajax:beforeSend', 'form[data-w2p_target]', function (e) {
web2py.disableFormElements($(this));
@@ -626,28 +635,28 @@
})(jQuery);
/* compatibility code - start */
ajax = $.web2py.ajax;
web2py_component = $.web2py.component;
web2py_websocket = $.web2py.websocket;
web2py_ajax_page = $.web2py.ajax_page;
ajax = jQuery.web2py.ajax;
web2py_component = jQuery.web2py.component;
web2py_websocket = jQuery.web2py.websocket;
web2py_ajax_page = jQuery.web2py.ajax_page;
//needed for IS_STRONG(entropy)
web2py_validate_entropy = $.web2py.validate_entropy;
web2py_validate_entropy = jQuery.web2py.validate_entropy;
//needed for crud.search and SQLFORM.grid's search
web2py_ajax_fields = $.web2py.ajax_fields;
web2py_ajax_fields = jQuery.web2py.ajax_fields;
//used for LOAD(ajax=False)
web2py_trap_form = $.web2py.trap_form;
web2py_trap_form = jQuery.web2py.trap_form;
/*undocumented - rare*/
popup = $.web2py.popup;
collapse = $.web2py.collapse;
fade = $.web2py.fade;
popup = jQuery.web2py.popup;
collapse = jQuery.web2py.collapse;
fade = jQuery.web2py.fade;
/* internals - shouldn't be needed
web2py_ajax_init = $.web2py.ajax_init;
web2py_event_handlers = $.web2py.event_handlers;
web2py_ajax_init = jQuery.web2py.ajax_init;
web2py_event_handlers = jQuery.web2py.event_handlers;
web2py_trap_link = $.web2py.trap_link;
web2py_calc_entropy = $.web2py.calc_entropy;
web2py_trap_link = jQuery.web2py.trap_link;
web2py_calc_entropy = jQuery.web2py.calc_entropy;
*/
/* compatibility code - end*/
+2 -2
View File
@@ -58,8 +58,8 @@
}}
<!-- uncomment here to load jquery-ui
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/base/jquery-ui.css" type="text/css" media="all" />
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/base/jquery-ui.css" type="text/css" media="all" />
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js" type="text/javascript"></script>
uncomment to load jquery-ui //-->
<noscript><link href="{{=URL('static', 'css/web2py_bootstrap_nojs.css')}}" rel="stylesheet" type="text/css" /></noscript>
{{block head}}{{end}}
+92
View File
@@ -81,6 +81,8 @@ _charsets.add(Charset(41, 'latin7', 'latin7_general_ci', 'Yes'))
_charsets.add(Charset(42, 'latin7', 'latin7_general_cs', ''))
_charsets.add(Charset(43, 'macce', 'macce_bin', ''))
_charsets.add(Charset(44, 'cp1250', 'cp1250_croatian_ci', ''))
_charsets.add(Charset(45, 'utf8mb4', 'utf8mb4_general_ci', 'Yes'))
_charsets.add(Charset(46, 'utf8mb4', 'utf8mb4_bin', ''))
_charsets.add(Charset(47, 'latin1', 'latin1_bin', ''))
_charsets.add(Charset(48, 'latin1', 'latin1_general_ci', ''))
_charsets.add(Charset(49, 'latin1', 'latin1_general_cs', ''))
@@ -88,9 +90,15 @@ _charsets.add(Charset(50, 'cp1251', 'cp1251_bin', ''))
_charsets.add(Charset(51, 'cp1251', 'cp1251_general_ci', 'Yes'))
_charsets.add(Charset(52, 'cp1251', 'cp1251_general_cs', ''))
_charsets.add(Charset(53, 'macroman', 'macroman_bin', ''))
_charsets.add(Charset(54, 'utf16', 'utf16_general_ci', 'Yes'))
_charsets.add(Charset(55, 'utf16', 'utf16_bin', ''))
_charsets.add(Charset(56, 'utf16le', 'utf16le_general_ci', 'Yes'))
_charsets.add(Charset(57, 'cp1256', 'cp1256_general_ci', 'Yes'))
_charsets.add(Charset(58, 'cp1257', 'cp1257_bin', ''))
_charsets.add(Charset(59, 'cp1257', 'cp1257_general_ci', 'Yes'))
_charsets.add(Charset(60, 'utf32', 'utf32_general_ci', 'Yes'))
_charsets.add(Charset(61, 'utf32', 'utf32_bin', ''))
_charsets.add(Charset(62, 'utf16le', 'utf16le_bin', ''))
_charsets.add(Charset(63, 'binary', 'binary', 'Yes'))
_charsets.add(Charset(64, 'armscii8', 'armscii8_bin', ''))
_charsets.add(Charset(65, 'ascii', 'ascii_bin', ''))
@@ -127,6 +135,30 @@ _charsets.add(Charset(96, 'cp932', 'cp932_bin', ''))
_charsets.add(Charset(97, 'eucjpms', 'eucjpms_japanese_ci', 'Yes'))
_charsets.add(Charset(98, 'eucjpms', 'eucjpms_bin', ''))
_charsets.add(Charset(99, 'cp1250', 'cp1250_polish_ci', ''))
_charsets.add(Charset(101, 'utf16', 'utf16_unicode_ci', ''))
_charsets.add(Charset(102, 'utf16', 'utf16_icelandic_ci', ''))
_charsets.add(Charset(103, 'utf16', 'utf16_latvian_ci', ''))
_charsets.add(Charset(104, 'utf16', 'utf16_romanian_ci', ''))
_charsets.add(Charset(105, 'utf16', 'utf16_slovenian_ci', ''))
_charsets.add(Charset(106, 'utf16', 'utf16_polish_ci', ''))
_charsets.add(Charset(107, 'utf16', 'utf16_estonian_ci', ''))
_charsets.add(Charset(108, 'utf16', 'utf16_spanish_ci', ''))
_charsets.add(Charset(109, 'utf16', 'utf16_swedish_ci', ''))
_charsets.add(Charset(110, 'utf16', 'utf16_turkish_ci', ''))
_charsets.add(Charset(111, 'utf16', 'utf16_czech_ci', ''))
_charsets.add(Charset(112, 'utf16', 'utf16_danish_ci', ''))
_charsets.add(Charset(113, 'utf16', 'utf16_lithuanian_ci', ''))
_charsets.add(Charset(114, 'utf16', 'utf16_slovak_ci', ''))
_charsets.add(Charset(115, 'utf16', 'utf16_spanish2_ci', ''))
_charsets.add(Charset(116, 'utf16', 'utf16_roman_ci', ''))
_charsets.add(Charset(117, 'utf16', 'utf16_persian_ci', ''))
_charsets.add(Charset(118, 'utf16', 'utf16_esperanto_ci', ''))
_charsets.add(Charset(119, 'utf16', 'utf16_hungarian_ci', ''))
_charsets.add(Charset(120, 'utf16', 'utf16_sinhala_ci', ''))
_charsets.add(Charset(121, 'utf16', 'utf16_german2_ci', ''))
_charsets.add(Charset(122, 'utf16', 'utf16_croatian_ci', ''))
_charsets.add(Charset(123, 'utf16', 'utf16_unicode_520_ci', ''))
_charsets.add(Charset(124, 'utf16', 'utf16_vietnamese_ci', ''))
_charsets.add(Charset(128, 'ucs2', 'ucs2_unicode_ci', ''))
_charsets.add(Charset(129, 'ucs2', 'ucs2_icelandic_ci', ''))
_charsets.add(Charset(130, 'ucs2', 'ucs2_latvian_ci', ''))
@@ -146,6 +178,36 @@ _charsets.add(Charset(143, 'ucs2', 'ucs2_roman_ci', ''))
_charsets.add(Charset(144, 'ucs2', 'ucs2_persian_ci', ''))
_charsets.add(Charset(145, 'ucs2', 'ucs2_esperanto_ci', ''))
_charsets.add(Charset(146, 'ucs2', 'ucs2_hungarian_ci', ''))
_charsets.add(Charset(147, 'ucs2', 'ucs2_sinhala_ci', ''))
_charsets.add(Charset(148, 'ucs2', 'ucs2_german2_ci', ''))
_charsets.add(Charset(149, 'ucs2', 'ucs2_croatian_ci', ''))
_charsets.add(Charset(150, 'ucs2', 'ucs2_unicode_520_ci', ''))
_charsets.add(Charset(151, 'ucs2', 'ucs2_vietnamese_ci', ''))
_charsets.add(Charset(159, 'ucs2', 'ucs2_general_mysql500_ci', ''))
_charsets.add(Charset(160, 'utf32', 'utf32_unicode_ci', ''))
_charsets.add(Charset(161, 'utf32', 'utf32_icelandic_ci', ''))
_charsets.add(Charset(162, 'utf32', 'utf32_latvian_ci', ''))
_charsets.add(Charset(163, 'utf32', 'utf32_romanian_ci', ''))
_charsets.add(Charset(164, 'utf32', 'utf32_slovenian_ci', ''))
_charsets.add(Charset(165, 'utf32', 'utf32_polish_ci', ''))
_charsets.add(Charset(166, 'utf32', 'utf32_estonian_ci', ''))
_charsets.add(Charset(167, 'utf32', 'utf32_spanish_ci', ''))
_charsets.add(Charset(168, 'utf32', 'utf32_swedish_ci', ''))
_charsets.add(Charset(169, 'utf32', 'utf32_turkish_ci', ''))
_charsets.add(Charset(170, 'utf32', 'utf32_czech_ci', ''))
_charsets.add(Charset(171, 'utf32', 'utf32_danish_ci', ''))
_charsets.add(Charset(172, 'utf32', 'utf32_lithuanian_ci', ''))
_charsets.add(Charset(173, 'utf32', 'utf32_slovak_ci', ''))
_charsets.add(Charset(174, 'utf32', 'utf32_spanish2_ci', ''))
_charsets.add(Charset(175, 'utf32', 'utf32_roman_ci', ''))
_charsets.add(Charset(176, 'utf32', 'utf32_persian_ci', ''))
_charsets.add(Charset(177, 'utf32', 'utf32_esperanto_ci', ''))
_charsets.add(Charset(178, 'utf32', 'utf32_hungarian_ci', ''))
_charsets.add(Charset(179, 'utf32', 'utf32_sinhala_ci', ''))
_charsets.add(Charset(180, 'utf32', 'utf32_german2_ci', ''))
_charsets.add(Charset(181, 'utf32', 'utf32_croatian_ci', ''))
_charsets.add(Charset(182, 'utf32', 'utf32_unicode_520_ci', ''))
_charsets.add(Charset(183, 'utf32', 'utf32_vietnamese_ci', ''))
_charsets.add(Charset(192, 'utf8', 'utf8_unicode_ci', ''))
_charsets.add(Charset(193, 'utf8', 'utf8_icelandic_ci', ''))
_charsets.add(Charset(194, 'utf8', 'utf8_latvian_ci', ''))
@@ -165,6 +227,36 @@ _charsets.add(Charset(207, 'utf8', 'utf8_roman_ci', ''))
_charsets.add(Charset(208, 'utf8', 'utf8_persian_ci', ''))
_charsets.add(Charset(209, 'utf8', 'utf8_esperanto_ci', ''))
_charsets.add(Charset(210, 'utf8', 'utf8_hungarian_ci', ''))
_charsets.add(Charset(211, 'utf8', 'utf8_sinhala_ci', ''))
_charsets.add(Charset(212, 'utf8', 'utf8_german2_ci', ''))
_charsets.add(Charset(213, 'utf8', 'utf8_croatian_ci', ''))
_charsets.add(Charset(214, 'utf8', 'utf8_unicode_520_ci', ''))
_charsets.add(Charset(215, 'utf8', 'utf8_vietnamese_ci', ''))
_charsets.add(Charset(223, 'utf8', 'utf8_general_mysql500_ci', ''))
_charsets.add(Charset(224, 'utf8mb4', 'utf8mb4_unicode_ci', ''))
_charsets.add(Charset(225, 'utf8mb4', 'utf8mb4_icelandic_ci', ''))
_charsets.add(Charset(226, 'utf8mb4', 'utf8mb4_latvian_ci', ''))
_charsets.add(Charset(227, 'utf8mb4', 'utf8mb4_romanian_ci', ''))
_charsets.add(Charset(228, 'utf8mb4', 'utf8mb4_slovenian_ci', ''))
_charsets.add(Charset(229, 'utf8mb4', 'utf8mb4_polish_ci', ''))
_charsets.add(Charset(230, 'utf8mb4', 'utf8mb4_estonian_ci', ''))
_charsets.add(Charset(231, 'utf8mb4', 'utf8mb4_spanish_ci', ''))
_charsets.add(Charset(232, 'utf8mb4', 'utf8mb4_swedish_ci', ''))
_charsets.add(Charset(233, 'utf8mb4', 'utf8mb4_turkish_ci', ''))
_charsets.add(Charset(234, 'utf8mb4', 'utf8mb4_czech_ci', ''))
_charsets.add(Charset(235, 'utf8mb4', 'utf8mb4_danish_ci', ''))
_charsets.add(Charset(236, 'utf8mb4', 'utf8mb4_lithuanian_ci', ''))
_charsets.add(Charset(237, 'utf8mb4', 'utf8mb4_slovak_ci', ''))
_charsets.add(Charset(238, 'utf8mb4', 'utf8mb4_spanish2_ci', ''))
_charsets.add(Charset(239, 'utf8mb4', 'utf8mb4_roman_ci', ''))
_charsets.add(Charset(240, 'utf8mb4', 'utf8mb4_persian_ci', ''))
_charsets.add(Charset(241, 'utf8mb4', 'utf8mb4_esperanto_ci', ''))
_charsets.add(Charset(242, 'utf8mb4', 'utf8mb4_hungarian_ci', ''))
_charsets.add(Charset(243, 'utf8mb4', 'utf8mb4_sinhala_ci', ''))
_charsets.add(Charset(244, 'utf8mb4', 'utf8mb4_german2_ci', ''))
_charsets.add(Charset(245, 'utf8mb4', 'utf8mb4_croatian_ci', ''))
_charsets.add(Charset(246, 'utf8mb4', 'utf8mb4_unicode_520_ci', ''))
_charsets.add(Charset(247, 'utf8mb4', 'utf8mb4_vietnamese_ci', ''))
def charset_by_name(name):
return _charsets.by_name(name)
+10 -12
View File
@@ -1857,7 +1857,7 @@ class BaseAdapter(ConnectionPool):
if isinstance(obj, datetime.datetime):
obj = obj.isoformat(self.T_SEP)[:19]
elif isinstance(obj, datetime.date):
obj = obj.isoformat()[:10]+' 00:00:00'
obj = obj.isoformat()[:10]+self.T_SEP+'00:00:00'
else:
obj = str(obj)
elif fieldtype == 'time':
@@ -6872,7 +6872,7 @@ class Row(object):
_extra = self.__dict__.get('_extra', None)
if _extra is not None:
v = _extra.get(key, None)
if v:
if v is not None:
return v
m = REGEX_TABLE_DOT_FIELD.match(key)
if m:
@@ -8307,8 +8307,9 @@ class Table(object):
field_type = self if same_db else 'bigint'
clones = []
for field in self:
nfk = same_db or not field.type.startswith('reference')
clones.append(field.clone(
unique=False, type=field.type if same_db else 'bigint'))
unique=False, type=field.type if nfk else 'bigint'))
archive_db.define_table(
archive_name, Field(current_record,field_type), *clones)
self._before_update.append(
@@ -8386,10 +8387,7 @@ class Table(object):
elif isinstance(key, dict):
""" for keyed table """
query = self._build_query(key)
rows = self._db(query).select()
if rows:
return rows[0]
return None
return self._db(query).select(limitby=(0,1), orderby_on_limitby=False).first()
elif str(key).isdigit() or 'google' in DRIVERS and isinstance(key, Key):
return self._db(self._id == key).select(limitby=(0,1), orderby_on_limitby=False).first()
elif key:
@@ -10308,7 +10306,7 @@ class Rows(object):
if i is None:
return (self.repr(i, fields=fields) for i in range(len(self)))
import sqlhtml
row = copy.copy(self.records[i])
row = copy.deepcopy(self.records[i])
keys = row.keys()
tables = [f.tablename for f in fields] if fields \
else [k for k in keys if k != '_extra']
@@ -10328,12 +10326,12 @@ class Rows(object):
def as_list(self,
compact=True,
storage_to_dict=True,
datetime_to_str=True,
datetime_to_str=False,
custom_types=None):
"""
returns the data as a list or dictionary.
:param storage_to_dict: when True returns a dict, otherwise a list(default True)
:param datetime_to_str: convert datetime fields as strings (default True)
:param datetime_to_str: convert datetime fields as strings (default False)
"""
(oc, self.compact) = (self.compact, compact)
if storage_to_dict:
@@ -10348,7 +10346,7 @@ class Rows(object):
key='id',
compact=True,
storage_to_dict=True,
datetime_to_str=True,
datetime_to_str=False,
custom_types=None):
"""
returns the data as a dictionary of dictionaries (storage_to_dict=True) or records (False)
@@ -10356,7 +10354,7 @@ class Rows(object):
:param key: the name of the field to be used as dict key, normally the id
:param compact: ? (default True)
:param storage_to_dict: when True returns a dict, otherwise a list(default True)
:param datetime_to_str: convert datetime fields as strings (default True)
:param datetime_to_str: convert datetime fields as strings (default False)
"""
# test for multiple rows
+4 -3
View File
@@ -506,7 +506,7 @@ class Session(Storage):
#check if session is separate
separate = None
if response.session_id[2:3] == "/":
if response.session and response.session_id[2:3] == "/":
separate = lambda session_name: session_name[-2:]
self._unlock(response)
@@ -589,8 +589,9 @@ class Session(Storage):
response.session_db_unique_key = unique_key
rcookies = response.cookies
rcookies[response.session_id_name] = response.session_id
rcookies[response.session_id_name]['path'] = '/'
if response.session_id_name:
rcookies[response.session_id_name] = response.session_id
rcookies[response.session_id_name]['path'] = '/'
if clear_session:
self.clear()
+1 -1
View File
@@ -333,7 +333,7 @@ def highlight(
== '_' and value])
if fa:
fa = ' ' + fa
return '<table%s><tr valign="top"><td style="width:40px; text-align: right;"><pre style="%s">%s</pre></td><td><pre style="%s">%s</pre></td></tr></table>'\
return '<table%s><tr style="vertical-align:top;"><td style="width:40px; text-align: right;"><pre style="%s">%s</pre></td><td><pre style="%s">%s</pre></td></tr></table>'\
% (fa, linenumbers_style, numbers, code_style, code)
+26 -7
View File
@@ -1198,12 +1198,12 @@ def TAG_pickler(data):
return (TAG_unpickler, (marshal_dump,))
class __tag__(DIV):
class __tag_div__(DIV):
def __init__(self,name,*a,**b):
DIV.__init__(self,*a,**b)
self.tag = name
copy_reg.pickle(__tag__, TAG_pickler, TAG_unpickler)
copy_reg.pickle(__tag_div__, TAG_pickler, TAG_unpickler)
class __TAG__(XmlComponent):
@@ -1223,7 +1223,7 @@ class __TAG__(XmlComponent):
name = name[:-1] + '/'
if isinstance(name, unicode):
name = name.encode('utf-8')
return lambda *a,**b: __tag__(name,*a,**b)
return lambda *a,**b: __tag_div__(name,*a,**b)
def __call__(self, html):
return web2pyHTMLParser(decoder.decoder(html)).tree
@@ -1481,9 +1481,13 @@ class A(DIV):
self.append(self['_href'])
if not self['_disable_with']:
self['_data-w2p_disable_with'] = 'default'
if self['callback'] and not self['_id']:
self['_id'] = web2py_uuid()
if self['delete']:
self['_data-w2p_remove'] = self['delete']
if self['target']:
if self['target'] == '<self>':
self['target'] = self['_id']
self['_data-w2p_target'] = self['target']
if self['component']:
self['_data-w2p_method'] = 'GET'
@@ -1636,12 +1640,27 @@ class TR(DIV):
self._wrap_components((TD, TH), TD)
class __TRHEAD__(DIV):
"""
__TRHEAD__ Component, internal only
If subcomponents are not TD/TH-components they will be wrapped in a TH
see also :class:`DIV`
"""
tag = 'tr'
def _fixup(self):
self._wrap_components((TD, TH), TH)
class THEAD(DIV):
tag = 'thead'
def _fixup(self):
self._wrap_components(TR, TR)
self._wrap_components((__TRHEAD__, TR), __TRHEAD__)
class TBODY(DIV):
@@ -2283,7 +2302,7 @@ class BEAUTIFY(DIV):
example::
>>> BEAUTIFY(['a', 'b', {'hello': 'world'}]).xml()
'<div><table><tr><td><div>a</div></td></tr><tr><td><div>b</div></td></tr><tr><td><div><table><tr><td style="font-weight:bold;vertical-align:top">hello</td><td valign="top">:</td><td><div>world</div></td></tr></table></div></td></tr></table></div>'
'<div><table><tr><td><div>a</div></td></tr><tr><td><div>b</div></td></tr><tr><td><div><table><tr><td style="font-weight:bold;vertical-align:top;">hello</td><td style="vertical-align:top;">:</td><td><div>world</div></td></tr></table></div></td></tr></table></div>'
turns any list, dictionary, etc into decent looking html.
Two special attributes are
@@ -2335,8 +2354,8 @@ class BEAUTIFY(DIV):
continue
rows.append(
TR(
TD(filtered_key, _style='font-weight:bold;vertical-align:top'),
TD(':', _valign='top'),
TD(filtered_key, _style='font-weight:bold;vertical-align:top;'),
TD(':', _style='vertical-align:top;'),
TD(BEAUTIFY(value, **attributes))))
components.append(TABLE(*rows, **attributes))
continue
+7 -1
View File
@@ -29,6 +29,7 @@ import tempfile
import random
import string
import urllib2
try:
import simplejson as sj #external installed library
except:
@@ -71,8 +72,13 @@ import logging.config
# This needed to prevent exception on Python 2.5:
# NameError: name 'gluon' is not defined
# See http://bugs.python.org/issue1436
# attention!, the import Tkinter in messageboxhandler, changes locale ...
import gluon.messageboxhandler
logging.gluon = gluon
# so we must restore it! Thanks ozancag
import locale
locale.setlocale(locale.LC_CTYPE, "C") # IMPORTANT, web2py requires locale "C"
exists = os.path.exists
pjoin = os.path.join
@@ -166,7 +172,7 @@ def copystream_progress(request, chunk_size=10 ** 5):
size = int(env.content_length)
except ValueError:
raise HTTP(400, "Invalid Content-Length header")
dest = tempfile.TemporaryFile()
dest = tempfile.NamedTemporaryFile()
if not 'X-Progress-ID' in request.vars:
copystream(source, dest, size, chunk_size)
return dest
+39 -12
View File
@@ -37,13 +37,15 @@ import datetime
import urllib
import re
import cStringIO
from gluon import current, redirect
from globals import current
from http import redirect
import inspect
import settings
is_gae = settings.global_settings.web2py_runtime_gae
try:
import settings
is_gae = settings.global_settings.web2py_runtime_gae
except ImportError:
is_gae = False # this is an assumption (if settings missing)
table_field = re.compile('[\w_]+\.[\w_]+')
widget_class = re.compile('^\w*')
@@ -773,7 +775,7 @@ def formstyle_bootstrap(form, fields):
_submit = False
if isinstance(controls, INPUT):
controls.add_class('input-xlarge')
controls.add_class('span4')
if controls['_type'] == 'submit':
# flag submit button
_submit = True
@@ -783,13 +785,13 @@ def formstyle_bootstrap(form, fields):
# For password fields, which are wrapped in a CAT object.
if isinstance(controls, CAT) and isinstance(controls[0], INPUT):
controls[0].add_class('input-xlarge')
controls[0].add_class('span4')
if isinstance(controls, SELECT):
controls.add_class('input-xlarge')
controls.add_class('span4')
if isinstance(controls, TEXTAREA):
controls.add_class('input-xlarge')
controls.add_class('span4')
if isinstance(label, LABEL):
label['_class'] = 'control-label'
@@ -2413,13 +2415,38 @@ class SQLFORM(FORM):
htmltable, _class='web2py_htmltable',
_style='width:100%;overflow-x:auto;-ms-overflow-x:scroll')
if selectable:
htmltable = FORM(htmltable, INPUT(
_type="submit", _value=T(selectable_submit_button)))
if not callable(selectable):
#now expect that selectable and related parameters are iterator (list, tuple, etc)
inputs = []
for i, submit_info in enumerate(selectable):
submit_text = submit_info[0]
submit_class = submit_info[2] if len(submit_info) > 2 else ''
input_ctrl = INPUT(_type="submit", _name='submit_%d' % i, _value=T(submit_text))
input_ctrl.add_class(submit_class)
inputs.append(input_ctrl)
else:
inputs = [INPUT(_type="submit", _value=T(selectable_submit_button))]
if formstyle == 'bootstrap':
# add space between buttons
#inputs = sum([[inp, ' '] for inp in inputs], [])[:-1]
htmltable = FORM(htmltable, DIV(_class='form-actions', *inputs))
else:
htmltable = FORM(htmltable, *inputs)
if htmltable.process(formname=formname).accepted:
htmltable.vars.records = htmltable.vars.records or []
htmltable.vars.records = htmltable.vars.records if type(htmltable.vars.records) == list else [htmltable.vars.records]
records = [int(r) for r in htmltable.vars.records]
selectable(records)
if not callable(selectable):
for i, submit_info in enumerate(selectable):
submit_callback = submit_info[1]
if htmltable.vars.get('submit_%d' % i, False):
submit_callback(records)
break
else:
selectable(records)
redirect(referrer)
else:
htmltable = DIV(T('No records found'))
-1
View File
@@ -178,7 +178,6 @@ class Messages(Settings):
return str(self.T(value))
return value
class FastStorage(dict):
"""
Eventually this should replace class Storage but causes memory leak
+2 -2
View File
@@ -800,8 +800,8 @@ class DummyResponse():
def write(self, data, escape=True):
if not escape:
self.body.write(str(data))
elif hasattr(data, 'as_html') and callable(data.as_html):
self.body.write(data.as_html())
elif hasattr(data, 'xml') and callable(data.xml):
self.body.write(data.xml())
else:
# make it a string
if not isinstance(data, (str, unicode)):
+4
View File
@@ -188,6 +188,10 @@ class TestBareHelpers(unittest.TestCase):
def testTHEAD(self):
self.assertEqual(THEAD('<>', _a='1', _b='2').xml(),
'<thead a="1" b="2"><tr><th>&lt;&gt;</th></tr></thead>')
#self.assertEqual(THEAD(TRHEAD('<>'), _a='1', _b='2').xml(),
# '<thead a="1" b="2"><tr><th>&lt;&gt;</th></tr></thead>')
self.assertEqual(THEAD(TR('<>'), _a='1', _b='2').xml(),
'<thead a="1" b="2"><tr><td>&lt;&gt;</td></tr></thead>')
def testTITLE(self):
+25 -22
View File
@@ -1116,7 +1116,7 @@ class Auth(object):
f=f, args=args, vars=vars, scheme=scheme)
def here(self):
return URL(args=current.request.args, vars=current.request.vars)
return current.request.env.request_uri
def __init__(self, environment=None, db=None, mailer=True,
hmac_key=None, controller='default', function='user',
@@ -1747,6 +1747,9 @@ class Auth(object):
else:
user_id = None # user unknown
vars = vars or {}
# log messages should not be translated
if type(descrption).__name__ == 'lazyT':
description = description.m
self.table_event().insert(
description=str(description % vars),
origin=origin, user_id=user_id)
@@ -2044,7 +2047,7 @@ class Auth(object):
if onaccept is DEFAULT:
onaccept = self.settings.login_onaccept
if log is DEFAULT:
log = self.messages.login_log
log = self.messages['login_log']
onfail = self.settings.login_onfail
@@ -2158,7 +2161,7 @@ class Auth(object):
form.vars, self.settings.update_fields)
break
if not user:
self.log_event(self.messages.login_failed_log,
self.log_event(self.messages['login_failed_log'],
request.post_vars)
# invalid login
session.flash = self.messages.invalid_login
@@ -2233,7 +2236,7 @@ class Auth(object):
if onlogout:
onlogout(self.user)
if log is DEFAULT:
log = self.messages.logout_log
log = self.messages['logout_log']
if self.user:
self.log_event(log, self.user)
if self.settings.login_form != self:
@@ -2278,7 +2281,7 @@ class Auth(object):
if onaccept is DEFAULT:
onaccept = self.settings.register_onaccept
if log is DEFAULT:
log = self.messages.register_log
log = self.messages['register_log']
table_user = self.table_user()
if self.settings.login_userfield:
@@ -2327,7 +2330,7 @@ class Auth(object):
if formstyle == 'bootstrap':
form.custom.widget.password_two[
'_class'] = 'input-xlarge'
'_class'] = 'span4'
addrow(
form, self.messages.verify_password +
@@ -2430,7 +2433,7 @@ class Auth(object):
if current.session.auth and current.session.auth.user:
current.session.auth.user.registration_key = user.registration_key
if log is DEFAULT:
log = self.messages.verify_email_log
log = self.messages['verify_email_log']
if next is DEFAULT:
next = self.settings.verify_email_next
if onaccept is DEFAULT:
@@ -2473,7 +2476,7 @@ class Auth(object):
if onaccept is DEFAULT:
onaccept = self.settings.retrieve_username_onaccept
if log is DEFAULT:
log = self.messages.retrieve_username_log
log = self.messages['retrieve_username_log']
old_requires = table_user.email.requires
table_user.email.requires = [IS_IN_DB(self.db, table_user.email,
error_message=self.messages.invalid_email)]
@@ -2555,7 +2558,7 @@ class Auth(object):
if onaccept is DEFAULT:
onaccept = self.settings.retrieve_password_onaccept
if log is DEFAULT:
log = self.messages.retrieve_password_log
log = self.messages['retrieve_password_log']
old_requires = table_user.email.requires
table_user.email.requires = [IS_IN_DB(self.db, table_user.email,
error_message=self.messages.invalid_email)]
@@ -2695,7 +2698,7 @@ class Auth(object):
if onaccept is DEFAULT:
onaccept = self.settings.reset_password_onaccept
if log is DEFAULT:
log = self.messages.reset_password_log
log = self.messages['reset_password_log']
table_user.email.requires = [
IS_EMAIL(error_message=self.messages.invalid_email),
IS_IN_DB(self.db, table_user.email,
@@ -2795,7 +2798,7 @@ class Auth(object):
if onaccept is DEFAULT:
onaccept = self.settings.change_password_onaccept
if log is DEFAULT:
log = self.messages.change_password_log
log = self.messages['change_password_log']
passfield = self.settings.password_field
form = SQLFORM.factory(
Field('old_password', 'password',
@@ -2864,7 +2867,7 @@ class Auth(object):
if onaccept is DEFAULT:
onaccept = self.settings.profile_onaccept
if log is DEFAULT:
log = self.messages.profile_log
log = self.messages['profile_log']
form = SQLFORM(
table_user,
self.user.id,
@@ -2930,7 +2933,7 @@ class Auth(object):
self.user = auth.user
self.update_groups()
onaccept = self.settings.login_onaccept
log = self.messages.impersonate_log
log = self.messages['impersonate_log']
self.log_event(log, dict(id=current_id, other_id=auth.user.id))
if onaccept:
form = Storage(dict(vars=self.user))
@@ -3086,7 +3089,7 @@ class Auth(object):
group_id = self.table_group().insert(
role=role, description=description)
self.log_event(self.messages.add_group_log,
self.log_event(self.messages['add_group_log'],
dict(group_id=group_id, role=role))
return group_id
@@ -3143,7 +3146,7 @@ class Auth(object):
r = True
else:
r = False
self.log_event(self.messages.has_membership_log,
self.log_event(self.messages['has_membership_log'],
dict(user_id=user_id, group_id=group_id, check=r))
return r
@@ -3167,7 +3170,7 @@ class Auth(object):
else:
id = membership.insert(group_id=group_id, user_id=user_id)
self.update_groups()
self.log_event(self.messages.add_membership_log,
self.log_event(self.messages['add_membership_log'],
dict(user_id=user_id, group_id=group_id))
return id
@@ -3181,7 +3184,7 @@ class Auth(object):
if not user_id and self.user:
user_id = self.user.id
membership = self.table_membership()
self.log_event(self.messages.del_membership_log,
self.log_event(self.messages['del_membership_log'],
dict(user_id=user_id, group_id=group_id))
ret = self.db(membership.user_id
== user_id)(membership.group_id
@@ -3237,7 +3240,7 @@ class Auth(object):
else:
r = False
if user_id:
self.log_event(self.messages.has_permission_log,
self.log_event(self.messages['has_permission_log'],
dict(user_id=user_id, name=name,
table_name=table_name, record_id=record_id))
return r
@@ -3264,7 +3267,7 @@ class Auth(object):
id = permission.insert(group_id=group_id, name=name,
table_name=str(table_name),
record_id=long(record_id))
self.log_event(self.messages.add_permission_log,
self.log_event(self.messages['add_permission_log'],
dict(permission_id=id, group_id=group_id,
name=name, table_name=table_name,
record_id=record_id))
@@ -3282,7 +3285,7 @@ class Auth(object):
"""
permission = self.table_permission()
self.log_event(self.messages.del_permission_log,
self.log_event(self.messages['del_permission_log'],
dict(group_id=group_id, name=name,
table_name=table_name, record_id=record_id))
return self.db(permission.group_id == group_id)(permission.name
@@ -3633,7 +3636,7 @@ class Crud(object):
if ondelete is DEFAULT:
ondelete = self.settings.update_ondelete
if log is DEFAULT:
log = self.messages.update_log
log = self.messages['update_log']
if deletable is DEFAULT:
deletable = self.settings.update_deletable
if message is DEFAULT:
@@ -3724,7 +3727,7 @@ class Crud(object):
if onaccept is DEFAULT:
onaccept = self.settings.create_onaccept
if log is DEFAULT:
log = self.messages.create_log
log = self.messages['create_log']
if message is DEFAULT:
message = self.messages.record_created
return self.update(
+2 -2
View File
@@ -2665,8 +2665,8 @@ class IS_EMPTY_OR(Validator):
if hasattr(other, 'options'):
self.options = self._options
def _options(self, zero=False):
options = self.other.options(zero=zero)
def _options(self):
options = self.other.options()
if (not options or options[0][0] != '') and not self.multiple:
options.insert(0, ('', ''))
return options
+10 -11
View File
@@ -29,15 +29,6 @@ from settings import global_settings
from shell import run, test
from utils import is_valid_ip_address, is_loopback_ip_address, getipaddrinfo
try:
import Tkinter
import tkMessageBox
import contrib.taskbar_widget
from winservice import register_service_handler, Web2pyService
have_winservice = True
except:
have_winservice = False
ProgramName = 'web2py Web Framework'
ProgramAuthor = 'Created by Massimo Di Pierro, Copyright 2007-' + str(
@@ -138,6 +129,7 @@ def start_browser(url, startup=False):
def presentation(root):
""" Draw the splash screen """
import Tkinter
root.withdraw()
@@ -194,6 +186,9 @@ class web2pyDialog(object):
def __init__(self, root, options):
""" web2pyDialog constructor """
import Tkinter
import tkMessageBox
root.title('web2py server')
self.root = Tkinter.Toplevel(root)
self.options = options
@@ -321,6 +316,7 @@ class web2pyDialog(object):
self.button_stop.configure(state='disabled')
if options.taskbar:
import contrib.taskbar_widget
self.tb = contrib.taskbar_widget.TaskBarIcon()
self.checkTaskBar()
@@ -460,6 +456,7 @@ class web2pyDialog(object):
def error(self, message):
""" Show error message """
import tkMessageBox
tkMessageBox.showerror('web2py start server', message)
def start(self):
@@ -1142,12 +1139,13 @@ def start(cron=True):
# ## if -W install/start/stop web2py as service
if options.winservice:
if os.name == 'nt':
if have_winservice:
try:
from winservice import register_service_handler, Web2pyService
register_service_handler(
argv=['', options.winservice],
opt_file=options.config,
cls=Web2pyService)
else:
except ImportError:
print 'Error: Missing python module winservice'
sys.exit(1)
else:
@@ -1188,6 +1186,7 @@ def start(cron=True):
logger.warn(
'GUI not available because Tk library is not installed')
havetk = False
options.nogui = True
if options.password == '<ask>' and havetk or options.taskbar and havetk:
try:
+3 -3
View File
@@ -43,19 +43,19 @@ echo 'server {
listen 80;
server_name $hostname;
###to enable correct use of response.static_version
#location ~* /(\w+)/static(?:/_[\d]+\.[\d]+\.[\d]+)?/(.*)$ {
#location ~* ^/(\w+)/static(?:/_[\d]+\.[\d]+\.[\d]+)?/(.*)$ {
# alias /home/www-data/web2py/applications/$1/static/$2;
# expires max;
#}
###
###if you use something like myapp = dict(languages=['en', 'it', 'jp'], default_language='en') in your routes.py
#location ~* /(\w+)/(en|it|jp)/static/(.*)$ {
#location ~* ^/(\w+)/(en|it|jp)/static/(.*)$ {
# alias /home/www-data/web2py/applications/$1/;
# try_files static/$2/$3 static/$3 =404;
#}
###
location ~* /(\w+)/static/ {
location ~* ^/(\w+)/static/ {
root /home/www-data/web2py/applications/;
#remove next comment on production
#expires max;