diff --git a/CHANGELOG b/CHANGELOG index 8a192c39..22f36fb1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,11 @@ ## 2.00.0 -- request.args(0,default=0, cast=int, url_onerror=URL(...)), thanks Anthony +- redirect(...,type='auto') will be handled properly in ajax responses +- experimental MongoDB support in DAL +- FORM.confirm('Confirm?',{'Back':URL(...)}) +- @auth.requires_login(otherwise=URL(...)) +- request.args(0,default=0, cast=int, otherwise=URL(...)), thanks Anthony +- better memcache support - generic.ics - generic.map - geodal and spatialite, thanks Denes and Fran @@ -11,6 +16,23 @@ - form.add_button(value,link) - db.table.insert(uploadfield=open(....)) - DAL BIGINT support and DAL(...,bigint_id=True) +- IS_IN_DB distinct +- more secure SQLFORM.grid and SQLFORM.smartgrid +- more export options in SQLFORM.grid and SQLFORM.smartgrid +- more secure admin against CSRF +- improved spreadsheet, thanks Alan +- routes in can redirect outside with routes_in=[('/path','303->http://..')] +- auth supports salt and compatible with third party data, thanks Dave Stoll +- CRYPT now defaults to pbkdf2(1000,20,sha1) +- experimental GIT integration +- experimental OpenShift deployment +- new makrmin with supports for nested lists, , , autolinks +- new interantionalization engine +- multi-language pluralization engine +- db.table.field.count(True) +- auth.wiki() +- new syntax BR()*5 +- gluon.cache.lazy_cache decorator - auth.settings.everybody_group_id - ace text web editor in admin - -E -b -L options for scheduler @@ -18,7 +40,6 @@ - ldap certificate support - pg8000 postgresql driver support - portable html.py -- to in markmin - new admin pages: manage_students, bulk_regsiter, and progress reports - @cache('%(name)s%(args)s%(vars)s',5) and cache.autokey - added tox.ini, thanks Marc @@ -36,6 +57,12 @@ - SQLFORM.grid(groupby=...') - db.table.field.filter_in, filter_out - allowed storage of uploads on any PyFileSystem (including amazon) +- new scheduler can now handle 10k tasks with 20 concurrent workers and no known issues (thanks to niphlod, ykessler, dhx, toomim) +- shceduler: tasks can be found in the environment (no need to define the tasks parameter) +- scheduler: max_empty_runs kills the workers automatically if no new tasks are found in queue (nice for "spikes" of processing power), discard_results to completely discard the results (if you don't need the output of the task), utc_time enables datetime calculations with UTC time, task_name is no longer required (filled automatically with function_name if found empty), uuid makes easy to coordinate scheduler_task maintenance (filled automatically if not provided), stop_time has no default (previously was today+1), retry_failed to requeue automatically failed tasks, sync_output refreshes automatically the output (nice to report percentages) +- scheduler tasks can be DISABLED (put to sleep and do nothing if not sending the heartbeat every 30 seconds), TERMINATE (complete the current task and then die), KILL (kill ASAP), EXPIRED (if stop_time passed) +- web2py.py -K myapp -X starts the myapp scheduler alongside the webserver + ## 1.99.5-1.99.7 - admin in Russian (Bulat), Japanese (Omi) and Slovenian (Robert Valentak) diff --git a/Makefile b/Makefile index cc599250..c433d751 100644 --- a/Makefile +++ b/Makefile @@ -43,11 +43,11 @@ src: rm -f applications/admin/uploads/* rm -f applications/welcome/uploads/* rm -f applications/examples/uploads/* - ### make admin layout and appadmin the default - cp applications/admin/views/appadmin.html applications/welcome/views - cp applications/admin/views/appadmin.html applications/examples/views - cp applications/admin/controllers/appadmin.py applications/welcome/controllers - cp applications/admin/controllers/appadmin.py applications/examples/controllers + ### make welcome layout and appadmin the default + cp applications/welcome/views/appadmin.html applications/admin/views + cp applications/welcome/views/appadmin.html applications/examples/views + cp applications/welcome/controllers/appadmin.py applications/admin/controllers + cp applications/welcome/controllers/appadmin.py applications/examples/controllers ### build web2py_src.zip echo '' > NEWINSTALL mv web2py_src.zip web2py_src_old.zip | echo 'no old' diff --git a/VERSION b/VERSION index 3159a75d..9b37dbd4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-07-27 09:32:24) dev +Version 2.00.0 (2012-08-18 16:21:48) dev diff --git a/__init__.py b/__init__.py index 6fb66a5e..12a6f48e 100644 --- a/__init__.py +++ b/__init__.py @@ -4,3 +4,5 @@ + + diff --git a/anyserver.py b/anyserver.py index bd2fc39e..3d6c929c 100644 --- a/anyserver.py +++ b/anyserver.py @@ -128,13 +128,14 @@ class Servers: from gunicorn.app.base import Application config = {'bind': "%s:%d" % address} config.update(options) + sys.argv = ['anyserver.py'] class GunicornApplication(Application): - def init(self, parser, opts, args): + def init(self, parser, opts, args): return config def load(self): return app g = GunicornApplication() - g.run() + g.run() @staticmethod def eventlet(app,address, **options): @@ -307,3 +308,4 @@ if __name__=='__main__': + diff --git a/appengine_config.py b/appengine_config.py index 323f7a2b..33916e4d 100644 --- a/appengine_config.py +++ b/appengine_config.py @@ -5,3 +5,4 @@ def webapp_add_wsgi_middleware(app): + diff --git a/applications/admin/controllers/appadmin.py b/applications/admin/controllers/appadmin.py index b8eccf9e..71ff7876 100644 --- a/applications/admin/controllers/appadmin.py +++ b/applications/admin/controllers/appadmin.py @@ -199,17 +199,8 @@ def select(): _class='delete', _type='checkbox', value=False), ''), TR('', '', INPUT(_type='submit', _value=T('submit')))), _action=URL(r=request,args=request.args)) - if request.vars.csvfile != None: - try: - import_csv(db[request.vars.table], - request.vars.csvfile.file) - response.flash = T('data uploaded') - except Exception, e: - response.flash = DIV(T('unable to parse csv file'),PRE(str(e))) if form.accepts(request.vars, formname=None): -# regex = re.compile(request.args[0] + '\.(?P\w+)\.id\>0') regex = re.compile(request.args[0] + '\.(?P
\w+)\..+') - match = regex.match(form.vars.query.strip()) if match: table = match.group('table') @@ -230,6 +221,23 @@ def select(): except Exception, e: (rows, nrows) = ([], 0) response.flash = DIV(T('Invalid Query'),PRE(str(e))) + # begin handle upload csv + if table: + formcsv = FORM(str(T('or import from csv file'))+" ", + INPUT(_type='file',_name='csvfile'), + INPUT(_type='hidden',_value=table,_name='table'), + INPUT(_type='submit',_value=T('import'))) + else: + formcsv = None + if formcsv and formcsv.process().accepted and request.vars.csvfile: + try: + import_csv(db[request.vars.table], + request.vars.csvfile.file) + response.flash = T('data uploaded') + except Exception, e: + response.flash = DIV(T('unable to parse csv file'),PRE(str(e))) + # end handle upload csv + return dict( form=form, table=table, @@ -238,6 +246,7 @@ def select(): nrows=nrows, rows=rows, query=request.vars.query, + formcsv = formcsv, ) diff --git a/applications/admin/controllers/default.py b/applications/admin/controllers/default.py index 341f1ddc..f6566500 100644 --- a/applications/admin/controllers/default.py +++ b/applications/admin/controllers/default.py @@ -11,6 +11,7 @@ if EXPERIMENTAL_STUFF: import re from gluon.admin import * from gluon.fileutils import abspath, read_file, write_file +from gluon.utils import web2py_uuid from glob import glob import shutil import platform @@ -40,6 +41,9 @@ if FILTER_APPS and request.args(0) and not request.args(0) in FILTER_APPS: session.flash = T('disabled in demo mode') redirect(URL('site')) + +if not session.token: session.token = web2py_uuid() + def count_lines(data): return len([line for line in data.split('\n') if line.strip() and not line.startswith('#')]) @@ -167,6 +171,7 @@ def change_password(): redirect(URL('site')) return dict(form=form) + def site(): """ Site handler """ @@ -175,12 +180,32 @@ def site(): # Shortcut to make the elif statements more legible file_or_appurl = 'file' in request.vars or 'appurl' in request.vars + class IS_VALID_APPNAME(object): + def __call__(self,value): + if not re.compile('\w+').match(value): + return (value,T('Invalid application name')) + if not request.vars.overwrite and \ + os.path.exists(os.path.join(apath(r=request),value)): + return (value,T('Application exists already')) + return (value,None) + + is_appname = IS_VALID_APPNAME() + form_create = SQLFORM.factory(Field('name',requires=is_appname), + table_name='appcreate') + form_update = SQLFORM.factory(Field('name',requires=is_appname), + Field('file','upload',uploadfield=False), + Field('url'), + Field('overwrite','boolean'), + table_name='appupdate') + form_create.process() + form_update.process() + if DEMO_MODE: pass - elif request.vars.filename and not 'file' in request.vars: + elif form_create.accepted: # create a new application - appname = cleanpath(request.vars.filename).replace('.', '_') + appname = cleanpath(form_create.vars.name) if app_create(appname, request): if MULTI_USER_MODE: db.app.insert(name=appname,owner=auth.user.id) @@ -189,49 +214,44 @@ def site(): redirect(URL('design',args=appname)) else: session.flash = \ - T('unable to create application "%s" (it may exist already)', request.vars.filename) + T('unable to create application "%s" (it may exist already)', + form_create.vars.name) redirect(URL(r=request)) - elif file_or_appurl and not request.vars.filename: - # can't do anything without an app name - msg = 'you must specify a name for the uploaded application' - response.flash = T(msg) - - elif (request.vars.appurl or '').endswith('.git') and request.vars.filename: - if not have_git: - session.flash = GIT_MISSING - elif request.vars.filename: - target = os.path.join(apath(r=request),request.vars.filename) - if os.path.exists(target): - session.flash = 'Application by that name already exists.' - else: - try: - new_repo = Repo.clone_from(request.vars.appurl,target) - session.flash = T('new application "%s" imported',request.vars.filename) - except GitCommandError, err: - session.flash = T('Invalid git repository specified.') - else: - session.flash = 'Application Name required for git import.' - redirect(URL(r=request)) - - elif file_or_appurl and request.vars.filename: - # fetch an application via URL or file upload - f = None - if request.vars.appurl: + elif form_update.accepted: + if (form_update.vars.url or '').endswith('.git'): + if not have_git: + session.flash = GIT_MISSING + target = os.path.join(apath(r=request),form_update.vars.name) try: - f = urllib.urlopen(request.vars.appurl) - except Exception, e: - session.flash = DIV(T('Unable to download app because:'),PRE(str(e))) - redirect(URL(r=request)) - fname = request.vars.appurl - elif request.vars.file: - f = request.vars.file.file - fname = request.vars.file.filename + new_repo = Repo.clone_from(form_update.vars.url,target) + session.flash = T('new application "%s" imported', + form_update.vars.name) + except GitCommandError, err: + session.flash = T('Invalid git repository specified.') + redirect(URL(r=request)) + elif form_update.vars.url: + # fetch an application via URL or file upload + try: + f = urllib.urlopen(form_update.vars.url) + if f.code == 404: + raise Exception("404 file not found") + except Exception, e: + session.flash = \ + DIV(T('Unable to download app because:'),PRE(str(e))) + redirect(URL(r=request)) + fname = form_update.vars.url + + elif form_update.accepted and form_update.vars.file: + fname = request.vars.file.filename + f = request.vars.file.file + if f: - appname = cleanpath(request.vars.filename).replace('.', '_') - installed = app_install(appname, f, request, fname, - overwrite=request.vars.overwrite_check) + appname = cleanpath(form_update.vars.name) + installed = app_install(appname, f, + request, fname, + overwrite=form_update.vars.overwrite) if f and installed: msg = 'application %(appname)s installed with md5sum: %(digest)s' if MULTI_USER_MODE: @@ -239,14 +259,12 @@ def site(): log_progress(appname) session.flash = T(msg, dict(appname=appname, digest=md5_hash(installed))) - elif f and request.vars.overwrite_check: + elif f and form_update.vars.overwrite: msg = 'unable to install application "%(appname)s"' - session.flash = T(msg, dict(appname=request.vars.filename)) - + session.flash = T(msg, dict(appname=form_update.vars.name)) else: msg = 'unable to install application "%(appname)s"' - session.flash = T(msg, dict(appname=request.vars.filename)) - + session.flash = T(msg, dict(appname=form_update.vars.name)) redirect(URL(r=request)) regex = re.compile('^\w+$') @@ -261,7 +279,8 @@ def site(): apps = sorted(apps,lambda a,b:cmp(a.upper(),b.upper())) - return dict(app=None, apps=apps, myversion=myversion) + return dict(app=None, apps=apps, myversion=myversion, + form_create=form_create, form_update=form_update) def report_progress(app): @@ -317,20 +336,24 @@ def pack_plugin(): redirect(URL('plugin',args=request.args)) def upgrade_web2py(): - if 'upgrade' in request.vars: + dialog = FORM.confim(T('Upgrade'), + {T('Cancel'):URL('site')}) + if dialog.accepted: (success, error) = upgrade(request) if success: session.flash = T('web2py upgraded; please restart it') else: session.flash = T('unable to upgrade because "%s"', error) redirect(URL('site')) - elif 'noupgrade' in request.vars: - redirect(URL('site')) - return dict() + return dict(dialog=dialog) def uninstall(): app = get_app() - if 'delete' in request.vars: + + dialog = FORM.confim(T('Uninstall'), + {T('Cancel'):URL('site')}) + + if dialog.accepted: if MULTI_USER_MODE: if is_manager() and db(db.app.name==app).delete(): pass @@ -344,9 +367,7 @@ def uninstall(): else: session.flash = T('unable to uninstall "%s"', app) redirect(URL('site')) - elif 'nodelete' in request.vars: - redirect(URL('site')) - return dict(app=app) + return dict(app=app, dialog=dialog) def cleanup(): @@ -412,7 +433,7 @@ def delete(): if isinstance(sender, list): # ## fix a problem with Vista sender = sender[0] - dialog = FORM.dialog(T('Delete'), + dialog = FORM.confim(T('Delete'), {T('Cancel'):URL(sender, anchor=request.vars.id)}) if dialog.accepted: @@ -846,6 +867,9 @@ def design(): msg = T('ATTENTION: you cannot edit the running application!') response.flash = msg + if request.vars and not request.vars.token==session.token: + redirect(URL('logout')) + if request.vars.pluginfile!=None and not isinstance(request.vars.pluginfile,str): filename=os.path.basename(request.vars.pluginfile.filename) if plugin_install(app, request.vars.pluginfile.file, @@ -978,9 +1002,12 @@ def delete_plugin(): app=request.args(0) plugin = request.args(1) plugin_name='plugin_'+plugin - if 'nodelete' in request.vars: - redirect(URL('design', args=app, anchor=request.vars.id)) - elif 'delete' in request.vars: + + dialog = FORM.confim( + T('Delete'), + {T('Cancel'):URL('design', args=app)}) + + if dialog.accepted: try: for folder in ['models','views','controllers','static','modules', 'private']: path=os.path.join(apath(app,r=request),folder) @@ -997,7 +1024,7 @@ def delete_plugin(): session.flash = T('unable to delete file plugin "%(plugin)s"', dict(plugin=plugin)) redirect(URL('design', args=request.args(0), anchor=request.vars.id2)) - return dict(plugin=plugin) + return dict(dialog=dialog,plugin=plugin) def plugin(): """ Application design handler """ @@ -1094,6 +1121,8 @@ def plugin(): def create_file(): """ Create files handler """ + if request.vars and not request.vars.token==session.token: + redirect(URL('logout')) try: anchor='#'+request.vars.id if request.vars.id else '' if request.vars.app: @@ -1241,6 +1270,8 @@ def create_file(): def upload_file(): """ File uploading handler """ + if request.vars and not request.vars.token==session.token: + redirect(URL('logout')) try: filename = None app = get_app(name=request.vars.location.split('/')[0]) @@ -1586,7 +1617,6 @@ def reload_routes(): gluon.rewrite.load() redirect(URL('site')) - def manage_students(): if not (MULTI_USER_MODE and is_manager()): session.flash = T('Not Authorized') @@ -1621,7 +1651,9 @@ def git_pull(): if not have_git: session.flash = GIT_MISSING redirect(URL('site')) - if 'pull' in request.vars: + dialog = FORM.confim(T('Pull'), + {T('Cancel'):URL('site')}) + if dialog.accepted: try: repo = Repo(os.path.join(apath(r=request),app)) origin = repo.remotes.origin @@ -1649,7 +1681,7 @@ def git_pull(): redirect(URL('site')) elif 'cancel' in request.vars: redirect(URL('site')) - return dict(app=app) + return dict(app=app,dialog=dialog) def git_push(): @@ -1666,8 +1698,7 @@ def git_push(): try: repo = Repo(os.path.join(apath(r=request),app)) index = repo.index - os.chdir(os.path.join(apath(r=request),app)) - index.add('*') + index.add([apath(r=request)+app+'/*']) new_commit = index.commit(form.vars.changelog) origin = repo.remotes.origin origin.push() @@ -1680,6 +1711,5 @@ def git_push(): logging.error("Unexpected error:", sys.exc_info()[0]) session.flash = T("Push failed, git exited abnormally. See logs for details.") redirect(URL('site')) - os.chdir(apath(r=request)) return dict(app=app,form=form) diff --git a/applications/admin/controllers/wizard.py b/applications/admin/controllers/wizard.py index 8de9dc1a..ca60ecdd 100644 --- a/applications/admin/controllers/wizard.py +++ b/applications/admin/controllers/wizard.py @@ -139,7 +139,7 @@ def step2(): if not name in session.app['pages']: session.app['pages'].append(name) session.app['page_'+name] = \ - '## Manage %s\n{{=form}}' % (table) + '## Manage %s\n\n{{=form}}' % (table) if session.app['tables']: redirect(URL('step3',args=0)) else: @@ -248,8 +248,11 @@ def sort_tables(tables): def append(table,trail=[]): if table in trail: raise RuntimeError - for t in d[table]: append(t,trail=trail+[table]) - if not table in tables: tables.append(table) + for t in d[table]: + # if not t==table: (problem, no dropdown for self references) + append(t,trail=trail+[table]) + if not table in tables: + tables.append(table) for table in d: append(table) return tables @@ -351,7 +354,7 @@ def make_table(table,fields): s+=""" db.auth_user.first_name.requires = IS_NOT_EMPTY(error_message=auth.messages.is_empty) db.auth_user.last_name.requires = IS_NOT_EMPTY(error_message=auth.messages.is_empty) -db.auth_user.password.requires = CRYPT(key=auth.settings.hmac_key) +db.auth_user.password.requires = CRYPT(key=auth.settings.hmac_key, min_length=4) db.auth_user.username.requires = IS_NOT_IN_DB(db, db.auth_user.username) db.auth_user.email.requires = (IS_EMAIL(error_message=auth.messages.invalid_email), IS_NOT_IN_DB(db, db.auth_user.email)) diff --git a/applications/admin/languages/de.py b/applications/admin/languages/de.py index 4a9e7212..eddd03c8 100644 --- a/applications/admin/languages/de.py +++ b/applications/admin/languages/de.py @@ -3,198 +3,28 @@ '!langcode!': 'de', '!langname!': 'Deutsch', '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"Update" ist ein optionaler Ausdruck wie "Feld1 = \'newvalue". JOIN Ergebnisse können nicht aktualisiert oder gelöscht werden', -'%Y-%m-%d': '%Y-%m-%d', -'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S', '%s %%{row} deleted': '%s Zeilen gelöscht', '%s %%{row} updated': '%s Zeilen aktualisiert', +'%Y-%m-%d': '%Y-%m-%d', +'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S', '(requires internet access)': '(requires internet access)', '(something like "it-it")': '(so etwas wie "it-it")', '@markmin\x01Searching: **%s** %%{file}': 'Searching: **%s** files', 'A new version of web2py is available': 'Eine neue Version von web2py ist verfügbar', 'A new version of web2py is available: %s': 'Eine neue Version von web2py ist verfügbar: %s', -'A new version of web2py is available: Version 1.85.3 (2010-09-18 07:07:46)\n': 'Eine neue Version von web2py ist verfügbar: Version 1.85.3 (2010-09-18 07:07:46)\n', -'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'ACHTUNG: Die Einwahl benötigt eine sichere (HTTPS) Verbindung. Es sei denn sie läuft Lokal(localhost).', -'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ACHTUNG: Testen ist nicht threadsicher. Führen sie also nicht mehrere Tests gleichzeitig aus.', -'ATTENTION: This is an experimental feature and it needs more testing.': 'ACHTUNG: Dies ist eine experimentelle Funktion und benötigt noch weitere Tests.', -'ATTENTION: you cannot edit the running application!': 'ACHTUNG: Eine laufende Anwendung kann nicht editiert werden!', 'Abort': 'Abbrechen', 'About': 'Über', 'About application': 'Über die Anwendung', 'Additional code for your application': 'Additional code for your application', -'Admin is disabled because insecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals', -'Admin is disabled because unsecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals', -'Admin language': 'Admin language', -'Administrator Password:': 'Administrator Passwort:', -'Application name:': 'Application name:', -'Are you sure you want to delete file "%s"?': 'Sind Sie sich sicher, dass Sie diese Datei löschen wollen "%s"?', -'Are you sure you want to uninstall application "%s"': 'Sind Sie sich sicher, dass Sie diese Anwendung deinstallieren wollen "%s"', -'Are you sure you want to uninstall application "%s"?': 'Sind Sie sich sicher, dass Sie diese Anwendung deinstallieren wollen "%s"?', -'Are you sure you want to upgrade web2py now?': 'Sind Sie sich sicher, dass Sie web2py jetzt upgraden möchten?', -'Authentication': 'Authentifizierung', -'Available databases and tables': 'Verfügbare Datenbanken und Tabellen', -'Cannot be empty': 'Darf nicht leer sein', -'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'Nicht Kompilierbar:Es sind Fehler in der Anwendung. Beseitigen Sie die Fehler und versuchen Sie es erneut.', -'Change Password': 'Passwort ändern', -'Change admin password': 'Administrator-Passwort ändern', -'Check for upgrades': 'check for upgrades', -'Check to delete': 'Markiere zum löschen', -'Checking for upgrades...': 'Auf Updates überprüfen...', -'Clean': 'löschen', -'Client IP': 'Client IP', -'Compile': 'kompilieren', -'Controller': 'Controller', -'Controllers': 'Controller', -'Copyright': 'Urheberrecht', -'Create': 'erstellen', -'Create new simple application': 'Erzeuge neue Anwendung', -'Current request': 'Aktuelle Anfrage (request)', -'Current response': 'Aktuelle Antwort (response)', -'Current session': 'Aktuelle Sitzung (session)', -'DB Model': 'DB Modell', -'DESIGN': 'design', -'Database': 'Datenbank', -'Date and Time': 'Datum und Uhrzeit', -'Delete': 'Löschen', -'Delete:': 'Löschen:', -'Deploy': 'deploy', -'Deploy on Google App Engine': 'Auf Google App Engine installieren', -'Description': 'Beschreibung', -'Design for': 'Design für', -'E-mail': 'E-mail', -'EDIT': 'BEARBEITEN', -'Edit': 'bearbeiten', -'Edit Profile': 'Bearbeite Profil', -'Edit This App': 'Bearbeite diese Anwendung', -'Edit application': 'Bearbeite Anwendung', -'Edit current record': 'Bearbeite aktuellen Datensatz', -'Editing Language file': 'Sprachdatei bearbeiten', -'Editing file': 'Bearbeite Datei', -'Editing file "%s"': 'Bearbeite Datei "%s"', -'Enterprise Web Framework': 'Enterprise Web Framework', -'Error logs for "%(app)s"': 'Fehlerprotokoll für "%(app)s"', -'Errors': 'Fehler', -'Exception instance attributes': 'Atribute der Ausnahmeinstanz', -'Expand Abbreviation': 'Kürzel erweitern', -'First name': 'Vorname', -'Functions with no doctests will result in [passed] tests.': 'Funktionen ohne doctests erzeugen [passed] in Tests', -'Go to Matching Pair': 'gehe zum übereinstimmenden Paar', -'Group ID': 'Gruppen ID', -'Hello World': 'Hallo Welt', -'Help': 'Hilfe', -'If the report above contains a ticket number it indicates a failure in executing the controller, before any attempt to execute the doctests. This is usually due to an indentation error or an error outside function code.\nA green title indicates that all tests (if defined) passed. In this case test results are not shown.': 'Falls der obere Test eine Fehler-Ticketnummer enthält deutet das auf einen Fehler in der Ausführung des Controllers hin, noch bevor der Doctest ausgeführt werden konnte. Gewöhnlich führen fehlerhafte Einrückungen oder fehlerhafter Code ausserhalb der Funktion zu solchen Fehlern. Ein grüner Titel deutet darauf hin, dass alle Test(wenn sie vorhanden sind) erfolgreich durchlaufen wurden. In diesem Fall werden die Testresultate nicht angezeigt.', -'If you answer "yes", be patient, it may take a while to download': '', -'If you answer yes, be patient, it may take a while to download': 'If you answer yes, be patient, it may take a while to download', -'Import/Export': 'Importieren/Exportieren', -'Index': 'Index', -'Install': 'installieren', -'Installed applications': 'Installierte Anwendungen', -'Internal State': 'interner Status', -'Invalid Query': 'Ungültige Abfrage', -'Invalid action': 'Ungültige Aktion', -'Invalid email': 'Ungültige Email', -'Key bindings': 'Tastenbelegungen', -'Key bindings for ZenConding Plugin': 'Tastenbelegungen für das ZenConding Plugin', -'Language files (static strings) updated': 'Sprachdatei (statisch Strings) aktualisiert', -'Languages': 'Sprachen', -'Last name': 'Nachname', -'Last saved on:': 'Zuletzt gespeichert am:', -'Layout': 'Layout', -'License for': 'Lizenz für', -'Login': 'Anmelden', -'Login to the Administrative Interface': 'An das Administrations-Interface anmelden', -'Logout': 'abmelden', -'Lost Password': 'Passwort vergessen', -'Main Menu': 'Menú principal', -'Match Pair': 'Paare finden', -'Menu Model': 'Menü Modell', -'Merge Lines': 'Zeilen zusammenfügen', -'Models': 'Modelle', -'Modules': 'Module', -'NO': 'NEIN', -'Name': 'Name', -'New Record': 'Neuer Datensatz', -'New application wizard': 'New application wizard', -'New simple application': 'New simple application', -'Next Edit Point': 'nächster Bearbeitungsschritt', -'No databases in this application': 'Keine Datenbank in dieser Anwendung', -'Origin': 'Herkunft', -'Original/Translation': 'Original/Übersetzung', -'Overwrite installed app': 'installierte Anwendungen überschreiben', -'Pack all': 'verpacke alles', -'Pack compiled': 'Verpacke kompiliert', -'Password': 'Passwort', -'Peeking at file': 'Dateiansicht', -'Plugin "%s" in application': 'Plugin "%s" in Anwendung', -'Plugins': 'Plugins', -'Powered by': 'Unterstützt von', -'Previous Edit Point': 'vorheriger Bearbeitungsschritt', -'Query:': 'Abfrage:', -'Record ID': 'Datensatz ID', -'Register': 'registrieren', -'Registration key': 'Registrierungsschlüssel', -'Remove compiled': 'kompilat gelöscht', -'Reset Password key': 'Passwortschlüssel zurücksetzen', -'Resolve Conflict file': 'bereinige Konflikt-Datei', -'Role': 'Rolle', -'Rows in table': 'Zeilen in Tabelle', -'Rows selected': 'Zeilen ausgewählt', -'Save via Ajax': 'via Ajax sichern', -'Saved file hash:': 'Gespeicherter Datei-Hash:', -'Site': 'Seite', -'Start wizard': 'start wizard', -'Static files': 'statische Dateien', -'Stylesheet': 'Stylesheet', -'Sure you want to delete this object?': 'Wollen Sie das Objekt wirklich löschen?', -'TM': 'TM', -'Table name': 'Tabellen Name', -'Testing application': 'Teste die Anwendung', -'Testing controller': 'teste Controller', -'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'Die "query" ist eine Bedingung wie "db.table1.field1 == \'Wert\'". Etwas wie "db.table1.field1 db.table2.field2 ==" führt zu einem SQL JOIN.', -'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': 'The data representation, define database tables and sets', -'The output of the file is a dictionary that was rendered by the view': 'The output of the file is a dictionary that was rendered by the view', -'The presentations layer, views are also known as templates': 'The presentations layer, views are also known as templates', -'There are no controllers': 'Keine Controller vorhanden', -'There are no models': 'Keine Modelle vorhanden', -'There are no modules': 'Keine Module vorhanden', -'There are no plugins': 'There are no plugins', -'There are no static files': 'Keine statischen Dateien vorhanden', -'There are no translators, only default language is supported': 'Keine Übersetzungen vorhanden, nur die voreingestellte Sprache wird unterstützt', -'There are no views': 'Keine Views vorhanden', -'These files are served without processing, your images go here': 'These files are served without processing, your images go here', -'This is a copy of the scaffolding application': 'Dies ist eine Kopie einer Grundgerüst-Anwendung', -'This is the %(filename)s template': 'Dies ist das Template %(filename)s', -'Ticket': 'Ticket', -'Timestamp': 'Timestamp', -'To create a plugin, name a file/folder plugin_[name]': 'Um ein Plugin zu erstellen benennen Sie eine(n) Datei/Ordner plugin_[Name]', -'Translation strings for the application': 'Translation strings for the application', -'Unable to check for upgrades': 'überprüfen von Upgrades nicht möglich', -'Unable to download': 'herunterladen nicht möglich', -'Unable to download app': 'herunterladen der Anwendung nicht möglich', -'Uninstall': 'deinstallieren', -'Update:': 'Aktualisiere:', -'Upload & install packed application': 'Verpackte Anwendung hochladen und installieren', -'Upload a package:': 'Upload a package:', -'Upload existing application': 'lade existierende Anwendung hoch', -'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Benutze (...)&(...) für AND, (...)|(...) für OR, und ~(...) für NOT, um komplexe Abfragen zu erstellen.', -'Use an url:': 'Use an url:', -'User ID': 'Benutzer ID', -'Version': 'Version', -'View': 'View', -'Views': 'Views', -'Welcome %s': 'Willkommen %s', -'Welcome to web2py': 'Willkommen zu web2py', -'Which called the function': 'Which called the function', -'Wrap with Abbreviation': 'mit Kürzel einhüllen', -'YES': 'JA', -'You are successfully running web2py': 'web2by wird erfolgreich ausgeführt', -'You can modify this application and adapt it to your needs': 'Sie können diese Anwendung verändern und Ihren Bedürfnissen anpassen', -'You visited the url': 'Sie besuchten die URL', 'additional code for your application': 'zusätzlicher Code für Ihre Anwendung', 'admin disabled because no admin password': ' admin ist deaktiviert, weil kein Admin-Passwort gesetzt ist', 'admin disabled because not supported on google apps engine': 'admin ist deaktiviert, es existiert dafür keine Unterstützung auf der google apps engine', 'admin disabled because unable to access password file': 'admin ist deaktiviert, weil kein Zugriff auf die Passwortdatei besteht', +'Admin is disabled because insecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals', +'Admin is disabled because unsecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals', +'Admin language': 'Admin language', 'administrative interface': 'administrative interface', +'Administrator Password:': 'Administrator Passwort:', 'and rename it (required):': 'und benenne sie um (erforderlich):', 'and rename it:': ' und benenne sie um:', 'appadmin': 'appadmin', @@ -202,49 +32,108 @@ 'application "%s" uninstalled': 'Anwendung "%s" deinstalliert', 'application compiled': 'Anwendung kompiliert', 'application is compiled and cannot be designed': 'Die Anwendung ist kompiliert kann deswegen nicht mehr geändert werden', +'Application name:': 'Application name:', +'Are you sure you want to delete file "%s"?': 'Sind Sie sich sicher, dass Sie diese Datei löschen wollen "%s"?', +'Are you sure you want to delete this object?': 'Are you sure you want to delete this object?', +'Are you sure you want to uninstall application "%s"': 'Sind Sie sich sicher, dass Sie diese Anwendung deinstallieren wollen "%s"', +'Are you sure you want to uninstall application "%s"?': 'Sind Sie sich sicher, dass Sie diese Anwendung deinstallieren wollen "%s"?', +'Are you sure you want to upgrade web2py now?': 'Sind Sie sich sicher, dass Sie web2py jetzt upgraden möchten?', 'arguments': 'arguments', +'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'ACHTUNG: Die Einwahl benötigt eine sichere (HTTPS) Verbindung. Es sei denn sie läuft Lokal(localhost).', +'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ACHTUNG: Testen ist nicht threadsicher. Führen sie also nicht mehrere Tests gleichzeitig aus.', +'ATTENTION: This is an experimental feature and it needs more testing.': 'ACHTUNG: Dies ist eine experimentelle Funktion und benötigt noch weitere Tests.', +'ATTENTION: you cannot edit the running application!': 'ACHTUNG: Eine laufende Anwendung kann nicht editiert werden!', +'Authentication': 'Authentifizierung', +'Available databases and tables': 'Verfügbare Datenbanken und Tabellen', 'back': 'zurück', 'beautify': 'beautify', 'cache': 'Cache', 'cache, errors and sessions cleaned': 'Zwischenspeicher (cache), Fehler und Sitzungen (sessions) gelöscht', 'call': 'call', +'can be a git repo': 'can be a git repo', +'Cannot be empty': 'Darf nicht leer sein', +'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'Nicht Kompilierbar:Es sind Fehler in der Anwendung. Beseitigen Sie die Fehler und versuchen Sie es erneut.', 'cannot create file': 'Kann Datei nicht erstellen', 'cannot upload file "%(filename)s"': 'Kann Datei nicht Hochladen "%(filename)s"', +'Change admin password': 'Administrator-Passwort ändern', +'Change Password': 'Passwort ändern', 'change password': 'Passwort ändern', 'check all': 'alles auswählen', +'Check for upgrades': 'check for upgrades', +'Check to delete': 'Markiere zum löschen', +'Checking for upgrades...': 'Auf Updates überprüfen...', +'Clean': 'löschen', 'click here for online examples': 'hier klicken für online Beispiele', 'click here for the administrative interface': 'hier klicken für die Administrationsoberfläche ', 'click to check for upgrades': 'hier klicken um nach Upgrades zu suchen', +'Client IP': 'Client IP', 'code': 'code', 'collapse/expand all': 'collapse/expand all', +'Compile': 'kompilieren', 'compiled application removed': 'kompilierte Anwendung gelöscht', +'Controller': 'Controller', +'Controllers': 'Controller', 'controllers': 'Controllers', +'Copyright': 'Urheberrecht', +'Create': 'erstellen', 'create file with filename:': 'erzeuge Datei mit Dateinamen:', 'create new application:': 'erzeuge neue Anwendung:', +'Create new simple application': 'Erzeuge neue Anwendung', 'created by': 'created by', 'crontab': 'crontab', +'Current request': 'Aktuelle Anfrage (request)', +'Current response': 'Aktuelle Antwort (response)', +'Current session': 'Aktuelle Sitzung (session)', 'currently running': 'currently running', 'currently saved or': 'des derzeit gespeicherten oder', 'customize me!': 'pass mich an!', 'data uploaded': 'Daten hochgeladen', +'Database': 'Datenbank', 'database': 'Datenbank', 'database %s select': 'Datenbank %s ausgewählt', 'database administration': 'Datenbankadministration', +'Date and Time': 'Datum und Uhrzeit', 'db': 'db', +'DB Model': 'DB Modell', +'Debug': 'Debug', 'defines tables': 'definiere Tabellen', +'Delete': 'Löschen', 'delete': 'löschen', 'delete all checked': 'lösche alle markierten', 'delete plugin': 'Plugin löschen', +'Delete:': 'Löschen:', +'Deploy': 'deploy', +'Deploy on Google App Engine': 'Auf Google App Engine installieren', +'Deploy to OpenShift': 'Deploy to OpenShift', +'Description': 'Beschreibung', 'design': 'design', +'DESIGN': 'design', +'Design for': 'Design für', 'direction: ltr': 'direction: ltr', +'Disable': 'Disable', 'documentation': 'Dokumentation', 'done!': 'fertig!', 'download layouts': 'download layouts', 'download plugins': 'download plugins', +'E-mail': 'E-mail', +'EDIT': 'BEARBEITEN', +'Edit': 'bearbeiten', +'Edit application': 'Bearbeite Anwendung', 'edit controller': 'Bearbeite Controller', +'Edit current record': 'Bearbeite aktuellen Datensatz', +'Edit Profile': 'Bearbeite Profil', 'edit profile': 'bearbeite Profil', +'Edit This App': 'Bearbeite diese Anwendung', 'edit views:': 'Views bearbeiten:', +'Editing file': 'Bearbeite Datei', +'Editing file "%s"': 'Bearbeite Datei "%s"', +'Editing Language file': 'Sprachdatei bearbeiten', +'Enterprise Web Framework': 'Enterprise Web Framework', +'Error logs for "%(app)s"': 'Fehlerprotokoll für "%(app)s"', +'Errors': 'Fehler', 'escape': 'escape', +'Exception instance attributes': 'Atribute der Ausnahmeinstanz', +'Expand Abbreviation': 'Kürzel erweitern', 'export as csv file': 'Exportieren als CSV-Datei', 'exposes': 'stellt zur Verfügung', 'extends': 'erweitert', @@ -259,81 +148,204 @@ 'file saved on %(time)s': 'Datei gespeichert am %(time)s', 'file saved on %s': 'Datei gespeichert auf %s', 'filter': 'filter', +'First name': 'Vorname', +'Functions with no doctests will result in [passed] tests.': 'Funktionen ohne doctests erzeugen [passed] in Tests', +'Get from URL:': 'Get from URL:', +'Git Pull': 'Git Pull', +'Git Push': 'Git Push', +'Go to Matching Pair': 'gehe zum übereinstimmenden Paar', +'Group ID': 'Gruppen ID', +'Hello World': 'Hallo Welt', +'Help': 'Hilfe', 'htmledit': 'htmledit', +'If the report above contains a ticket number it indicates a failure in executing the controller, before any attempt to execute the doctests. This is usually due to an indentation error or an error outside function code.\nA green title indicates that all tests (if defined) passed. In this case test results are not shown.': 'Falls der obere Test eine Fehler-Ticketnummer enthält deutet das auf einen Fehler in der Ausführung des Controllers hin, noch bevor der Doctest ausgeführt werden konnte. Gewöhnlich führen fehlerhafte Einrückungen oder fehlerhafter Code ausserhalb der Funktion zu solchen Fehlern. Ein grüner Titel deutet darauf hin, dass alle Test(wenn sie vorhanden sind) erfolgreich durchlaufen wurden. In diesem Fall werden die Testresultate nicht angezeigt.', +'If you answer "yes", be patient, it may take a while to download': '', +'If you answer yes, be patient, it may take a while to download': 'If you answer yes, be patient, it may take a while to download', +'Import/Export': 'Importieren/Exportieren', 'includes': 'Einfügen', +'Index': 'Index', 'index': 'index', 'insert new': 'neu einfügen', 'insert new %s': 'neu einfügen %s', +'Install': 'installieren', +'Installed applications': 'Installierte Anwendungen', 'internal error': 'interner Fehler', +'Internal State': 'interner Status', +'Invalid action': 'Ungültige Aktion', +'Invalid email': 'Ungültige Email', 'invalid password': 'Ungültiges Passwort', +'Invalid Query': 'Ungültige Abfrage', 'invalid request': 'ungültige Anfrage', 'invalid ticket': 'ungültiges Ticket', +'Key bindings': 'Tastenbelegungen', +'Key bindings for ZenConding Plugin': 'Tastenbelegungen für das ZenConding Plugin', 'language file "%(filename)s" created/updated': 'Sprachdatei "%(filename)s" erstellt/aktualisiert', +'Language files (static strings) updated': 'Sprachdatei (statisch Strings) aktualisiert', 'languages': 'Sprachen', +'Languages': 'Sprachen', 'languages updated': 'Sprachen aktualisiert', +'Last name': 'Nachname', +'Last saved on:': 'Zuletzt gespeichert am:', +'Layout': 'Layout', +'License for': 'Lizenz für', 'loading...': 'lade...', 'located in the file': 'located in Datei', +'Login': 'Anmelden', 'login': 'anmelden', +'Login to the Administrative Interface': 'An das Administrations-Interface anmelden', +'Logout': 'abmelden', +'Lost Password': 'Passwort vergessen', 'lost password?': 'Passwort vergessen?', +'Main Menu': 'Menú principal', +'Match Pair': 'Paare finden', +'Menu Model': 'Menü Modell', 'merge': 'verbinden', +'Merge Lines': 'Zeilen zusammenfügen', +'Models': 'Modelle', 'models': 'Modelle', +'Modules': 'Module', 'modules': 'Module', +'Name': 'Name', 'new application "%s" created': 'neue Anwendung "%s" erzeugt', +'New application wizard': 'New application wizard', +'New Record': 'Neuer Datensatz', 'new record inserted': 'neuer Datensatz eingefügt', +'New simple application': 'New simple application', 'next 100 rows': 'nächsten 100 Zeilen', +'Next Edit Point': 'nächster Bearbeitungsschritt', +'NO': 'NEIN', +'No databases in this application': 'Keine Datenbank in dieser Anwendung', 'or import from csv file': 'oder importieren von cvs Datei', 'or provide app url:': 'oder geben Sie eine Anwendungs-URL an:', 'or provide application url:': 'oder geben Sie eine Anwendungs-URL an:', +'Origin': 'Herkunft', +'Original/Translation': 'Original/Übersetzung', +'Overwrite installed app': 'installierte Anwendungen überschreiben', +'Pack all': 'verpacke alles', +'Pack compiled': 'Verpacke kompiliert', 'pack plugin': 'Plugin verpacken', +'Password': 'Passwort', +'Peeking at file': 'Dateiansicht', 'please wait!': 'bitte warten!', +'Plugin "%s" in application': 'Plugin "%s" in Anwendung', 'plugins': 'plugins', +'Plugins': 'Plugins', +'Powered by': 'Unterstützt von', 'previous 100 rows': 'vorherige 100 zeilen', +'Previous Edit Point': 'vorheriger Bearbeitungsschritt', +'Query:': 'Abfrage:', 'record': 'Datensatz', 'record does not exist': 'Datensatz existiert nicht', 'record id': 'Datensatz id', +'Record ID': 'Datensatz ID', 'register': 'Registrierung', +'Register': 'registrieren', +'Registration key': 'Registrierungsschlüssel', +'Reload routes': 'Reload routes', +'Remove compiled': 'kompilat gelöscht', +'Reset Password key': 'Passwortschlüssel zurücksetzen', +'Resolve Conflict file': 'bereinige Konflikt-Datei', 'restore': 'wiederherstellen', 'revert': 'zurückkehren', +'Role': 'Rolle', +'Rows in table': 'Zeilen in Tabelle', +'Rows selected': 'Zeilen ausgewählt', +'Running on %s': 'Running on %s', 'save': 'sichern', +'Save via Ajax': 'via Ajax sichern', +'Saved file hash:': 'Gespeicherter Datei-Hash:', 'selected': 'ausgewählt(e)', 'session expired': 'Sitzung Abgelaufen', 'shell': 'shell', +'Site': 'Seite', 'some files could not be removed': 'einige Dateien konnten nicht gelöscht werden', +'Start wizard': 'start wizard', 'state': 'Status', 'static': 'statische Dateien', +'Static files': 'statische Dateien', +'Stylesheet': 'Stylesheet', +'Submit': 'Submit', 'submit': 'Absenden', +'Sure you want to delete this object?': 'Wollen Sie das Objekt wirklich löschen?', 'table': 'Tabelle', +'Table name': 'Tabellen Name', 'test': 'Test', 'test_def': 'test_def', 'test_for': 'test_for', 'test_if': 'test_if', 'test_try': 'test_try', +'Testing application': 'Teste die Anwendung', +'Testing controller': 'teste Controller', +'The "query" is a condition like "db.table1.field1==\'value\'". Something like "db.table1.field1==db.table2.field2" results in a SQL JOIN.': 'Die "query" ist eine Bedingung wie "db.table1.field1 == \'Wert\'". Etwas wie "db.table1.field1 db.table2.field2 ==" führt zu einem SQL JOIN.', 'the application logic, each URL path is mapped in one exposed function in the controller': 'Die Logik der Anwendung, jeder URL-Pfad wird auf eine Funktion abgebildet die der Controller zur Verfügung stellt', +'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': 'Die Datenrepräsentation definiert Mengen von Tabellen und Datenbanken ', +'The data representation, define database tables and sets': 'The data representation, define database tables and sets', +'The output of the file is a dictionary that was rendered by the view': 'The output of the file is a dictionary that was rendered by the view', +'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': 'Die Präsentationsschicht, Views sind auch bekannt als Vorlagen/Templates', +'There are no controllers': 'Keine Controller vorhanden', +'There are no models': 'Keine Modelle vorhanden', +'There are no modules': 'Keine Module vorhanden', +'There are no plugins': 'There are no plugins', +'There are no static files': 'Keine statischen Dateien vorhanden', +'There are no translators, only default language is supported': 'Keine Übersetzungen vorhanden, nur die voreingestellte Sprache wird unterstützt', +'There are no views': 'Keine Views vorhanden', +'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': 'Diese Dateien werden ohne Verarbeitung ausgeliefert. Beispielsweise Bilder kommen hier hin.', +'This is a copy of the scaffolding application': 'Dies ist eine Kopie einer Grundgerüst-Anwendung', +'This is the %(filename)s template': 'Dies ist das Template %(filename)s', +'Ticket': 'Ticket', +'Timestamp': 'Timestamp', +'TM': 'TM', 'to previous version.': 'zu einer früheren Version.', +'To create a plugin, name a file/folder plugin_[name]': 'Um ein Plugin zu erstellen benennen Sie eine(n) Datei/Ordner plugin_[Name]', 'translation strings for the application': 'Übersetzungs-Strings für die Anwendung', +'Translation strings for the application': 'Translation strings for the application', 'try': 'versuche', 'try something like': 'versuche so etwas wie', +'Unable to check for upgrades': 'überprüfen von Upgrades nicht möglich', 'unable to create application "%s"': 'erzeugen von Anwendung "%s" nicht möglich', 'unable to delete file "%(filename)s"': 'löschen von Datein "%(filename)s" nicht möglich', +'Unable to download': 'herunterladen nicht möglich', +'Unable to download app': 'herunterladen der Anwendung nicht möglich', 'unable to parse csv file': 'analysieren der cvs Datei nicht möglich', 'unable to uninstall "%s"': 'deinstallieren von "%s" nicht möglich', 'uncheck all': 'alles demarkieren', +'Uninstall': 'deinstallieren', 'update': 'aktualisieren', 'update all languages': 'aktualisiere alle Sprachen', +'Update:': 'Aktualisiere:', 'upgrade web2py now': 'jetzt web2py upgraden', 'upload': 'upload', +'Upload & install packed application': 'Verpackte Anwendung hochladen und installieren', +'Upload a package:': 'Upload a package:', +'Upload and install packed application': 'Upload and install packed application', 'upload application:': 'lade Anwendung hoch:', +'Upload existing application': 'lade existierende Anwendung hoch', 'upload file:': 'lade Datei hoch:', 'upload plugin file:': 'Plugin-Datei hochladen:', +'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Benutze (...)&(...) für AND, (...)|(...) für OR, und ~(...) für NOT, um komplexe Abfragen zu erstellen.', +'Use an url:': 'Use an url:', 'user': 'user', +'User ID': 'Benutzer ID', 'variables': 'variables', +'Version': 'Version', +'Version %s.%s.%s (%s) %s': 'Version %s.%s.%s (%s) %s', 'versioning': 'Versionierung', +'View': 'View', 'view': 'View', +'Views': 'Views', 'views': 'Views', -'web2py Recent Tweets': 'neuste Tweets von web2py', 'web2py is up to date': 'web2py ist auf dem neuesten Stand', +'web2py Recent Tweets': 'neuste Tweets von web2py', +'Welcome %s': 'Willkommen %s', +'Welcome to web2py': 'Willkommen zu web2py', +'Which called the function': 'Which called the function', +'Wrap with Abbreviation': 'mit Kürzel einhüllen', 'xml': 'xml', +'YES': 'JA', +'You are successfully running web2py': 'web2by wird erfolgreich ausgeführt', +'You can modify this application and adapt it to your needs': 'Sie können diese Anwendung verändern und Ihren Bedürfnissen anpassen', +'You visited the url': 'Sie besuchten die URL', } diff --git a/applications/admin/languages/he.py b/applications/admin/languages/he.py index 27b00f7a..c209c3ec 100644 --- a/applications/admin/languages/he.py +++ b/applications/admin/languages/he.py @@ -11,7 +11,6 @@ '(something like "it-it")': '(למשל "it-it")', '@markmin\x01Searching: **%s** %%{file}': 'Searching: **%s** files', 'A new version of web2py is available: %s': 'גירסא חדשה של web2py זמינה: %s', -'A new version of web2py is available: Version 1.85.3 (2010-09-18 07:07:46)\n': 'A new version of web2py is available: Version 1.85.3 (2010-09-18 07:07:46)\r\n', 'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'לתשומת ליבך: ניתן להתחבר רק בערוץ מאובטח (HTTPS) או מlocalhost', 'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'לתשומת ליבך: אין לערוך מספר בדיקות במקביל, שכן הן עשויות להפריע זו לזו', 'ATTENTION: you cannot edit the running application!': 'לתשומת ליבך: לא ניתן לערוך אפליקציה בזמן הרצתה', diff --git a/applications/admin/languages/ru.py b/applications/admin/languages/ru.py index ee1a6bbd..60689f0b 100644 --- a/applications/admin/languages/ru.py +++ b/applications/admin/languages/ru.py @@ -12,7 +12,6 @@ '@markmin\x01Searching: **%s** %%{file}': 'Найдено: **%s** %%{файл}', 'A new version of web2py is available': 'Доступна новая версия web2py', 'A new version of web2py is available: %s': 'Доступна новая версия web2py: %s', -'A new version of web2py is available: Version 1.85.3 (2010-09-18 07:07:46)\n': 'Доступна новая версия web2py: Версия 1.85.3 (2010-09-18 07:07:46)\n', 'Abort': 'Отмена', 'About': 'О', 'About application': 'О приложении', diff --git a/applications/admin/languages/sl.py b/applications/admin/languages/sl.py index 7d1638ff..701a8170 100755 --- a/applications/admin/languages/sl.py +++ b/applications/admin/languages/sl.py @@ -12,7 +12,6 @@ '@markmin\x01Searching: **%s** %%{file}': 'Iskanje: **%s** datoteke', 'A new version of web2py is available': 'Nova različica web2py je na voljo', 'A new version of web2py is available: %s': 'Nova različica web2py je na voljo: %s', -'A new version of web2py is available: Version 1.85.3 (2010-09-18 07:07:46)\n': 'Nova različica web2py je na voljo: Različica 1.85.3 (2010-09-18 07:07:46)\n', 'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'POZOR: Prijava zahteva varno povezavo (HTTPS) ali lokalni (localhost) dostop.', 'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'POZOR: Testiranje ni večopravilno, zato ne poganjajte več testov hkrati.', 'ATTENTION: This is an experimental feature and it needs more testing.': 'POZOR: To je preizkusni fazi in potrebuje več testiranja.', diff --git a/applications/admin/languages/uk.py b/applications/admin/languages/uk.py index ef4487a6..461a4370 100644 --- a/applications/admin/languages/uk.py +++ b/applications/admin/languages/uk.py @@ -65,6 +65,7 @@ 'cache': 'кеш', 'Cache Keys': 'Ключі кешу', 'cache, errors and sessions cleaned': 'кеш, список зареєстрованих помилок та сесії очищенні', +'can be a git repo': 'може бути git-репозитарієм', 'Cancel': 'Відмінити', 'Cannot be empty': 'Не може бути порожнім', 'Cannot compile: there are errors in your app:': 'Не вдається скомпілювати: є помилки у вашому додатку:', @@ -85,6 +86,7 @@ 'Code listing': 'Лістинг', 'collapse/expand all': 'згорнути/розгорнути все', 'Command': 'Команда', +'Commit': 'Комміт', 'Compile': 'Компілювати', 'compiled application removed': 'скомпільований додаток вилучено', 'Condition': 'Умова', @@ -187,6 +189,8 @@ 'GAE Password': 'Пароль GAE', 'Generate': 'Генерувати', 'Get from URL:': 'Отримати з URL:', +'Git Pull': 'Git Pull', +'Git Push': 'Git Push', 'Globals##debug': 'Глобальні змінні', 'Go to Matching Pair': 'Перейти до відповідної пари', 'go!': 'почали!', @@ -200,7 +204,7 @@ 'honored only if the expression evaluates to true': 'точка зупинки активується тільки за істинності умови', 'If start the downgrade, be patient, it may take a while to rollback': 'Запустивши повернення на попередню версію, будьте терплячими, це може зайняти трохи часу', 'If start the upgrade, be patient, it may take a while to download': 'Запустивши оновлення, будьте терплячими, потрібен час для завантаження необхідних даних', -'If the report above contains a ticket number it indicates a failure in executing the controller, before any attempt to execute the doctests. This is usually due to an indentation error or an error outside function code.\nA green title indicates that all tests (if defined) passed. In this case test results are not shown.': 'Якщо в наданому вище звіті присутня позначка про помилку (ticket number), то це вказує на збій у виконанні контролера ще до початку запуску док-тестів. Це, зазвичай, сигналізує про помилку вирівнювання тексту програми (indention error) або помилку за межами функції (error outside function code).\r\nЗелений заголовок сигналізує, що всі тести (з наявних) пройшли успішно. В цьому випадку результат тестів показано не буде.', +'If the report above contains a ticket number it indicates a failure in executing the controller, before any attempt to execute the doctests. This is usually due to an indentation error or an error outside function code.\nA green title indicates that all tests (if defined) passed. In this case test results are not shown.': 'Якщо в наданому вище звіті присутня позначка про помилку (ticket number), то це вказує на збій у виконанні контролера ще до початку запуску док-тестів. Це, зазвичай, сигналізує про помилку вирівнювання тексту програми (indention error) або помилку за межами функції (error outside function code). Зелений заголовок сигналізує, що всі тести (з наявних) пройшли успішно. В цьому випадку результат тестів показано не буде.', 'Import/Export': 'Імпорт/Експорт', 'In development, use the default Rocket webserver that is currently supported by this debugger.': 'Під час розробки , використовуйте вбудований веб-сервер Rocket, він найкраще налаштований на спільну роботу з інтерактивним ладначем.', 'includes': 'включає', @@ -306,7 +310,11 @@ 'Powered by': 'Працює на', 'previous 100 rows': 'попередні 100 рядків', 'Previous Edit Point': 'Попереднє місце редагування', +'Private files': 'Приватні файли', +'private files': 'приватні файли', 'Project Progress': 'Поступ проекту', +'Pull': 'Втягнути', +'Push': 'Проштовхнути', 'Query:': 'Запит:', 'RAM Cache Keys': 'Ключ ОЗП-кешу (RAM Cache)', 'Ram Cleared': "Кеш в пам'яті очищено", @@ -383,6 +391,7 @@ 'There are no translators': 'Перекладів нема', 'There are no translators, only default language is supported': 'Перекладів нема, підтримується тільки мова оригіналу', 'There are no views': 'Відображень нема', +'These files are not served, they are only available from within your app': 'Ці файли ніяк не обробляються, вони доступні тільки в межах вашого додатку', 'These files are served without processing, your images go here': 'Ці файли обслуговуються "як є", без обробки, ваші графічні файли та інші супутні файли даних можуть знаходитись тут', "This debugger may not work properly if you don't have a threaded webserver or you're using multiple daemon processes.": 'Цей ладнач може працювати некоректно, якщо ви використовуєте веб-сервер без підтримки потоків або використовуєте декілька сервісних процесів.', 'This is an experimental feature and it needs more testing. If you decide to downgrade you do it at your own risk': 'Це експериментальна властивість, яка вимагає подальшого тестування. Якщо ви вирішили повернутись на попередню версію, ви це робити на ваш власний розсуд.', @@ -391,6 +400,8 @@ "This page can commit your changes to an openshift app repo and push them to your cloud instance. This assumes that you've already created the application instance using the web2py skeleton and have that repo somewhere on a filesystem that this web2py instance can access. This functionality requires GitPython installed and on the python path of the runtime that web2py is operating in.": 'На цій сторінці можна закомітити ваші зміни в репозитарій додатків openshift та проштовхнути їх у ваш примірник в хмарі. Це передбачає, що ви вже створили примірник додатку, використовуючи базовий додаток web2py, як скелет, і маєте репозитарій десь на вашій файловій системі, причому екземпляр web2py має до нього доступ. Ця властивість вимагає наявності встановленого модулю GitPython так, щоб web2py міг його викликати.', 'This page can upload your application to the Google App Engine computing cloud. Mind that you must first create indexes locally and this is done by installing the Google appserver and running the app locally with it once, or there will be errors when selecting records. Attention: deployment may take long time, depending on the network speed. Attention: it will overwrite your app.yaml. DO NOT SUBMIT TWICE.': 'На цій сторінці ви можете завантажити свій додаток в сервіс хмарних обчислень Google App Engine. Майте на увазі, що спочатку необхідно локально створити індекси, і це можна зробити встановивши сервер додатків Google appserver та запустивши в ньому додаток один раз, інакше при виборі записів виникатимуть помилки. Увага: розгортання може зайняти тривалий час, в залежності від швидкості мережі. Увага: це призведе до перезапису app.yaml. НЕ ПУБЛІКУЙТЕ ДВІЧІ.', 'this page to see if a breakpoint was hit and debug interaction is required.': 'цю сторінку, щоб побачити, чи була досягнута точка зупинки і процес ладнання розпочато.', +'This will pull changes from the remote repo for application "%s"?': '"Втягнути" (pull) зміни з віддаленого репозитарію для додатку "%s"?', +'This will push changes to the remote repo for application "%s".': 'Проштовхнути (push) зміни у віддалений репозитарій для додатку "%s"?', 'ticket': 'позначка', 'Ticket': 'Позначка (Ticket)', 'Ticket ID': 'Ід.позначки (Ticket ID)', diff --git a/applications/admin/models/buttons.py b/applications/admin/models/buttons.py index d33f2bff..a725cd7a 100644 --- a/applications/admin/models/buttons.py +++ b/applications/admin/models/buttons.py @@ -33,6 +33,6 @@ def helpicon(): return IMG(_src=URL('static', 'images/help.png'), _alt='help') def searchbox(elementid): - return TAG[''](LABEL(IMG(_src=URL('static', 'images/search.png'), _alt=T('filter')), _class='icon', _for=elementid), ' ', INPUT(_id=elementid, _type='text', _size=12)) + return TAG[''](LABEL(IMG(_id="search_start",_src=URL('static', 'images/search.png'), _alt=T('filter')), _class='icon', _for=elementid), ' ', INPUT(_id=elementid, _type='text', _size=12)) diff --git a/applications/admin/static/css/web2py.css b/applications/admin/static/css/web2py.css index cab92321..5b645cc4 100644 --- a/applications/admin/static/css/web2py.css +++ b/applications/admin/static/css/web2py.css @@ -1,190 +1,181 @@ /** these MUST stay **/ -body { margin: 0; padding:0; border: 0; } -a { text-decoration:none; white-space: nowrap;} -a:hover {text-decoration: underline} -a.button {text-decoration: none} -h1,h2,h3,h4,h5,h6 {margin: 0.5em 0 0.25em 0; display: block; font-family: Helvetica;} - h1 { font-size: 4.00em;} - h2 { font-size: 3.00em;} - h3 { font-size: 2.00em;} - h4 { font-size: 1.50em;} - h5 { font-size: 1.25em;} - h6 { font-size: 1.12em;} -right { float:right; text-align: right; } -left { float:left; text-align: left; } -center { width:100; text-align: center; vertical-align:middle;} -th, label { font-weight: bold; white-space: nowrap; } -td, th { text-align: left; padding: 2px 5px 2px 5px; } -th { vertical-align: middle; border-right: 1px solid white;} -td { vertical-align: top; } -form table tr td label { text-align: left; } -p, table, ol, ul { padding: 0.5em 0 0.5em 0 } -p {text-align: justify } -ol, ul { padding-left: 30px } -li { margin-bottom: 0.5em; } -span, input, select, textarea, button, label, a { display: inline } -img { border: 0; } -blockquote, blockquote p, p blockquote { font-style: italic; margin: 0.5em 30px 0.5em 30px; font-size: 0.9em} -i, em { font-style: italic; } -strong { font-weight: bold; } -small { font-size: 0.8em; } -textarea { width: 100%; } -code { font-family: Courier;} -video { width:400px; } -audio { width:200px; } -input[type=text], input[type=password], select { width: 300px; margin-right: 5px } -ul { list-style-type: none; margin: 0px; padding: 0px; } +a {text-decoration:none; white-space:nowrap} +a:hover {text-decoration:underline} +a.button {text-decoration:none} +h1,h2,h3,h4,h5,h6 {margin:0.5em 0 0.25em 0; display:block; + font-family:Helvetica} +h1 {font-size:4.00em} +h2 {font-size:3.00em} +h3 {font-size:2.00em} +h4 {font-size:1.50em} +h5 {font-size:1.25em} +h6 {font-size:1.12em} +th,label {font-weight:bold; white-space:nowrap} +td,th {text-align:left; padding:2px 5px 2px 5px} +th {vertical-align:middle; border-right:1px solid white} +td {vertical-align:top} +form table tr td label {text-align:left} +p,table,ol,ul {padding:0; margin: 0.5em 0} +p {text-align:justify} +ol, ul {list-style-position:inside} +li {margin-bottom:0.5em} +span,input,select,textarea,button,label,a {display:inline} +img {border:0} +blockquote,blockquote p,p blockquote { + font-style:italic; margin:0.5em 30px 0.5em 30px; font-size:0.9em} +i,em {font-style:italic} +strong {font-weight:bold} +small {font-size:0.8em} +code {font-family:Courier} +textarea {width:100%} +video {width:400px} +audio {width:200px} +input[type=text],input[type=password],select{width:300px; margin-right:5px} .hidden {display:none;visibility:visible} +.right {float:right; text-align:right} +.left {float:left; text-align:left} +.center {width:100; text-align:center; vertical-align:middle} /** end **/ /* Sticky footer begin */ -html, body { - height: 100%; -} + .wrapper { - min-height: 100%; - height: auto !important; - height: 100%; - margin: 0 auto -8em; /* set last value to footer height plus footer vertical padding */ + min-height:100%; + height:auto !important; + height:100%; + margin:0 auto -8em; /* set last value to footer height plus footer vertical padding */ } .main { - padding: 20px 0 50px 0; + padding:20px 0 50px 0; } -.footer, .push { - height: 6em; - padding: 1em 0; - clear: both; +.footer,.push { + height:6em; + padding:1em 0; + clear:both; } -.footer-content {position: relative; bottom: -4em; width: 100%;} +.footer-content {position:relative; bottom:-4em; width:100%} .auth_navbar { - white-space: nowrap; + white-space:nowrap; } /* Sticky footer end */ .footer { - border-top: 1px #DEDEDE solid; + border-top:1px #DEDEDE solid; } .header { - // background: ; + // background:; } -fieldset { padding: 16px; border-top: 1px #DEDEDE solid;} -fieldset legend {text-transform:uppercase; font-weight: bold; padding: 4px 16px 4px 16px; background: #f1f1f1;} +fieldset {padding:16px; border-top:1px #DEDEDE solid} +fieldset legend {text-transform:uppercase; font-weight:bold; padding:4px 16px 4px 16px; background:#f1f1f1} /* fix ie problem with menu */ -.ie-lte7 .topbar .container {z-index: 2; } +.ie-lte7 .topbar .container {z-index:2} -td.w2p_fw {padding-bottom: 1px;} -td.w2p_fl, td.w2p_fw, td.w2p_fc { vertical-align:top; } -td.w2p_fl { text-align:right; } -td.w2p_fl, td.w2p_fw {padding-right: 7px;} -td.w2p_fl, td.w2p_fc { padding-top: 4px; } +td.w2p_fw {padding-bottom:1px} +td.w2p_fl,td.w2p_fw,td.w2p_fc {vertical-align:top} +td.w2p_fl {text-align:right} +td.w2p_fl, td.w2p_fw {padding-right:7px} +td.w2p_fl,td.w2p_fc {padding-top:4px} -/* tr#submit_record__row {border-top: 1px solid #E5E5E5;} */ -#submit_record__row td {padding-top: .5em;} +/* tr#submit_record__row {border-top:1px solid #E5E5E5} */ +#submit_record__row td {padding-top:.5em} /* Fix */ -#auth_user_remember__row label {display: inline;} -#web2py_user_form td { vertical-align:top; } +#auth_user_remember__row label {display:inline} +#web2py_user_form td {vertical-align:top} /*********** web2py specific ***********/ div.flash { - font-weight: bold; - display: none; - position: fixed; - padding: 10px; - top: 48px; - right: 50px; - min-width: 280px; - opacity: 0.85; - margin: 0px 0px 10px 10px; - color: #fff; - vertical-align: middle; - cursor: pointer; - background: #000; - border: 2px solid #fff; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - z-index: 2; + font-weight:bold; + display:none; + position:fixed; + padding:10px; + top:48px; + right:50px; + min-width:280px; + opacity:0.85; + margin:0px 0px 10px 10px; + color:#fff; + vertical-align:middle; + cursor:pointer; + background:#000; + border:2px solid #fff; + border-radius:5px; + -moz-border-radius:5px; + -webkit-border-radius:5px; + z-index:2000; } -div.flash {z-index:2000;} -div.error_wrapper { display: block; } +div.error_wrapper {display:block} div.error { - background-color: red; - color: white; - padding: 3px; - display: inline-block; + background-color:red; + color:white; + padding:3px; + display:inline-block; } .topbar { - padding: 10px 0; + padding:10px 0; width:100%; - color: #959595; - vertical-align: middle; - padding: auto; - background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222)); - background-image: -moz-linear-gradient(top, #333333, #222222); - background-image: -ms-linear-gradient(top, #333333, #222222); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222)); - background-image: -webkit-linear-gradient(top, #333333, #222222); - background-image: -o-linear-gradient(top, #333333, #222222); - background-image: linear-gradient(top, #333333, #222222); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + color:#959595; + vertical-align:middle; + padding:auto; + background-image:-khtml-gradient(linear,left top,left bottom,from(#333333),to(#222222)); + background-image:-moz-linear-gradient(top,#333333,#222222); + background-image:-ms-linear-gradient(top,#333333,#222222); + background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#333333),color-stop(100%,#222222)); + background-image:-webkit-linear-gradient(top,#333333,#222222); + background-image:-o-linear-gradient(top,#333333,#222222); + background-image:linear-gradient(top,#333333,#222222); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333',endColorstr='#222222',GradientType=0); + -webkit-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1); + -moz-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1); + box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1); } .topbar a { - color: #e1e1e1; + color:#e1e1e1; } -#navbar {float: right; padding: 5px; /* same as superfish */} - -.right { - width:100%; - text-align: right; - float: right; -} +#navbar {float:right; padding:5px; /* same as superfish */} .statusbar { - background-color: #F5F5F5; - margin-top: 1em; - margin-bottom: 1em; - padding: .5em 1em; - border: 1px solid #ddd; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; + background-color:#F5F5F5; + margin-top:1em; + margin-bottom:1em; + padding:.5em 1em; + border:1px solid #ddd; + border-radius:5px; + -moz-border-radius:5px; + -webkit-border-radius:5px; } -.breadcrumbs { float: left; } +.breadcrumbs {float:left} -.copyright {float: left;} -#poweredBy {float: right;} +.copyright {float:left} +#poweredBy {float:right} /* #MEDIA QUERIES SECTION */ /* All Mobile Sizes (devices and browser) */ - @media only screen and (max-width: 767px) { + @media only screen and (max-width:767px) { /* removed because of bootswatch - .topbar {text-align: center;} - #navbar, #menu {float: none;} - #navbar {font-size: 1.2em; padding: .6em 0 1.2em;} - #menu {padding: 0 0 1.5em;} - #menu select {font-size: 1.2em; margin: 0; padding: 0;} + .topbar {text-align:center} + #navbar,#menu {float:none} + #navbar {font-size:1.2em; padding:.6em 0 1.2em} + #menu {padding:0 0 1.5em} + #menu select {font-size:1.2em; margin:0; padding:0} - div.flash {top: 110px; right: 10px;} + div.flash {top:110px; right:10px} */ - } + } /* *Grid @@ -193,43 +184,47 @@ div.error { * will look better with the declarations below * if needed to remove base.css consider keeping these following lines in some css file. */ -// .web2py_table { border: 1px solid #ccc; } -.web2py_paginator { } -.web2py_grid {width: 100% } -.web2py_grid table { width: 100% } +// .web2py_table {border:1px solid #ccc} +.web2py_paginator {} +.web2py_grid {width:100%} +.web2py_grid table {width:100%} .web2py_grid tbody td { - padding: 2px 5px 2px 5px; - vertical-align: middle; + padding:2px 5px 2px 5px; + vertical-align:middle; } -.web2py_grid thead th, .web2py_grid tfoot td { +.web2py_grid thead th,.web2py_grid tfoot td { background-color:#EAEAEA; - padding: 10px 5px 10px 5px; + padding:10px 5px 10px 5px; } -.web2py_grid tr.odd {background-color: #F9F9F9;} -.web2py_grid tr:hover {background-color: #F5F5F5; } +.web2py_grid tr.odd {background-color:#F9F9F9} +.web2py_grid tr:hover {background-color:#F5F5F5} /* .web2py_breadcrumbs a { - line-height: 20px; margin-right: 5px; display: inline-block; - padding: 3px 5px 3px 5px; - font-family: 'lucida grande', tahoma, verdana, arial, sans-serif; - color: #3C3C3D; - text-shadow: 1px 1px 0 #FFFFFF; - white-space: nowrap; overflow: visible; cursor: pointer; + line-height:20px; margin-right:5px; display:inline-block; + padding:3px 5px 3px 5px; + font-family:'lucida grande',tahoma,verdana,arial,sans-serif; + color:#3C3C3D; + text-shadow:1px 1px 0 #FFFFFF; + white-space:nowrap; overflow:visible; cursor:pointer; background:#ECECEC; - border: 1px solid #CACACA; - -webkit-border-radius: 2px; -moz-border-radius: 2px; - -webkit-background-clip: padding-box; border-radius: 2px; - outline: none; position: relative; zoom: 1; *display: inline; + border:1px solid #CACACA; + -webkit-border-radius:2px; -moz-border-radius:2px; + -webkit-background-clip:padding-box; border-radius:2px; + outline:none; position:relative; zoom:1; *display:inline; } */ .web2py_console form { width:100%; + display:inline; } +.web2py_console form select { + margin:0; +} .web2py_search_actions{ float:left; @@ -238,14 +233,14 @@ div.error { .web2py_grid .row_buttons { min-height:25px; - vertical-align: middle; + vertical-align:middle; } .web2py_grid .row_buttons a { - margin: 3px; + margin:3px; } .web2py_search_actions { - width: 100%; + width:100%; } .web2py_grid .row_buttons a, @@ -254,13 +249,13 @@ div.error { .web2py_console input[type=submit], .web2py_console input[type=button], .web2py_console button { - line-height: 20px; - margin-right: 5px; display: inline-block; - padding: 3px 5px 3px 5px; + line-height:20px; + margin-right:5px; display:inline-block; + padding:3px 5px 3px 5px; } .web2py_counter { - margin-top: 5px; + margin-top:5px; margin-right:5px; width:35%; float:right; @@ -268,37 +263,37 @@ div.error { } /*Fix firefox problem*/ -.web2py_table {clear: both; display: block;} +.web2py_table {clear:both; display:block} .web2py_paginator { - padding: 5px; + padding:5px; text-align:right; - background-color: #f2f2f2; + background-color:#f2f2f2; } .web2py_paginator ul { - list-style-type: none; - margin: 0px; - padding: 0px; + list-style-type:none; + margin:0px; + padding:0px; } .web2py_paginator ul li { - display: inline; + display:inline; } .web2py_paginator .current { - font-weight: bold; + font-weight:bold; } #w2p_query_panel {} .web2py_breadcrumbs ul { - list-style: none; - margin-bottom: 18px; + list-style:none; + margin-bottom:18px; } .web2py_breadcrumbs ul li { - display: inline-block; + display:inline-block; } -.ie9 #query_panel {padding-bottom:2px;} +.ie9 #query_panel {padding-bottom:2px} diff --git a/applications/admin/static/js/ajax_editor.js b/applications/admin/static/js/ajax_editor.js index 8790d847..8706cbd8 100644 --- a/applications/admin/static/js/ajax_editor.js +++ b/applications/admin/static/js/ajax_editor.js @@ -72,7 +72,7 @@ function doClickSave() { // show flash message (if any) var flash=xhr.getResponseHeader('web2py-component-flash'); - if (flash) jQuery('.flash').html(flash).slideDown(); + if (flash) jQuery('.flash').html(decodeURIComponent(flash)).slideDown(); else jQuery('.flash').hide(); // reenable disabled submit button @@ -149,8 +149,8 @@ function doToggleBreakpoint(filename, url) { success: function(json,text,xhr){ // show flash message (if any) - var flash=decodeURIComponent(xhr.getResponseHeader('web2py-component-flash')); - if (flash) jQuery('.flash').html(flash).slideDown(); + var flash=xhr.getResponseHeader('web2py-component-flash'); + if (flash) jQuery('.flash').html(decodeURIComponent(flash)).slideDown(); else jQuery('.flash').hide(); try { if (json.error) { diff --git a/applications/admin/static/js/jqueryMultiSelect.js b/applications/admin/static/js/jqueryMultiSelect.js index c7011265..57eeaf03 100755 --- a/applications/admin/static/js/jqueryMultiSelect.js +++ b/applications/admin/static/js/jqueryMultiSelect.js @@ -45,11 +45,8 @@ if(jQuery) (function($){ html += ''; $(select).after(html); diff --git a/applications/admin/static/js/web2py.js b/applications/admin/static/js/web2py.js index eb1e3b09..9a2e208c 100644 --- a/applications/admin/static/js/web2py.js +++ b/applications/admin/static/js/web2py.js @@ -44,6 +44,12 @@ function web2py_event_handlers() { doc.on('keyup', 'input.double, input.decimal', function(){this.value=this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g,'').reverse();}); 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(!confirm(confirm_message)) this.checked=false;}); + doc.ajaxSuccess(function(e, xhr) { + var redirect=xhr.getResponseHeader('web2py-redirect-location'); + if (redirect != null) { + window.location = redirect; + }; + }); }; jQuery(function() { @@ -98,8 +104,8 @@ function web2py_ajax_page(method, action, data, target) { eval(decodeURIComponent(command)); if(flash) jQuery('.flash').html(decodeURIComponent(flash)).slideDown(); - } - }); + } + }); } function web2py_component(action, target, timeout, times){ diff --git a/applications/admin/views/appadmin.html b/applications/admin/views/appadmin.html index 73c4ae47..1d967c2f 100644 --- a/applications/admin/views/appadmin.html +++ b/applications/admin/views/appadmin.html @@ -29,7 +29,7 @@ {{pass}} {{pass}}

- {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}} + {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}}

[ {{=A(str(T('insert new'))+' '+table,_href=URL('insert',args=[db,table]))}} ]

@@ -50,7 +50,7 @@ {{=T('Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.')}}
{{=T('"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN')}}



-

{{=nrows}} {{=T("selected")}}

+

{{=T("%s selected", nrows)}}

{{if start>0:}}[ {{=A(T('previous 100 rows'),_href=URL('select',args=request.args[0],vars=dict(start=start-100)))}} ]{{pass}} {{if stop

{{=T("Import/Export")}}


[ {{=T("export as csv file")}} ] - {{if table:}} - {{=FORM(str(T('or import from csv file'))+" ",INPUT(_type='file',_name='csvfile'),INPUT(_type='hidden',_value=table,_name='table'),INPUT(_type='submit',_value=T('import')))}} - {{pass}} - + {{=formcsv or ''}} {{elif request.function=='insert':}}

{{=T("database")}} {{=A(request.args[0],_href=URL('index'))}} @@ -108,40 +105,34 @@ {{elif request.function == 'ccache':}} -

Cache

+

{{T("Cache")}}

-

Statistics

+

{{T("Statistics")}}

-

Overview

-

Number of entries: {{=total['entries']}} - {{if total['entries'] > 0:}} -

+

{{=T("Overview")}}

+

{{=T.M("Number of entries: **%s**", total['entries'])}}

+ {{if total['entries'] > 0:}} +

{{=T.M("Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses})", + dict(ratio=total['ratio'], hits=total['hits'], misses=total['misses']))}} +

- Hit Ratio: - {{=total['ratio']}}% - ({{=total['hits']}} hits - and {{=total['misses']}} misses) -

-

- Size of cache: + {{=T("Size of cache:")}} {{if object_stats:}} - {{=total['objects']}} items, - {{=total['bytes']}} bytes - {{if total['bytes'] > 524287:}} - ({{="%.0d" % (total['bytes'] / 1048576)}} MB) - {{pass}} - {{else:}} not available (requires the Python guppy library) + {{=T.M("**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}", dict(items=total['objects'], bytes=total['bytes']))}} + {{if total['bytes'] > 524287:}} + {{=T.M("(**%.0d MB**)", total['bytes'] / 1048576)}} + {{pass}} + {{else:}} + {{=T.M("**not available** (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)")}} {{pass}}

- Cache contains items up to - {{="%02d" % total['oldest'][0]}} hours - {{="%02d" % total['oldest'][1]}} minutes - {{="%02d" % total['oldest'][2]}} seconds old. + {{=T.M("Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.", + dict(hours=total['oldest'][0], min=total['oldest'][1], sec=total['oldest'][2]))}}

{{=BUTTON(T('Cache Keys'), _onclick='jQuery("#all_keys").toggle();')}}
- - -
{{=FORM(INPUT(_type='submit',_name='cancel',_value=T('Cancel')))}}{{=FORM(INPUT(_type='submit',_name='pull',_value=T('Pull')))}}
- +{{=dialog}} diff --git a/applications/admin/views/default/plugin.html b/applications/admin/views/default/plugin.html index aded9d40..49d328e7 100644 --- a/applications/admin/views/default/plugin.html +++ b/applications/admin/views/default/plugin.html @@ -16,6 +16,7 @@ def file_upload_form(location): INPUT(_type="file",_name="file")," ",T("and rename it:")," ", INPUT(_type="text",_name="filename",requires=IS_NOT_EMPTY), INPUT(_type="hidden",_name="location",_value=location), + INPUT(_type="hidden",_name="token",_value=session.token), INPUT(_type="hidden",_name="sender",_value=URL('design/'+app)), INPUT(_type="submit",_value=T("submit")),_action=URL('upload_file')) return form @@ -23,14 +24,10 @@ def file_create_form(location): form=FORM(T("create file with filename:")," ", INPUT(_type="text",_name="filename",requires=IS_NOT_EMPTY), INPUT(_type="hidden",_name="location",_value=location), + INPUT(_type="hidden",_name="token",_value=session.token), INPUT(_type="hidden",_name="sender",_value=URL('design/'+app)), INPUT(_type="submit",_value=T("submit")),_action=URL('create_file')) return form -def upload_plugin_form(app): - form=FORM(T("upload plugin file:")," ", - INPUT(_type="file",_name="pluginfile"), - INPUT(_type="submit",_value=T("submit"))) - return form def deletefile(arglist): return A(TAG[''](IMG(_src=URL('static', 'images/delete_icon.png')), SPAN(T('Delete this file (you will be asked to confirm deletion)'))), _class='icon delete tooltip', _href=URL('delete',args=arglist,vars=dict(sender=request.function+'/'+app))) }} diff --git a/applications/admin/views/default/site.html b/applications/admin/views/default/site.html index fd809416..879dccc2 100644 --- a/applications/admin/views/default/site.html +++ b/applications/admin/views/default/site.html @@ -70,12 +70,12 @@ {{else:}}

{{=button("javascript:ajax('"+URL('check_version')+"',[],'check_version')", T('Check for upgrades'))}} - {{pass}} + {{=button(URL('default','reload_routes'), T('Reload routes'))}}

-
+ {{pass}} +

{{=T("Running on %s", request.env.server_software)}} -

-

{{=button(URL('default','reload_routes'), T('Reload routes'))}}

+

{{pass}} @@ -87,64 +87,42 @@

{{=T("New simple application")}}

- -
- {{=LABEL(T("Application name:"), _for="scaffold_filename")}} - - -
- - + {{=form_create.custom.begin}} +
+ {{=LABEL(T("Application name:"))}} + + {{=form_create.custom.widget.name}} + + +
+ {{=form_create.custom.end}}

{{=T("Upload and install packed application")}}

-
-
- - - - - - - - - - - - - - -
- {{=LABEL(T("Application name:"), _form='upload_filename')}} - - -
- {{=LABEL(T("Upload a package:"), _for='upload_file')}} - - - OR -
- {{=LABEL(T("Get from URL:"), _for='upload_url')}} - -
-
+ {{=form_update.custom.begin}} + - - - - - - -
+ {{=LABEL(T("Application name:"))}} + + {{=form_update.custom.widget.name}} +
+ {{=LABEL(T("Upload a package:"))}} + + {{=form_update.custom.widget.file}} +
+ {{=LABEL('Or ',T("Get from URL:"))}} + + {{=form_update.custom.widget.url}} +
({{=T('can be a git repo')}}) - - - {{=LABEL(T("Overwrite installed app"), _for='upload_overwrite')}} -
- -
- - +
+ {{=form_update.custom.widget.overwrite}} + {{=LABEL(T("Overwrite installed app"))}} +
+ + +
+ {{=form_update.custom.end}}
diff --git a/applications/admin/views/default/uninstall.html b/applications/admin/views/default/uninstall.html index b2d9b4f0..72920aba 100644 --- a/applications/admin/views/default/uninstall.html +++ b/applications/admin/views/default/uninstall.html @@ -1,10 +1,7 @@ {{extend 'layout.html'}} -

{{=T('Are you sure you want to uninstall application "%s"?', app)}}

- - - -
{{=FORM(INPUT(_type='submit',_name='nodelete',_value=T('Abort')))}}{{=FORM(INPUT(_type='submit',_name='delete',_value=T('Uninstall')))}}
-
+
+{{=dialog}} +
diff --git a/applications/admin/views/default/upgrade_web2py.html b/applications/admin/views/default/upgrade_web2py.html index c9974570..34bf06cd 100644 --- a/applications/admin/views/default/upgrade_web2py.html +++ b/applications/admin/views/default/upgrade_web2py.html @@ -8,7 +8,6 @@ {{=T('If start the upgrade, be patient, it may take a while to download')}}

-{{=FORM(INPUT(_type='submit',_name='noupgrade',_value=T('Cancel')), _class='inline')}} -{{=FORM(INPUT(_type='submit',_name='upgrade',_value=T('Upgrade')), _class='inline')}} +{{=dialog}}
diff --git a/applications/admin/views/layout.html b/applications/admin/views/layout.html index 79f0efa3..d6a29b59 100644 --- a/applications/admin/views/layout.html +++ b/applications/admin/views/layout.html @@ -28,7 +28,7 @@
{{block footer}} - powered by web2py - @2011 + powered by web2py - @{{=request.now.year}} {{end}}
diff --git a/applications/admin/views/shell/index.html b/applications/admin/views/shell/index.html index 469e44a7..028dd424 100644 --- a/applications/admin/views/shell/index.html +++ b/applications/admin/views/shell/index.html @@ -73,7 +73,7 @@ Type some Python code in here and hit Return (Enter) to execute it. -
autoscroll
+
autoscroll
diff --git a/applications/examples/controllers/appadmin.py b/applications/examples/controllers/appadmin.py index b8eccf9e..71ff7876 100644 --- a/applications/examples/controllers/appadmin.py +++ b/applications/examples/controllers/appadmin.py @@ -199,17 +199,8 @@ def select(): _class='delete', _type='checkbox', value=False), ''), TR('', '', INPUT(_type='submit', _value=T('submit')))), _action=URL(r=request,args=request.args)) - if request.vars.csvfile != None: - try: - import_csv(db[request.vars.table], - request.vars.csvfile.file) - response.flash = T('data uploaded') - except Exception, e: - response.flash = DIV(T('unable to parse csv file'),PRE(str(e))) if form.accepts(request.vars, formname=None): -# regex = re.compile(request.args[0] + '\.(?P\w+)\.id\>0') regex = re.compile(request.args[0] + '\.(?P
\w+)\..+') - match = regex.match(form.vars.query.strip()) if match: table = match.group('table') @@ -230,6 +221,23 @@ def select(): except Exception, e: (rows, nrows) = ([], 0) response.flash = DIV(T('Invalid Query'),PRE(str(e))) + # begin handle upload csv + if table: + formcsv = FORM(str(T('or import from csv file'))+" ", + INPUT(_type='file',_name='csvfile'), + INPUT(_type='hidden',_value=table,_name='table'), + INPUT(_type='submit',_value=T('import'))) + else: + formcsv = None + if formcsv and formcsv.process().accepted and request.vars.csvfile: + try: + import_csv(db[request.vars.table], + request.vars.csvfile.file) + response.flash = T('data uploaded') + except Exception, e: + response.flash = DIV(T('unable to parse csv file'),PRE(str(e))) + # end handle upload csv + return dict( form=form, table=table, @@ -238,6 +246,7 @@ def select(): nrows=nrows, rows=rows, query=request.vars.query, + formcsv = formcsv, ) diff --git a/applications/examples/controllers/cache_examples.py b/applications/examples/controllers/cache_examples.py index 21971da0..930f23c0 100644 --- a/applications/examples/controllers/cache_examples.py +++ b/applications/examples/controllers/cache_examples.py @@ -49,14 +49,3 @@ def cache_controller_and_view(): return response.render(d) -def cache_db_select(): - """cache the database select in ram for 5 seconds""" - - db.users.insert(name='somebody', email='gluon@mdp.cti.depaul.edu') - records = db().select(db.users.ALL, cache=(cache.ram, 5)) - if len(records) > 20: - db(dba.users.id > 0).delete() - return dict(records=records) - - - diff --git a/applications/examples/controllers/database_examples.py b/applications/examples/controllers/database_examples.py deleted file mode 100644 index 489c3662..00000000 --- a/applications/examples/controllers/database_examples.py +++ /dev/null @@ -1,90 +0,0 @@ -from gluon.fileutils import read_file - -response.menu = [['Register Person', False, URL('register_person')], - ['Register Dog', False, URL('register_dog')], - ['Register Product', False, URL('register_product')], - ['Buy product', False, URL('buy')]] - - -def register_person(): - """ simple person registration form with validation and database.insert() - also lists all records currently in the table""" - - # create an insert form from the table - form = SQLFORM(db.person) - - # if form correct perform the insert - if form.process().accepted: - response.flash = 'new record inserted' - - # and get a list of all persons - records = SQLTABLE(db().select(db.person.ALL),headers='fieldname:capitalize') - - return dict(form=form, records=records) - - -def register_dog(): - """ simple person registration form with validation and database.insert() - also lists all records currently in the table""" - - form = SQLFORM(db.dog) - if form.process().accepted: - response.flash = 'new record inserted' - download = URL('download') # to see the picture - records = SQLTABLE(db().select(db.dog.ALL), upload=download, - headers='fieldname:capitalize') - return dict(form=form, records=records) - - -def register_product(): - """ simple person registration form with validation and database.insert() - also lists all records currently in the table""" - - form = SQLFORM(db.product) - if form.process().accepted: - response.flash = 'new record inserted' - records = SQLTABLE(db().select(db.product.ALL), - headers='fieldname:capitalize') - return dict(form=form, records=records) - - -def buy(): - """ uses a form to query who is buying what. validates form and - updates existing record or inserts new record in purchases """ - - form = SQLFORM.factory( - Field('buyer_id',requires=IS_IN_DB(db,db.person.id,'%(name)s')), - Field('product_id',requires=IS_IN_DB(db,db.product.id,'%(name)s')), - Field('quantity','integer',requires=IS_INT_IN_RANGE(1,100))) - if form.process().accepted: - # get previous purchese - purchase = db((db.purchase.buyer_id == form.vars.buyer_id)& - (db.purchase.product_id==form.vars.product_id)).select().first() - - if purchase: - # if list contains a record, update that record - purchase.update_record( - quantity = purchase.quantity+form.vars.quantity) - else: - # self insert a new record in table - db.purchase.insert(buyer_id=form.vars.buyer_id, - product_id=form.vars.product_id, - quantity=form.vars.quantity) - response.flash = 'product purchased!' - elif form.errors: - response.flash = 'invalid values in form!' - - # now get a list of all purchases - records = SQLTABLE(db(purchased).select(),headers='fieldname:capitalize') - return dict(form=form, records=records) - - -def delete_purchased(): - """ delete all records in purchases """ - db(db.purchase.id > 0).delete() - redirect(URL('buy')) - -def download(): - """ used to download uploaded files """ - return response.download(request,db) - diff --git a/applications/examples/models/cache_examples/db.py b/applications/examples/models/cache_examples/db.py deleted file mode 100644 index 1a1025c1..00000000 --- a/applications/examples/models/cache_examples/db.py +++ /dev/null @@ -1,69 +0,0 @@ -######################################################################### -## This scaffolding model makes your app work on Google App Engine too -######################################################################### - -if request.controller.endswith('_examples'): response.generic_patterns.append('*') - -from gluon.settings import settings - -# if running on Google App Engine -if settings.web2py_runtime_gae: - from gluon.contrib.gql import * - # connect to Google BigTable - db = DAL('gae') - # and store sessions there - session.connect(request, response, db=db) -else: - # if not, use SQLite or other DB - db = DAL('sqlite://storage.sqlite') - -db.define_table( - 'users', - Field('name'), - Field('email') - ) - -# ONE (users) TO MANY (dogs) - -db.define_table( - 'dogs', - Field('owner_id', db.users), - Field('name'), - Field('type'), - Field('vaccinated', 'boolean', default=False), - Field('picture', 'upload', default=''), - ) - -db.define_table( - 'products', - Field('name'), - Field('description', 'text') - ) - -# MANY (users) TO MANY (purchases) - -db.define_table( - 'purchases', - Field('buyer_id', db.users), - Field('product_id', db.products), - Field('quantity', 'integer') - ) - -# if running on Google App Engine -if settings.web2py_runtime_gae: - # quick hack to skip the join - purchased = None -else: - # use a joined view - purchased = (db.users.id == db.purchases.buyer_id) & (db.products.id - == db.purchases.product_id) - -db.users.name.requires = IS_NOT_EMPTY() -db.users.email.requires = [IS_EMAIL(), IS_NOT_IN_DB(db, 'users.email')] -db.dogs.owner_id.requires = IS_IN_DB(db, 'users.id', 'users.name') -db.dogs.name.requires = IS_NOT_EMPTY() -db.dogs.type.requires = IS_IN_SET(['small', 'medium', 'large']) -db.purchases.buyer_id.requires = IS_IN_DB(db, 'users.id', 'users.name') -db.purchases.product_id.requires = IS_IN_DB(db, 'products.id', - 'products.name') -db.purchases.quantity.requires = IS_INT_IN_RANGE(0, 10) diff --git a/applications/examples/models/database_examples/db.py b/applications/examples/models/database_examples/db.py deleted file mode 100644 index 417805b5..00000000 --- a/applications/examples/models/database_examples/db.py +++ /dev/null @@ -1,72 +0,0 @@ -######################################################################### -## This scaffolding model makes your app work on Google App Engine too -######################################################################### - -if request.controller.endswith('_examples'): response.generic_patterns.append('*') - -from gluon.settings import settings - -# if running on Google App Engine -if settings.web2py_runtime_gae: - from gluon.contrib.gql import * - # connect to Google BigTable - db = DAL('gae') - # and store sessions there - session.connect(request, response, db=db) -else: - # if not, use SQLite or other DB - db = DAL('sqlite://storage.sqlite') - -db.define_table( - 'person', - Field('name'), - Field('email'), - format = '%(name)s', - singular = 'Person', - plural = 'Persons', - ) - -# ONE (person) TO MANY (dogs) - -db.define_table( - 'dog', - Field('owner_id', db.person), - Field('name'), - Field('type'), - Field('vaccinated', 'boolean', default=False), - Field('picture', 'upload', default=''), - format = '%(name)s', - singular = 'Dog', - plural = 'Dogs', - ) - -db.define_table( - 'product', - Field('name'), - Field('description', 'text'), - format = '%(name)s', - singular = 'Product', - plural = 'Products', - ) - -# MANY (persons) TO MANY (purchases) - -db.define_table( - 'purchase', - Field('buyer_id', db.person), - Field('product_id', db.product), - Field('quantity', 'integer'), - format = '%(quantity)s %(product_id)s -> %(buyer_id)s', - singular = 'Purchase', - plural = 'Purchases', - ) - -purchased = \ - (db.person.id==db.purchase.buyer_id)&\ - (db.product.id==db.purchase.product_id) - -db.person.name.requires = IS_NOT_EMPTY() -db.person.email.requires = [IS_EMAIL(), IS_NOT_IN_DB(db, 'person.email')] -db.dog.name.requires = IS_NOT_EMPTY() -db.dog.type.requires = IS_IN_SET(('small', 'medium', 'large')) -db.purchase.quantity.requires = IS_INT_IN_RANGE(0, 10) diff --git a/applications/examples/models/default/quotes.py b/applications/examples/models/default/quotes.py deleted file mode 100644 index 79d83658..00000000 --- a/applications/examples/models/default/quotes.py +++ /dev/null @@ -1,12 +0,0 @@ -import random -quotes = [ - ("web2py was the life saver today for me, my blog post: Standalone Usage of web2py's", "caglartoklu", "http://twitter.com/#!/caglartoklu/status/84292131707031553"), - ("Get Things Done - Faster, Better and More Easily with web2py", - "Bruno Rocha", "http://twitter.com/#!/rochacbruno/status/73583156044890112"), - ("Please use www.web2py.com when using MVC , no PHP/SQL stuff please...its 2011 not 1999", "rabblesoft", "http://twitter.com/#!/rabblesoft/status/79189028431343616"), - ('web2py rules! as a sysadmin I like the no installation and no configuration approach a lot)', "kjogut", "http://twitter.com/#!/jkogut/status/61414554273447936"), - ("web2py it is. Compatible with everything under the sun and great interfaces to googleappengine", "comamitc","http://twitter.com/#!/comamitc/status/51744719071477760"), - ("If you are still learning python, web2py is best tool by far", "pbreit", "http://twitter.com/#!/pbreit/status/48260905775017984") - ] -random.shuffle(quotes) - diff --git a/applications/examples/static/css/web2py.css b/applications/examples/static/css/web2py.css index cab92321..5b645cc4 100644 --- a/applications/examples/static/css/web2py.css +++ b/applications/examples/static/css/web2py.css @@ -1,190 +1,181 @@ /** these MUST stay **/ -body { margin: 0; padding:0; border: 0; } -a { text-decoration:none; white-space: nowrap;} -a:hover {text-decoration: underline} -a.button {text-decoration: none} -h1,h2,h3,h4,h5,h6 {margin: 0.5em 0 0.25em 0; display: block; font-family: Helvetica;} - h1 { font-size: 4.00em;} - h2 { font-size: 3.00em;} - h3 { font-size: 2.00em;} - h4 { font-size: 1.50em;} - h5 { font-size: 1.25em;} - h6 { font-size: 1.12em;} -right { float:right; text-align: right; } -left { float:left; text-align: left; } -center { width:100; text-align: center; vertical-align:middle;} -th, label { font-weight: bold; white-space: nowrap; } -td, th { text-align: left; padding: 2px 5px 2px 5px; } -th { vertical-align: middle; border-right: 1px solid white;} -td { vertical-align: top; } -form table tr td label { text-align: left; } -p, table, ol, ul { padding: 0.5em 0 0.5em 0 } -p {text-align: justify } -ol, ul { padding-left: 30px } -li { margin-bottom: 0.5em; } -span, input, select, textarea, button, label, a { display: inline } -img { border: 0; } -blockquote, blockquote p, p blockquote { font-style: italic; margin: 0.5em 30px 0.5em 30px; font-size: 0.9em} -i, em { font-style: italic; } -strong { font-weight: bold; } -small { font-size: 0.8em; } -textarea { width: 100%; } -code { font-family: Courier;} -video { width:400px; } -audio { width:200px; } -input[type=text], input[type=password], select { width: 300px; margin-right: 5px } -ul { list-style-type: none; margin: 0px; padding: 0px; } +a {text-decoration:none; white-space:nowrap} +a:hover {text-decoration:underline} +a.button {text-decoration:none} +h1,h2,h3,h4,h5,h6 {margin:0.5em 0 0.25em 0; display:block; + font-family:Helvetica} +h1 {font-size:4.00em} +h2 {font-size:3.00em} +h3 {font-size:2.00em} +h4 {font-size:1.50em} +h5 {font-size:1.25em} +h6 {font-size:1.12em} +th,label {font-weight:bold; white-space:nowrap} +td,th {text-align:left; padding:2px 5px 2px 5px} +th {vertical-align:middle; border-right:1px solid white} +td {vertical-align:top} +form table tr td label {text-align:left} +p,table,ol,ul {padding:0; margin: 0.5em 0} +p {text-align:justify} +ol, ul {list-style-position:inside} +li {margin-bottom:0.5em} +span,input,select,textarea,button,label,a {display:inline} +img {border:0} +blockquote,blockquote p,p blockquote { + font-style:italic; margin:0.5em 30px 0.5em 30px; font-size:0.9em} +i,em {font-style:italic} +strong {font-weight:bold} +small {font-size:0.8em} +code {font-family:Courier} +textarea {width:100%} +video {width:400px} +audio {width:200px} +input[type=text],input[type=password],select{width:300px; margin-right:5px} .hidden {display:none;visibility:visible} +.right {float:right; text-align:right} +.left {float:left; text-align:left} +.center {width:100; text-align:center; vertical-align:middle} /** end **/ /* Sticky footer begin */ -html, body { - height: 100%; -} + .wrapper { - min-height: 100%; - height: auto !important; - height: 100%; - margin: 0 auto -8em; /* set last value to footer height plus footer vertical padding */ + min-height:100%; + height:auto !important; + height:100%; + margin:0 auto -8em; /* set last value to footer height plus footer vertical padding */ } .main { - padding: 20px 0 50px 0; + padding:20px 0 50px 0; } -.footer, .push { - height: 6em; - padding: 1em 0; - clear: both; +.footer,.push { + height:6em; + padding:1em 0; + clear:both; } -.footer-content {position: relative; bottom: -4em; width: 100%;} +.footer-content {position:relative; bottom:-4em; width:100%} .auth_navbar { - white-space: nowrap; + white-space:nowrap; } /* Sticky footer end */ .footer { - border-top: 1px #DEDEDE solid; + border-top:1px #DEDEDE solid; } .header { - // background: ; + // background:; } -fieldset { padding: 16px; border-top: 1px #DEDEDE solid;} -fieldset legend {text-transform:uppercase; font-weight: bold; padding: 4px 16px 4px 16px; background: #f1f1f1;} +fieldset {padding:16px; border-top:1px #DEDEDE solid} +fieldset legend {text-transform:uppercase; font-weight:bold; padding:4px 16px 4px 16px; background:#f1f1f1} /* fix ie problem with menu */ -.ie-lte7 .topbar .container {z-index: 2; } +.ie-lte7 .topbar .container {z-index:2} -td.w2p_fw {padding-bottom: 1px;} -td.w2p_fl, td.w2p_fw, td.w2p_fc { vertical-align:top; } -td.w2p_fl { text-align:right; } -td.w2p_fl, td.w2p_fw {padding-right: 7px;} -td.w2p_fl, td.w2p_fc { padding-top: 4px; } +td.w2p_fw {padding-bottom:1px} +td.w2p_fl,td.w2p_fw,td.w2p_fc {vertical-align:top} +td.w2p_fl {text-align:right} +td.w2p_fl, td.w2p_fw {padding-right:7px} +td.w2p_fl,td.w2p_fc {padding-top:4px} -/* tr#submit_record__row {border-top: 1px solid #E5E5E5;} */ -#submit_record__row td {padding-top: .5em;} +/* tr#submit_record__row {border-top:1px solid #E5E5E5} */ +#submit_record__row td {padding-top:.5em} /* Fix */ -#auth_user_remember__row label {display: inline;} -#web2py_user_form td { vertical-align:top; } +#auth_user_remember__row label {display:inline} +#web2py_user_form td {vertical-align:top} /*********** web2py specific ***********/ div.flash { - font-weight: bold; - display: none; - position: fixed; - padding: 10px; - top: 48px; - right: 50px; - min-width: 280px; - opacity: 0.85; - margin: 0px 0px 10px 10px; - color: #fff; - vertical-align: middle; - cursor: pointer; - background: #000; - border: 2px solid #fff; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - z-index: 2; + font-weight:bold; + display:none; + position:fixed; + padding:10px; + top:48px; + right:50px; + min-width:280px; + opacity:0.85; + margin:0px 0px 10px 10px; + color:#fff; + vertical-align:middle; + cursor:pointer; + background:#000; + border:2px solid #fff; + border-radius:5px; + -moz-border-radius:5px; + -webkit-border-radius:5px; + z-index:2000; } -div.flash {z-index:2000;} -div.error_wrapper { display: block; } +div.error_wrapper {display:block} div.error { - background-color: red; - color: white; - padding: 3px; - display: inline-block; + background-color:red; + color:white; + padding:3px; + display:inline-block; } .topbar { - padding: 10px 0; + padding:10px 0; width:100%; - color: #959595; - vertical-align: middle; - padding: auto; - background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222)); - background-image: -moz-linear-gradient(top, #333333, #222222); - background-image: -ms-linear-gradient(top, #333333, #222222); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222)); - background-image: -webkit-linear-gradient(top, #333333, #222222); - background-image: -o-linear-gradient(top, #333333, #222222); - background-image: linear-gradient(top, #333333, #222222); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + color:#959595; + vertical-align:middle; + padding:auto; + background-image:-khtml-gradient(linear,left top,left bottom,from(#333333),to(#222222)); + background-image:-moz-linear-gradient(top,#333333,#222222); + background-image:-ms-linear-gradient(top,#333333,#222222); + background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#333333),color-stop(100%,#222222)); + background-image:-webkit-linear-gradient(top,#333333,#222222); + background-image:-o-linear-gradient(top,#333333,#222222); + background-image:linear-gradient(top,#333333,#222222); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333',endColorstr='#222222',GradientType=0); + -webkit-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1); + -moz-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1); + box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1); } .topbar a { - color: #e1e1e1; + color:#e1e1e1; } -#navbar {float: right; padding: 5px; /* same as superfish */} - -.right { - width:100%; - text-align: right; - float: right; -} +#navbar {float:right; padding:5px; /* same as superfish */} .statusbar { - background-color: #F5F5F5; - margin-top: 1em; - margin-bottom: 1em; - padding: .5em 1em; - border: 1px solid #ddd; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; + background-color:#F5F5F5; + margin-top:1em; + margin-bottom:1em; + padding:.5em 1em; + border:1px solid #ddd; + border-radius:5px; + -moz-border-radius:5px; + -webkit-border-radius:5px; } -.breadcrumbs { float: left; } +.breadcrumbs {float:left} -.copyright {float: left;} -#poweredBy {float: right;} +.copyright {float:left} +#poweredBy {float:right} /* #MEDIA QUERIES SECTION */ /* All Mobile Sizes (devices and browser) */ - @media only screen and (max-width: 767px) { + @media only screen and (max-width:767px) { /* removed because of bootswatch - .topbar {text-align: center;} - #navbar, #menu {float: none;} - #navbar {font-size: 1.2em; padding: .6em 0 1.2em;} - #menu {padding: 0 0 1.5em;} - #menu select {font-size: 1.2em; margin: 0; padding: 0;} + .topbar {text-align:center} + #navbar,#menu {float:none} + #navbar {font-size:1.2em; padding:.6em 0 1.2em} + #menu {padding:0 0 1.5em} + #menu select {font-size:1.2em; margin:0; padding:0} - div.flash {top: 110px; right: 10px;} + div.flash {top:110px; right:10px} */ - } + } /* *Grid @@ -193,43 +184,47 @@ div.error { * will look better with the declarations below * if needed to remove base.css consider keeping these following lines in some css file. */ -// .web2py_table { border: 1px solid #ccc; } -.web2py_paginator { } -.web2py_grid {width: 100% } -.web2py_grid table { width: 100% } +// .web2py_table {border:1px solid #ccc} +.web2py_paginator {} +.web2py_grid {width:100%} +.web2py_grid table {width:100%} .web2py_grid tbody td { - padding: 2px 5px 2px 5px; - vertical-align: middle; + padding:2px 5px 2px 5px; + vertical-align:middle; } -.web2py_grid thead th, .web2py_grid tfoot td { +.web2py_grid thead th,.web2py_grid tfoot td { background-color:#EAEAEA; - padding: 10px 5px 10px 5px; + padding:10px 5px 10px 5px; } -.web2py_grid tr.odd {background-color: #F9F9F9;} -.web2py_grid tr:hover {background-color: #F5F5F5; } +.web2py_grid tr.odd {background-color:#F9F9F9} +.web2py_grid tr:hover {background-color:#F5F5F5} /* .web2py_breadcrumbs a { - line-height: 20px; margin-right: 5px; display: inline-block; - padding: 3px 5px 3px 5px; - font-family: 'lucida grande', tahoma, verdana, arial, sans-serif; - color: #3C3C3D; - text-shadow: 1px 1px 0 #FFFFFF; - white-space: nowrap; overflow: visible; cursor: pointer; + line-height:20px; margin-right:5px; display:inline-block; + padding:3px 5px 3px 5px; + font-family:'lucida grande',tahoma,verdana,arial,sans-serif; + color:#3C3C3D; + text-shadow:1px 1px 0 #FFFFFF; + white-space:nowrap; overflow:visible; cursor:pointer; background:#ECECEC; - border: 1px solid #CACACA; - -webkit-border-radius: 2px; -moz-border-radius: 2px; - -webkit-background-clip: padding-box; border-radius: 2px; - outline: none; position: relative; zoom: 1; *display: inline; + border:1px solid #CACACA; + -webkit-border-radius:2px; -moz-border-radius:2px; + -webkit-background-clip:padding-box; border-radius:2px; + outline:none; position:relative; zoom:1; *display:inline; } */ .web2py_console form { width:100%; + display:inline; } +.web2py_console form select { + margin:0; +} .web2py_search_actions{ float:left; @@ -238,14 +233,14 @@ div.error { .web2py_grid .row_buttons { min-height:25px; - vertical-align: middle; + vertical-align:middle; } .web2py_grid .row_buttons a { - margin: 3px; + margin:3px; } .web2py_search_actions { - width: 100%; + width:100%; } .web2py_grid .row_buttons a, @@ -254,13 +249,13 @@ div.error { .web2py_console input[type=submit], .web2py_console input[type=button], .web2py_console button { - line-height: 20px; - margin-right: 5px; display: inline-block; - padding: 3px 5px 3px 5px; + line-height:20px; + margin-right:5px; display:inline-block; + padding:3px 5px 3px 5px; } .web2py_counter { - margin-top: 5px; + margin-top:5px; margin-right:5px; width:35%; float:right; @@ -268,37 +263,37 @@ div.error { } /*Fix firefox problem*/ -.web2py_table {clear: both; display: block;} +.web2py_table {clear:both; display:block} .web2py_paginator { - padding: 5px; + padding:5px; text-align:right; - background-color: #f2f2f2; + background-color:#f2f2f2; } .web2py_paginator ul { - list-style-type: none; - margin: 0px; - padding: 0px; + list-style-type:none; + margin:0px; + padding:0px; } .web2py_paginator ul li { - display: inline; + display:inline; } .web2py_paginator .current { - font-weight: bold; + font-weight:bold; } #w2p_query_panel {} .web2py_breadcrumbs ul { - list-style: none; - margin-bottom: 18px; + list-style:none; + margin-bottom:18px; } .web2py_breadcrumbs ul li { - display: inline-block; + display:inline-block; } -.ie9 #query_panel {padding-bottom:2px;} +.ie9 #query_panel {padding-bottom:2px} diff --git a/applications/examples/static/js/web2py.js b/applications/examples/static/js/web2py.js index eb1e3b09..9a2e208c 100644 --- a/applications/examples/static/js/web2py.js +++ b/applications/examples/static/js/web2py.js @@ -44,6 +44,12 @@ function web2py_event_handlers() { doc.on('keyup', 'input.double, input.decimal', function(){this.value=this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g,'').reverse();}); 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(!confirm(confirm_message)) this.checked=false;}); + doc.ajaxSuccess(function(e, xhr) { + var redirect=xhr.getResponseHeader('web2py-redirect-location'); + if (redirect != null) { + window.location = redirect; + }; + }); }; jQuery(function() { @@ -98,8 +104,8 @@ function web2py_ajax_page(method, action, data, target) { eval(decodeURIComponent(command)); if(flash) jQuery('.flash').html(decodeURIComponent(flash)).slideDown(); - } - }); + } + }); } function web2py_component(action, target, timeout, times){ diff --git a/applications/examples/views/appadmin.html b/applications/examples/views/appadmin.html index 73c4ae47..1d967c2f 100644 --- a/applications/examples/views/appadmin.html +++ b/applications/examples/views/appadmin.html @@ -29,7 +29,7 @@ {{pass}} {{pass}}

- {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}} + {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}}

[ {{=A(str(T('insert new'))+' '+table,_href=URL('insert',args=[db,table]))}} ]

@@ -50,7 +50,7 @@ {{=T('Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.')}}
{{=T('"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN')}}



-

{{=nrows}} {{=T("selected")}}

+

{{=T("%s selected", nrows)}}

{{if start>0:}}[ {{=A(T('previous 100 rows'),_href=URL('select',args=request.args[0],vars=dict(start=start-100)))}} ]{{pass}} {{if stop

{{=T("Import/Export")}}


[ {{=T("export as csv file")}} ] - {{if table:}} - {{=FORM(str(T('or import from csv file'))+" ",INPUT(_type='file',_name='csvfile'),INPUT(_type='hidden',_value=table,_name='table'),INPUT(_type='submit',_value=T('import')))}} - {{pass}} - + {{=formcsv or ''}} {{elif request.function=='insert':}}

{{=T("database")}} {{=A(request.args[0],_href=URL('index'))}} @@ -108,40 +105,34 @@ {{elif request.function == 'ccache':}} -

Cache

+

{{T("Cache")}}

-

Statistics

+

{{T("Statistics")}}

-

Overview

-

Number of entries: {{=total['entries']}} - {{if total['entries'] > 0:}} -

+

{{=T("Overview")}}

+

{{=T.M("Number of entries: **%s**", total['entries'])}}

+ {{if total['entries'] > 0:}} +

{{=T.M("Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses})", + dict(ratio=total['ratio'], hits=total['hits'], misses=total['misses']))}} +

- Hit Ratio: - {{=total['ratio']}}% - ({{=total['hits']}} hits - and {{=total['misses']}} misses) -

-

- Size of cache: + {{=T("Size of cache:")}} {{if object_stats:}} - {{=total['objects']}} items, - {{=total['bytes']}} bytes - {{if total['bytes'] > 524287:}} - ({{="%.0d" % (total['bytes'] / 1048576)}} MB) - {{pass}} - {{else:}} not available (requires the Python guppy library) + {{=T.M("**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}", dict(items=total['objects'], bytes=total['bytes']))}} + {{if total['bytes'] > 524287:}} + {{=T.M("(**%.0d MB**)", total['bytes'] / 1048576)}} + {{pass}} + {{else:}} + {{=T.M("**not available** (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)")}} {{pass}}

- Cache contains items up to - {{="%02d" % total['oldest'][0]}} hours - {{="%02d" % total['oldest'][1]}} minutes - {{="%02d" % total['oldest'][2]}} seconds old. + {{=T.M("Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.", + dict(hours=total['oldest'][0], min=total['oldest'][1], sec=total['oldest'][2]))}}

{{=BUTTON(T('Cache Keys'), _onclick='jQuery("#all_keys").toggle();')}}
diff --git a/applications/examples/views/layout.html b/applications/examples/views/layout.html index 0f5cc8d8..e08c8e11 100644 --- a/applications/examples/views/layout.html +++ b/applications/examples/views/layout.html @@ -122,7 +122,7 @@
\w+)\.id\>0') regex = re.compile(request.args[0] + '\.(?P
\w+)\..+') - match = regex.match(form.vars.query.strip()) if match: table = match.group('table') @@ -230,6 +221,23 @@ def select(): except Exception, e: (rows, nrows) = ([], 0) response.flash = DIV(T('Invalid Query'),PRE(str(e))) + # begin handle upload csv + if table: + formcsv = FORM(str(T('or import from csv file'))+" ", + INPUT(_type='file',_name='csvfile'), + INPUT(_type='hidden',_value=table,_name='table'), + INPUT(_type='submit',_value=T('import'))) + else: + formcsv = None + if formcsv and formcsv.process().accepted and request.vars.csvfile: + try: + import_csv(db[request.vars.table], + request.vars.csvfile.file) + response.flash = T('data uploaded') + except Exception, e: + response.flash = DIV(T('unable to parse csv file'),PRE(str(e))) + # end handle upload csv + return dict( form=form, table=table, @@ -238,6 +246,7 @@ def select(): nrows=nrows, rows=rows, query=request.vars.query, + formcsv = formcsv, ) diff --git a/applications/welcome/languages/plural-ru.py b/applications/welcome/languages/plural-ru.py index 6cb20bd0..61499183 100644 --- a/applications/welcome/languages/plural-ru.py +++ b/applications/welcome/languages/plural-ru.py @@ -6,4 +6,11 @@ 'изменена': ['изменены','изменено'], 'строка': ['строки','строк'], 'удалена': ['удалены','удалено'], +'день': ['дня', 'дней'], +'месяц': ['месяца','месяцев'], +'неделю': ['недели','недель'], +'год': ['года','лет'], +'час': ['часа','часов'], +'минуту': ['минуты','минут'], +'секунду': ['секунды','секунд'], } diff --git a/applications/welcome/languages/plural-uk.py b/applications/welcome/languages/plural-uk.py index 3679be13..f00be815 100644 --- a/applications/welcome/languages/plural-uk.py +++ b/applications/welcome/languages/plural-uk.py @@ -10,4 +10,8 @@ 'секунду': ['секунди','секунд'], 'схибнення': ['схибнення','схибнень'], 'хвилину': ['хвилини','хвилин'], +'день': ['дні', 'днів'], +'місяць': ['місяці','місяців'], +'тиждень': ['тижні','тижнів'], +'рік': ['роки','років'], } diff --git a/applications/welcome/languages/ru.py b/applications/welcome/languages/ru.py index 79a03d06..8782bb9a 100644 --- a/applications/welcome/languages/ru.py +++ b/applications/welcome/languages/ru.py @@ -3,11 +3,25 @@ '!langcode!': 'ru', '!langname!': 'Русский', '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"Изменить" - необязательное выражение вида "field1=\'новое значение\'". Результаты операции JOIN нельзя изменить или удалить.', +'%d days ago': '%d %%{день} тому', +'%d hours ago': '%d %%{час} тому', +'%d minutes ago': '%d %%{минуту} тому', +'%d months ago': '%d %%{месяц} тому', +'%d seconds ago': '%d %%{секунду} тому', +'%d weeks ago': '%d %%{неделю} тому', +'%d years ago': '%d %%{год} тому', '%s %%{row} deleted': '%%{!удалена[0]} %s %%{строка[0]}', '%s %%{row} updated': '%%{!изменена[0]} %s %%{строка[0]}', '%s selected': '%%{!выбрана[0]} %s %%{запись[0]}', '%Y-%m-%d': '%Y-%m-%d', '%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S', +'1 day ago': '1 день тому', +'1 hour ago': '1 час тому', +'1 minute ago': '1 минуту тому', +'1 month ago': '1 месяц тому', +'1 second ago': '1 секунду тому', +'1 week ago': '1 неделю тому', +'1 year ago': '1 год тому', 'About': 'About', 'Access Control': 'Access Control', 'Administrative Interface': 'Administrative Interface', @@ -31,8 +45,8 @@ 'Current session': 'Текущая сессия', 'customize me!': 'настройте внешний вид!', 'data uploaded': 'данные загружены', -'Database': 'Database', 'database': 'база данных', +'Database': 'Database', 'database %s select': 'выбор базы данных %s', 'db': 'БД', 'DB Model': 'DB Model', @@ -93,6 +107,7 @@ 'new record inserted': 'новая запись добавлена', 'next 100 rows': 'следующие 100 строк', 'No databases in this application': 'В приложении нет баз данных', +'now': 'сейчас', 'Object or table name': 'Object or table name', 'Old password': 'Старый пароль', 'Online examples': 'примеры он-лайн', diff --git a/applications/welcome/languages/uk.py b/applications/welcome/languages/uk.py index 23b1e8ab..1bf341e2 100644 --- a/applications/welcome/languages/uk.py +++ b/applications/welcome/languages/uk.py @@ -3,11 +3,25 @@ '!langcode!': 'uk', '!langname!': 'Українська', '"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"Оновити" це додатковий вираз, такий, як "field1=\'нове_значення\'". Ви не можете змінювати або вилучати дані об\'єднаних таблиць.', +'%d days ago': '%d %%{день} тому', +'%d hours ago': '%d %%{годину} тому', +'%d minutes ago': '%d %%{хвилину} тому', +'%d months ago': '%d %%{місяць} тому', +'%d secods ago': '%d %%{секунду} тому', +'%d weeks ago': '%d %%{тиждень} тому', +'%d years ago': '%d %%{рік} тому', '%s %%{row} deleted': 'Вилучено %s %%{рядок}', '%s %%{row} updated': 'Змінено %s %%{рядок}', '%s selected': 'Вибрано %s %%{запис}', '%Y-%m-%d': '%Y/%m/%d', '%Y-%m-%d %H:%M:%S': '%Y/%m/%d %H:%M:%S', +'1 day ago': '1 день тому', +'1 hour ago': '1 годину тому', +'1 minute ago': '1 хвилину тому', +'1 month ago': '1 місяць тому', +'1 second ago': '1 секунду тому', +'1 week ago': '1 тиждень тому', +'1 year ago': '1 рік тому', '@markmin\x01(**%.0d MB**)': '(**``%.0d``:red МБ**)', '@markmin\x01**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}': '**%(items)s** %%{елемент(items)}, **%(bytes)s** %%{байт(bytes)}', '@markmin\x01``**not available**``:red (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)': '**нема в наявності** (потребує Пітонівської бібліотеки [[guppy {посилання відкриється у новому вікні} http://pypi.python.org/pypi/guppy/ popup]])', @@ -115,6 +129,7 @@ 'new record inserted': 'новий рядок додано', 'next 100 rows': 'наступні 100 рядків', 'No databases in this application': 'Даний додаток не використовує базу даних', +'now': 'зараз', 'Object or table name': "Об'єкт або назва таблиці", 'Old password': 'Старий пароль', 'Online examples': 'Зразковий демо-сайт', diff --git a/applications/welcome/models/menu.py b/applications/welcome/models/menu.py index 8a9ebe4a..784f4a4a 100644 --- a/applications/welcome/models/menu.py +++ b/applications/welcome/models/menu.py @@ -13,7 +13,6 @@ response.meta.author = 'Your Name ' response.meta.description = 'a cool new app' response.meta.keywords = 'web2py, python, framework' response.meta.generator = 'Web2py Web Framework' -response.meta.copyright = 'Copyright 2011' ## your http://google.com/analytics id response.google_analytics_id = None @@ -36,7 +35,7 @@ def _(): ctr = request.controller # useful links to internal and external resources response.menu+=[ - (SPAN('web2py',_style='color:yellow'),False, None, [ + (SPAN('web2py',_style='color:yellow'),False, 'http://web2py.com', [ (T('My Sites'),False,URL('admin','default','site')), (T('This App'),False,URL('admin','default','design/%s' % app), [ (T('Controller'),False, diff --git a/applications/welcome/static/css/bootswatch.css b/applications/welcome/static/css/bootswatch.css index af8b7ff6..de65e658 100644 --- a/applications/welcome/static/css/bootswatch.css +++ b/applications/welcome/static/css/bootswatch.css @@ -1,112 +1,130 @@ -#navbar{padding-top:9px;} +body { + padding-top: 60px; +} + #navbar .auth_navbar, #navbar .auth_navbar a {color:inherit;} -@media only screen and (max-width: 479px) { - div.flash { - right: 5px; - } +/* bootstrap dropdown */ + +.dropdown-menu ul { + left: 100%; + position: absolute; + top: 0; + visibility: hidden; + margin-top: -1px; } -@media only screen and (max-width: 767px) { +.dropdown-menu li:hover ul { + visibility: visible; +} + +.mastheader h1 { + margin-bottom: 9px; + font-size: 81px; + font-weight: bold; + letter-spacing: -1px; + line-height: 1; +} + +.mastheader h1 { + font-size: 54px; +} + +.mastheader small { + font-size: 20px; + font-weight: 300; +} + +.navbar .dropdown-menu ul:before { + border-bottom: 7px solid transparent; + border-left: none; + border-right: 7px solid rgba(0, 0, 0, 0.2); + border-top: 7px solid transparent; + left: -7px; + top: 5px; +} + +.navbar .dropdown-menu ul:after { + border-top: 6px solid transparent; + border-left: none; + border-right: 6px solid #fff; + border-bottom: 6px solid transparent; + left: 10px; + top: 6px; + left: -6px; +} + +.dropdown-menu span{ + display:inline-block; +} + +.chevron-right { + border-left: 4px solid #000; + border-right: 4px solid transparent; + border-bottom: 4px solid transparent; + border-top: 4px solid transparent; + content: ""; + display: inline-block; + height: 0; + opacity: 0.7; + vertical-align: top; + width: 0; + margin-right:-13px; + margin-top: 7px; + float:right; +} + +.open > .dropdown-menu ul { /* fix menu issue when BS2.0.4 is applied */ + display: block; +} + +.ie-lte7 #navbar .auth_navbar, #navbar .auth_navbar a {color:expression(this.parentNode.currentStyle['color']); /* ie7 doesn't support inherit */} + +#navbar .auth_navbar a:hover {color:white;text-decoration:none;} /* this overwrite bootswatch */ + +body { + height:auto; /*to avoid vertical scroll bar*/ +} + +h1,h2,h3,h4,h5,h6 {font-family: inherit;} + +li {margin-bottom: 0;} /*bootswatch*/ + +.auth_navbar, .navbar .btn-group { padding:0; } + +[class^="icon-"],[class*=" icon-"]{background-image:url("../images/glyphicons-halflings.png")} /* right folder for bootstrap black images/icons */ +.icon-white{background-image:url("../images/glyphicons-halflings-white.png");} /* right folder for bootstrap white images/icons */ + +@media only screen and (max-width: 979px) { + body { + padding-top: 0px; + } + .navbar-inner{position:relative;} #navbar{bottom:-10px;left:4px;} + + div.flash { + right: 5px; + } + + .dropdown-menu ul { + visibility: visible; + } + } -@media only screen and (min-width: 768px) { - body { - height:auto; /*to avoid vertical scroll bar*/ - } - - h1,h2,h3,h4,h5,h6 {font-family: inherit;} - - li {margin-bottom: 0;} /*bootswatch*/ - - .auth_navbar, .navbar .btn-group{padding:0;} - - .mastheader h1 { - margin-bottom: 9px; - font-size: 81px; - font-weight: bold; - letter-spacing: -1px; - line-height: 1; - } - - .mastheader h1 { - font-size: 54px; - } - - .mastheader small { - font-size: 20px; - font-weight: 300; - } - - /* bootstrap dropdown */ - - .dropdown-menu ul { - left: 100%; - position: absolute; - top: 0; - visibility: hidden; - margin-top: -1px; - } - - .dropdown-menu li:hover ul { - visibility: visible; - } - - .navbar .dropdown-menu ul:before { - border-bottom: 7px solid transparent; - border-left: none; - border-right: 7px solid rgba(0, 0, 0, 0.2); - border-top: 7px solid transparent; - left: -7px; - top: 5px; - } - - .navbar .dropdown-menu ul:after { - border-top: 6px solid transparent; - border-left: none; - border-right: 6px solid #fff; - border-bottom: 6px solid transparent; - left: 10px; - top: 6px; - left: -6px; - } - - .dropdown-menu span{ - display:inline-block; - } - - .chevron-right { - border-left: 4px solid #000; - border-right: 4px solid transparent; - border-bottom: 4px solid transparent; - border-top: 4px solid transparent; - content: ""; - display: inline-block; - height: 0; - opacity: 0.7; - vertical-align: top; - width: 0; - margin-right:-13px; - margin-top: 7px; - float:right; - } - - .open > .dropdown-menu ul { /* fix menu issue when BS2.0.4 is applied */ - display: block; - } - - .ie-lte7 #navbar .auth_navbar, #navbar .auth_navbar a {color:expression(this.parentNode.currentStyle['color']); /* ie7 doesn't support inherit */} - - #navbar .auth_navbar a:hover {color:white;text-decoration:none;} /* this overwrite bootswatch */ - - [class^="icon-"],[class*=" icon-"]{background-image:url("../images/glyphicons-halflings.png")} /* right folder for bootstrap black images/icons */ - .icon-white{background-image:url("../images/glyphicons-halflings-white.png");} /* right folder for bootstrap white images/icons */ -} - -@media only screen and (min-width: 980px) { - body { - padding-top: 60px; - } +@media only screen and (max-width: 479px) { + body { + padding-left: 10px; + padding-right: 10px; + } + + .navbar-fixed-top, .navbar-fixed-bottom { + margin-left: -10px; + margin-right: -10px; + } + + input[type="text"], input[type="password"], select { + width: 95%; + } } diff --git a/applications/welcome/static/css/web2py.css b/applications/welcome/static/css/web2py.css index b6ae2a25..5b645cc4 100644 --- a/applications/welcome/static/css/web2py.css +++ b/applications/welcome/static/css/web2py.css @@ -1,187 +1,181 @@ /** these MUST stay **/ -a { text-decoration:none; white-space: nowrap;} -a:hover {text-decoration: underline} -a.button {text-decoration: none} -h1,h2,h3,h4,h5,h6 {margin: 0.5em 0 0.25em 0; display: block; font-family: Helvetica;} - h1 { font-size: 4.00em;} - h2 { font-size: 3.00em;} - h3 { font-size: 2.00em;} - h4 { font-size: 1.50em;} - h5 { font-size: 1.25em;} - h6 { font-size: 1.12em;} -right { float:right; text-align: right; } -left { float:left; text-align: left; } -center { width:100; text-align: center; vertical-align:middle;} -th, label { font-weight: bold; white-space: nowrap; } -td, th { text-align: left; padding: 2px 5px 2px 5px; } -th { vertical-align: middle; border-right: 1px solid white;} -td { vertical-align: top; } -form table tr td label { text-align: left; } -p, table, ol, ul { padding: 0.5em 0 0.5em 0 } -p {text-align: justify } -ol, ul { padding-left: 30px } -li { margin-bottom: 0.5em; } -span, input, select, textarea, button, label, a { display: inline } -img { border: 0; } -blockquote, blockquote p, p blockquote { font-style: italic; margin: 0.5em 30px 0.5em 30px; font-size: 0.9em} -i, em { font-style: italic; } -strong { font-weight: bold; } -small { font-size: 0.8em; } -textarea { width: 100%; } -code { font-family: Courier;} -video { width:400px; } -audio { width:200px; } -input[type=text], input[type=password], select { width: 300px; margin-right: 5px } -ul { list-style-type: none; margin: 0px; padding: 0px; } +a {text-decoration:none; white-space:nowrap} +a:hover {text-decoration:underline} +a.button {text-decoration:none} +h1,h2,h3,h4,h5,h6 {margin:0.5em 0 0.25em 0; display:block; + font-family:Helvetica} +h1 {font-size:4.00em} +h2 {font-size:3.00em} +h3 {font-size:2.00em} +h4 {font-size:1.50em} +h5 {font-size:1.25em} +h6 {font-size:1.12em} +th,label {font-weight:bold; white-space:nowrap} +td,th {text-align:left; padding:2px 5px 2px 5px} +th {vertical-align:middle; border-right:1px solid white} +td {vertical-align:top} +form table tr td label {text-align:left} +p,table,ol,ul {padding:0; margin: 0.5em 0} +p {text-align:justify} +ol, ul {list-style-position:inside} +li {margin-bottom:0.5em} +span,input,select,textarea,button,label,a {display:inline} +img {border:0} +blockquote,blockquote p,p blockquote { + font-style:italic; margin:0.5em 30px 0.5em 30px; font-size:0.9em} +i,em {font-style:italic} +strong {font-weight:bold} +small {font-size:0.8em} +code {font-family:Courier} +textarea {width:100%} +video {width:400px} +audio {width:200px} +input[type=text],input[type=password],select{width:300px; margin-right:5px} .hidden {display:none;visibility:visible} +.right {float:right; text-align:right} +.left {float:left; text-align:left} +.center {width:100; text-align:center; vertical-align:middle} /** end **/ /* Sticky footer begin */ .wrapper { - min-height: 100%; - height: auto !important; - height: 100%; - margin: 0 auto -8em; /* set last value to footer height plus footer vertical padding */ + min-height:100%; + height:auto !important; + height:100%; + margin:0 auto -8em; /* set last value to footer height plus footer vertical padding */ } .main { - padding: 20px 0 50px 0; + padding:20px 0 50px 0; } -.footer, .push { - height: 6em; - padding: 1em 0; - clear: both; +.footer,.push { + height:6em; + padding:1em 0; + clear:both; } -.footer-content {position: relative; bottom: -4em; width: 100%;} +.footer-content {position:relative; bottom:-4em; width:100%} .auth_navbar { - white-space: nowrap; + white-space:nowrap; } /* Sticky footer end */ .footer { - border-top: 1px #DEDEDE solid; + border-top:1px #DEDEDE solid; } .header { - // background: ; + // background:; } -fieldset { padding: 16px; border-top: 1px #DEDEDE solid;} -fieldset legend {text-transform:uppercase; font-weight: bold; padding: 4px 16px 4px 16px; background: #f1f1f1;} +fieldset {padding:16px; border-top:1px #DEDEDE solid} +fieldset legend {text-transform:uppercase; font-weight:bold; padding:4px 16px 4px 16px; background:#f1f1f1} /* fix ie problem with menu */ -.ie-lte7 .topbar .container {z-index: 2; } +.ie-lte7 .topbar .container {z-index:2} -td.w2p_fw {padding-bottom: 1px;} -td.w2p_fl, td.w2p_fw, td.w2p_fc { vertical-align:top; } -td.w2p_fl { text-align:right; } -td.w2p_fl, td.w2p_fw {padding-right: 7px;} -td.w2p_fl, td.w2p_fc { padding-top: 4px; } +td.w2p_fw {padding-bottom:1px} +td.w2p_fl,td.w2p_fw,td.w2p_fc {vertical-align:top} +td.w2p_fl {text-align:right} +td.w2p_fl, td.w2p_fw {padding-right:7px} +td.w2p_fl,td.w2p_fc {padding-top:4px} -/* tr#submit_record__row {border-top: 1px solid #E5E5E5;} */ -#submit_record__row td {padding-top: .5em;} +/* tr#submit_record__row {border-top:1px solid #E5E5E5} */ +#submit_record__row td {padding-top:.5em} /* Fix */ -#auth_user_remember__row label {display: inline;} -#web2py_user_form td { vertical-align:top; } +#auth_user_remember__row label {display:inline} +#web2py_user_form td {vertical-align:top} /*********** web2py specific ***********/ div.flash { - font-weight: bold; - display: none; - position: fixed; - padding: 10px; - top: 48px; - right: 50px; - min-width: 280px; - opacity: 0.85; - margin: 0px 0px 10px 10px; - color: #fff; - vertical-align: middle; - cursor: pointer; - background: #000; - border: 2px solid #fff; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - z-index: 2; + font-weight:bold; + display:none; + position:fixed; + padding:10px; + top:48px; + right:50px; + min-width:280px; + opacity:0.85; + margin:0px 0px 10px 10px; + color:#fff; + vertical-align:middle; + cursor:pointer; + background:#000; + border:2px solid #fff; + border-radius:5px; + -moz-border-radius:5px; + -webkit-border-radius:5px; + z-index:2000; } -div.flash {z-index:2000;} -div.error_wrapper { display: block; } +div.error_wrapper {display:block} div.error { - background-color: red; - color: white; - padding: 3px; - display: inline-block; + background-color:red; + color:white; + padding:3px; + display:inline-block; } .topbar { - padding: 10px 0; + padding:10px 0; width:100%; - color: #959595; - vertical-align: middle; - padding: auto; - background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222)); - background-image: -moz-linear-gradient(top, #333333, #222222); - background-image: -ms-linear-gradient(top, #333333, #222222); - background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222)); - background-image: -webkit-linear-gradient(top, #333333, #222222); - background-image: -o-linear-gradient(top, #333333, #222222); - background-image: linear-gradient(top, #333333, #222222); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); - -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25), inset 0 -1px 0 rgba(0, 0, 0, 0.1); + color:#959595; + vertical-align:middle; + padding:auto; + background-image:-khtml-gradient(linear,left top,left bottom,from(#333333),to(#222222)); + background-image:-moz-linear-gradient(top,#333333,#222222); + background-image:-ms-linear-gradient(top,#333333,#222222); + background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#333333),color-stop(100%,#222222)); + background-image:-webkit-linear-gradient(top,#333333,#222222); + background-image:-o-linear-gradient(top,#333333,#222222); + background-image:linear-gradient(top,#333333,#222222); + filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333',endColorstr='#222222',GradientType=0); + -webkit-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1); + -moz-box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1); + box-shadow:0 1px 3px rgba(0,0,0,0.25),inset 0 -1px 0 rgba(0,0,0,0.1); } .topbar a { - color: #e1e1e1; + color:#e1e1e1; } -#navbar {float: right; padding: 5px; /* same as superfish */} - -.right { - width:100%; - text-align: right; - float: right; -} +#navbar {float:right; padding:5px; /* same as superfish */} .statusbar { - background-color: #F5F5F5; - margin-top: 1em; - margin-bottom: 1em; - padding: .5em 1em; - border: 1px solid #ddd; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; + background-color:#F5F5F5; + margin-top:1em; + margin-bottom:1em; + padding:.5em 1em; + border:1px solid #ddd; + border-radius:5px; + -moz-border-radius:5px; + -webkit-border-radius:5px; } -.breadcrumbs { float: left; } +.breadcrumbs {float:left} -.copyright {float: left;} -#poweredBy {float: right;} +.copyright {float:left} +#poweredBy {float:right} /* #MEDIA QUERIES SECTION */ /* All Mobile Sizes (devices and browser) */ - @media only screen and (max-width: 767px) { + @media only screen and (max-width:767px) { /* removed because of bootswatch - .topbar {text-align: center;} - #navbar, #menu {float: none;} - #navbar {font-size: 1.2em; padding: .6em 0 1.2em;} - #menu {padding: 0 0 1.5em;} - #menu select {font-size: 1.2em; margin: 0; padding: 0;} + .topbar {text-align:center} + #navbar,#menu {float:none} + #navbar {font-size:1.2em; padding:.6em 0 1.2em} + #menu {padding:0 0 1.5em} + #menu select {font-size:1.2em; margin:0; padding:0} - div.flash {top: 110px; right: 10px;} + div.flash {top:110px; right:10px} */ - } + } /* *Grid @@ -190,46 +184,46 @@ div.error { * will look better with the declarations below * if needed to remove base.css consider keeping these following lines in some css file. */ -// .web2py_table { border: 1px solid #ccc; } -.web2py_paginator { } -.web2py_grid {width: 100% } -.web2py_grid table { width: 100% } +// .web2py_table {border:1px solid #ccc} +.web2py_paginator {} +.web2py_grid {width:100%} +.web2py_grid table {width:100%} .web2py_grid tbody td { - padding: 2px 5px 2px 5px; - vertical-align: middle; + padding:2px 5px 2px 5px; + vertical-align:middle; } -.web2py_grid thead th, .web2py_grid tfoot td { +.web2py_grid thead th,.web2py_grid tfoot td { background-color:#EAEAEA; - padding: 10px 5px 10px 5px; + padding:10px 5px 10px 5px; } -.web2py_grid tr.odd {background-color: #F9F9F9;} -.web2py_grid tr:hover {background-color: #F5F5F5; } +.web2py_grid tr.odd {background-color:#F9F9F9} +.web2py_grid tr:hover {background-color:#F5F5F5} /* .web2py_breadcrumbs a { - line-height: 20px; margin-right: 5px; display: inline-block; - padding: 3px 5px 3px 5px; - font-family: 'lucida grande', tahoma, verdana, arial, sans-serif; - color: #3C3C3D; - text-shadow: 1px 1px 0 #FFFFFF; - white-space: nowrap; overflow: visible; cursor: pointer; + line-height:20px; margin-right:5px; display:inline-block; + padding:3px 5px 3px 5px; + font-family:'lucida grande',tahoma,verdana,arial,sans-serif; + color:#3C3C3D; + text-shadow:1px 1px 0 #FFFFFF; + white-space:nowrap; overflow:visible; cursor:pointer; background:#ECECEC; - border: 1px solid #CACACA; - -webkit-border-radius: 2px; -moz-border-radius: 2px; - -webkit-background-clip: padding-box; border-radius: 2px; - outline: none; position: relative; zoom: 1; *display: inline; + border:1px solid #CACACA; + -webkit-border-radius:2px; -moz-border-radius:2px; + -webkit-background-clip:padding-box; border-radius:2px; + outline:none; position:relative; zoom:1; *display:inline; } */ .web2py_console form { width:100%; - display: inline; + display:inline; } .web2py_console form select { - margin: 0; + margin:0; } .web2py_search_actions{ @@ -239,14 +233,14 @@ div.error { .web2py_grid .row_buttons { min-height:25px; - vertical-align: middle; + vertical-align:middle; } .web2py_grid .row_buttons a { - margin: 3px; + margin:3px; } .web2py_search_actions { - width: 100%; + width:100%; } .web2py_grid .row_buttons a, @@ -255,13 +249,13 @@ div.error { .web2py_console input[type=submit], .web2py_console input[type=button], .web2py_console button { - line-height: 20px; - margin-right: 5px; display: inline-block; - padding: 3px 5px 3px 5px; + line-height:20px; + margin-right:5px; display:inline-block; + padding:3px 5px 3px 5px; } .web2py_counter { - margin-top: 5px; + margin-top:5px; margin-right:5px; width:35%; float:right; @@ -269,37 +263,37 @@ div.error { } /*Fix firefox problem*/ -.web2py_table {clear: both; display: block;} +.web2py_table {clear:both; display:block} .web2py_paginator { - padding: 5px; + padding:5px; text-align:right; - background-color: #f2f2f2; + background-color:#f2f2f2; } .web2py_paginator ul { - list-style-type: none; - margin: 0px; - padding: 0px; + list-style-type:none; + margin:0px; + padding:0px; } .web2py_paginator ul li { - display: inline; + display:inline; } .web2py_paginator .current { - font-weight: bold; + font-weight:bold; } #w2p_query_panel {} .web2py_breadcrumbs ul { - list-style: none; - margin-bottom: 18px; + list-style:none; + margin-bottom:18px; } .web2py_breadcrumbs ul li { - display: inline-block; + display:inline-block; } -.ie9 #query_panel {padding-bottom:2px;} +.ie9 #query_panel {padding-bottom:2px} diff --git a/applications/welcome/static/favicon.ico b/applications/welcome/static/images/favicon.ico similarity index 100% rename from applications/welcome/static/favicon.ico rename to applications/welcome/static/images/favicon.ico diff --git a/applications/welcome/static/favicon.png b/applications/welcome/static/images/favicon.png similarity index 100% rename from applications/welcome/static/favicon.png rename to applications/welcome/static/images/favicon.png diff --git a/applications/welcome/static/js/web2py.js b/applications/welcome/static/js/web2py.js index eb1e3b09..9a2e208c 100644 --- a/applications/welcome/static/js/web2py.js +++ b/applications/welcome/static/js/web2py.js @@ -44,6 +44,12 @@ function web2py_event_handlers() { doc.on('keyup', 'input.double, input.decimal', function(){this.value=this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g,'').reverse();}); 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(!confirm(confirm_message)) this.checked=false;}); + doc.ajaxSuccess(function(e, xhr) { + var redirect=xhr.getResponseHeader('web2py-redirect-location'); + if (redirect != null) { + window.location = redirect; + }; + }); }; jQuery(function() { @@ -98,8 +104,8 @@ function web2py_ajax_page(method, action, data, target) { eval(decodeURIComponent(command)); if(flash) jQuery('.flash').html(decodeURIComponent(flash)).slideDown(); - } - }); + } + }); } function web2py_component(action, target, timeout, times){ diff --git a/applications/welcome/static/robots.txt b/applications/welcome/static/robots.txt deleted file mode 100644 index 8cb06798..00000000 --- a/applications/welcome/static/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: /welcome/default/user diff --git a/applications/welcome/views/appadmin.html b/applications/welcome/views/appadmin.html index 73c4ae47..1d967c2f 100644 --- a/applications/welcome/views/appadmin.html +++ b/applications/welcome/views/appadmin.html @@ -29,7 +29,7 @@ {{pass}} {{pass}}

- {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}} + {{=A("%s.%s" % (db,table),_href=URL('select',args=[db],vars=dict(query=qry)))}}

[ {{=A(str(T('insert new'))+' '+table,_href=URL('insert',args=[db,table]))}} ]

@@ -50,7 +50,7 @@ {{=T('Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.')}}
{{=T('"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN')}}



-

{{=nrows}} {{=T("selected")}}

+

{{=T("%s selected", nrows)}}

{{if start>0:}}[ {{=A(T('previous 100 rows'),_href=URL('select',args=request.args[0],vars=dict(start=start-100)))}} ]{{pass}} {{if stop

{{=T("Import/Export")}}


[
{{=T("export as csv file")}} ] - {{if table:}} - {{=FORM(str(T('or import from csv file'))+" ",INPUT(_type='file',_name='csvfile'),INPUT(_type='hidden',_value=table,_name='table'),INPUT(_type='submit',_value=T('import')))}} - {{pass}} - + {{=formcsv or ''}} {{elif request.function=='insert':}}

{{=T("database")}} {{=A(request.args[0],_href=URL('index'))}} @@ -108,40 +105,34 @@ {{elif request.function == 'ccache':}} -

Cache

+

{{T("Cache")}}

-

Statistics

+

{{T("Statistics")}}

-

Overview

-

Number of entries: {{=total['entries']}} - {{if total['entries'] > 0:}} -

+

{{=T("Overview")}}

+

{{=T.M("Number of entries: **%s**", total['entries'])}}

+ {{if total['entries'] > 0:}} +

{{=T.M("Hit Ratio: **%(ratio)s%%** (**%(hits)s** %%{hit(hits)} and **%(misses)s** %%{miss(misses})", + dict(ratio=total['ratio'], hits=total['hits'], misses=total['misses']))}} +

- Hit Ratio: - {{=total['ratio']}}% - ({{=total['hits']}} hits - and {{=total['misses']}} misses) -

-

- Size of cache: + {{=T("Size of cache:")}} {{if object_stats:}} - {{=total['objects']}} items, - {{=total['bytes']}} bytes - {{if total['bytes'] > 524287:}} - ({{="%.0d" % (total['bytes'] / 1048576)}} MB) - {{pass}} - {{else:}} not available (requires the Python guppy library) + {{=T.M("**%(items)s** %%{item(items)}, **%(bytes)s** %%{byte(bytes)}", dict(items=total['objects'], bytes=total['bytes']))}} + {{if total['bytes'] > 524287:}} + {{=T.M("(**%.0d MB**)", total['bytes'] / 1048576)}} + {{pass}} + {{else:}} + {{=T.M("**not available** (requires the Python [[guppy http://pypi.python.org/pypi/guppy/ popup]] library)")}} {{pass}}

- Cache contains items up to - {{="%02d" % total['oldest'][0]}} hours - {{="%02d" % total['oldest'][1]}} minutes - {{="%02d" % total['oldest'][2]}} seconds old. + {{=T.M("Cache contains items up to **%(hours)02d** %%{hour(hours)} **%(min)02d** %%{minute(min)} **%(sec)02d** %%{second(sec)} old.", + dict(hours=total['oldest'][0], min=total['oldest'][1], sec=total['oldest'][2]))}}

{{=BUTTON(T('Cache Keys'), _onclick='jQuery("#all_keys").toggle();')}}