improved admin navigation, thanks Vladyslav

This commit is contained in:
mdipierro
2012-07-15 17:28:46 -05:00
parent 8412b4d0cc
commit d5f5f5495b
10 changed files with 283 additions and 95 deletions
+154 -32
View File
@@ -8,11 +8,15 @@ if EXPERIMENTAL_STUFF:
response.view = response.view.replace('default/','default.mobile/')
response.menu = []
import re
from gluon.admin import *
from gluon.fileutils import abspath, read_file, write_file
from glob import glob
import shutil
import platform
from gluon.languages import (regex_language, read_possible_languages,
lang_sampling, read_dict, write_dict)
if DEMO_MODE and request.function in ['change_password','pack','pack_plugin','upgrade_web2py','uninstall','cleanup','compile_app','remove_compiled_app','delete','delete_plugin','create_file','upload_file','update_languages','reload_routes']:
session.flash = T('disabled in demo mode')
@@ -186,14 +190,14 @@ def site():
elif file_or_appurl and request.vars.filename:
# fetch an application via URL or file upload
f = None
if request.vars.appurl is not '':
if request.vars.appurl:
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 is not '':
elif request.vars.file:
f = request.vars.file.file
fname = request.vars.file.filename
@@ -247,7 +251,7 @@ def report_progress(app):
counter += int(m[1])
events.append([days,counter])
return events
def pack():
app = get_app()
@@ -357,7 +361,7 @@ def delete():
sender = sender[0]
if 'nodelete' in request.vars:
redirect(URL(sender))
redirect(URL(sender, anchor=request.vars.id))
elif 'delete' in request.vars:
try:
full_path = apath(filename, r=request)
@@ -369,7 +373,7 @@ def delete():
except Exception:
session.flash = T('unable to delete file "%(filename)s"',
dict(filename=filename))
redirect(URL(sender))
redirect(URL(sender, anchor=request.vars.id2))
return dict(filename=filename, sender=sender)
def enable():
@@ -384,22 +388,25 @@ def enable():
def peek():
""" Visualize object code """
app = get_app()
app = get_app(request.vars.app)
filename = '/'.join(request.args)
if request.vars.app:
path = abspath(filename, gluon=False)
else:
path = apath(filename, r=request)
try:
data = safe_read(apath(filename, r=request)).replace('\r','')
data = safe_read(path).replace('\r','')
except IOError:
session.flash = T('file does not exist')
redirect(URL('site'))
extension = filename[filename.rfind('.') + 1:].lower()
return dict(app=request.args[0],
return dict(app=app,
filename=filename,
data=data,
extension=extension)
def test():
""" Execute controller tests """
app = get_app()
@@ -428,14 +435,18 @@ def search():
files2 = glob(os.path.join(path,'*/*.html'))
files3 = glob(os.path.join(path,'*/*/*.html'))
files=[x[len(path)+1:].replace('\\','/') for x in files1+files2+files3 if match(x,keywords)]
return response.json({'files':files})
return response.json(dict(files=files, message=T('@Searching: **%s** %%{file}', len(files))))
def edit():
""" File edit handler """
# Load json only if it is ajax edited...
app = get_app()
app = get_app(request.vars.app)
filename = '/'.join(request.args)
# Try to discover the file type
if request.vars.app:
path = abspath(filename)
else:
path = apath(filename, r=request)
# Try to discover the file type
if filename[-3:] == '.py':
filetype = 'python'
elif filename[-5:] == '.html':
@@ -450,9 +461,6 @@ def edit():
filetype = 'html'
# ## check if file is not there
path = apath(filename, r=request)
if ('revert' in request.vars) and os.path.exists(path + '.bak'):
try:
data = safe_read(path + '.bak')
@@ -672,9 +680,13 @@ def edit_language():
""" Edit language file """
app = get_app()
filename = '/'.join(request.args)
from gluon.languages import read_dict, write_dict
strings = read_dict(apath(filename, r=request))
keys = sorted(strings.keys(),lambda x,y: cmp(x.lower(), y.lower()))
if '__corrupted__' in strings:
form = SPAN(strings['__corrupted__'],_class='error')
return dict(filename=filename, form=form)
keys = sorted(strings.keys(),lambda x,y: cmp(unicode(x,'utf-8').lower(), unicode(y,'utf-8').lower()))
rows = []
rows.append(H2(T('Original/Translation')))
@@ -711,6 +723,54 @@ def edit_language():
return dict(app=request.args[0], filename=filename, form=form)
def edit_plurals():
""" Edit plurals file """
#import ipdb; ipdb.set_trace()
app = get_app()
filename = '/'.join(request.args)
plurals = read_plural_dict(apath(filename, r=request)) # plural forms dictionary
nplurals = int(request.vars.nplurals)-1 # plural forms quantity
xnplurals = xrange(nplurals)
if '__corrupted__' in plurals:
# show error message and exit
form = SPAN(plurals['__corrupted__'],_class='error')
return dict(filename=filename, form=form)
keys = sorted(plurals.keys(),lambda x,y: cmp(unicode(x,'utf-8').lower(), unicode(y,'utf-8').lower()))
rows = []
row=[T("Singular Form")]
row.extend([T("Plural Form #%s", n+1) for n in xnplurals])
table=TABLE(THEAD(TR(row)))
for key in keys:
name = md5_hash(key)
forms = plurals[key]
if len(forms) < nplurals:
forms.extend(None for i in xrange(nplurals-len(forms)))
row = [B(key)]
row.extend([INPUT(_type='text', _name=name+'_'+str(n), value=forms[n], _size=20) for n in xnplurals])
row.append(TD(TAG.BUTTON(T('delete'), _onclick='return delkey("%s")' % name)))
rows.append(TR(row, _id=name))
if rows:
table.append(TBODY(rows))
rows=[table, INPUT(_type='submit', _value=T('update'))]
form = FORM(*rows)
if form.accepts(request.vars, keepvalues=True):
new_plurals = dict()
for key in keys:
name = md5_hash(key)
if form.vars[name+'_0']==chr(127): continue
new_plurals[key] = [form.vars[name+'_'+str(n)] for n in xnplurals]
write_plural_dict(apath(filename, r=request), new_plurals)
session.flash = T('file saved on %(time)s', dict(time=time.ctime()))
redirect(URL(r=request, args=request.args, vars=dict(nplurals=request.vars.nplurals)))
return dict(app=request.args[0], filename=filename, form=form)
def about():
""" Read about info """
app = get_app()
@@ -794,8 +854,34 @@ def design():
statics.sort()
# Get all languages
languages = listdir(apath('%s/languages/' % app, r=request), '[\w-]*\.py')
all_languages = dict([(lang+'.py',info[0]) for lang,info
in read_possible_languages(apath(app, r=request)).iteritems()
if info[2]!=0]) # info[2] is langfile_mtime:
# get only existing files
languages = sorted(all_languages)
plural_rules = {}
try:
all_plurals = read_possible_plurals()
except:
all_plurals = {} # not implemented yet
for langfile,lang in all_languages.iteritems():
lang=lang.strip()
match_language = regex_language.match(lang)
if match_language:
match_language = tuple(part
for part in match_language.groups()
if part)
plang = lang_sampling(match_language, all_plurals.keys())
if plang:
plural=all_plurals[plang]
plural_rules[langfile]=(plural[0],plang,plural[1],plural[3])
else:
plural_rules[langfile]=(0,lang,'plural_rules-%s.py'%lang,'')
plurals = listdir(apath('%s/languages/' % app, r=request),
'^plural-[\w-]+\.py$')
#Get crontab
cronfolder = apath('%s/cron' % app, r=request)
if not os.path.exists(cronfolder): os.mkdir(cronfolder)
@@ -821,6 +907,8 @@ def design():
include=include,
statics=filter_plugins(statics,plugins),
languages=languages,
plurals=plurals,
plural_rules=plural_rules,
crontab=crontab,
plugins=plugins)
@@ -830,7 +918,7 @@ def delete_plugin():
plugin = request.args(1)
plugin_name='plugin_'+plugin
if 'nodelete' in request.vars:
redirect(URL('design',args=app))
redirect(URL('design', args=app, anchor=request.vars.id))
elif 'delete' in request.vars:
try:
for folder in ['models','views','controllers','static','modules']:
@@ -847,7 +935,7 @@ def delete_plugin():
except Exception:
session.flash = T('unable to delete file plugin "%(plugin)s"',
dict(plugin=plugin))
redirect(URL('design',args=request.args(0)))
redirect(URL('design', args=request.args(0), anchor=request.vars.id2))
return dict(plugin=plugin)
def plugin():
@@ -940,24 +1028,56 @@ def plugin():
def create_file():
""" Create files handler """
try:
app = get_app(name=request.vars.location.split('/')[0])
path = apath(request.vars.location, r=request)
anchor='#'+request.vars.id if request.vars.id else ''
if request.vars.app:
app = get_app(request.vars.app)
path = abspath(request.vars.location, gluon=False)
else:
app = get_app(name=request.vars.location.split('/')[0])
path = apath(request.vars.location, r=request)
filename = re.sub('[^\w./-]+', '_', request.vars.filename)
if path[-7:] == '/rules/':
# Handle plural rules files
if len(filename) == 0:
raise SyntaxError
if not filename[-3:] == '.py':
filename += '.py'
lang = re.match('^plural_rules-(.*)\.py$',filename).group(1)
langinfo = read_possible_languages(apath(app, r=request))[lang]
text = dedent("""
#!/usr/bin/env python
# -*- coding: utf8 -*-
# Plural-Forms for %(lang)s (%(langname)s)
if path[-11:] == '/languages/':
nplurals=2 # for example, English language has 2 forms:
# 1 singular and 1 plural
# Determine plural_id for number *n* as sequence of positive
# integers: 0,1,...
# NOTE! For singular form ALWAYS return plural_id = 0
get_plural_id = lambda n: int(n != 1)
# Construct and return plural form of *word* using
# *plural_id* (which ALWAYS>0). This function will be executed
# for words (or phrases) not found in plural_dict dictionary.
# By default this function simply returns word in singular:
construct_plural_form = lambda word, plural_id: word
""")[1:] % dict(lang=langinfo[0], langname=langinfo[1])
elif path[-11:] == '/languages/':
# Handle language files
if len(filename) == 0:
raise SyntaxError
if not filename[-3:] == '.py':
filename += '.py'
app = path.split('/')[-3]
path=os.path.join(apath(app, r=request),'languages',filename)
if not os.path.exists(path):
safe_write(path, '')
# create language xx[-yy].py file:
findT(apath(app, r=request), filename[:-3])
session.flash = T('language file "%(filename)s" created/updated',
dict(filename=filename))
redirect(request.vars.sender)
dict(filename=filename))
redirect(request.vars.sender+anchor)
elif path[-8:] == '/models/':
# Handle python models
@@ -1024,7 +1144,7 @@ def create_file():
filename = 'plugin_%s/%s' % (request.vars.plugin, filename)
text = ''
else:
redirect(request.vars.sender)
redirect(request.vars.sender+anchor)
full_filename = os.path.join(path, filename)
dirpath = os.path.dirname(full_filename)
@@ -1039,18 +1159,20 @@ def create_file():
log_progress(app,'CREATE',filename)
session.flash = T('file "%(filename)s" created',
dict(filename=full_filename[len(path):]))
vars={}
if request.vars.id: vars['id']=request.vars.id
if request.vars.app: vars['app']=request.vars.app
redirect(URL('edit',
args=[os.path.join(request.vars.location, filename)]))
args=[os.path.join(request.vars.location, filename)], vars=vars))
except Exception, e:
if not isinstance(e,HTTP):
session.flash = T('cannot create file')
redirect(request.vars.sender)
redirect(request.vars.sender+anchor)
def upload_file():
""" File uploading handler """
try:
filename = None
app = get_app(name=request.vars.location.split('/')[0])
@@ -1123,7 +1245,7 @@ def errors():
hash2error = dict()
for fn in listdir(errors_path, '^\w.*'):
for fn in listdir(errors_path, '^[a-fA-F0-9.\-]+$'):
fullpath = os.path.join(errors_path, fn)
if not os.path.isfile(fullpath): continue
try: