From 9b4888e6d73c3437c486cc9d13a19b5defcfbf50 Mon Sep 17 00:00:00 2001 From: ilvalle Date: Mon, 27 May 2013 16:30:27 +0200 Subject: [PATCH] initial import for tabs in the online editor --- applications/admin/controllers/default.py | 43 +- applications/admin/static/js/ajax_editor.js | 77 +++- applications/admin/views/default/edit.html | 399 +++++------------- applications/admin/views/default/edit_js.html | 116 +++++ 4 files changed, 311 insertions(+), 324 deletions(-) create mode 100644 applications/admin/views/default/edit_js.html diff --git a/applications/admin/controllers/default.py b/applications/admin/controllers/default.py index 7f8106d9..35a14530 100644 --- a/applications/admin/controllers/default.py +++ b/applications/admin/controllers/default.py @@ -586,6 +586,24 @@ def edit(): """ File edit handler """ # Load json only if it is ajax edited... app = get_app(request.vars.app) + + if not(request.ajax): + # return the scaffolding, the rest will be through ajax requests + response.title = T('Editing %s' % app) + editarea_preferences = {} + editarea_preferences['FONT_SIZE'] = '10' + editarea_preferences['FULL_SCREEN'] = 'false' + editarea_preferences['ALLOW_TOGGLE'] = 'true' + editarea_preferences['REPLACE_TAB_BY_SPACES'] = '4' + editarea_preferences['DISPLAY'] = 'onload' + for key in editarea_preferences: + if key in globals(): + editarea_preferences[key] = globals()[key] + return response.render ('default/edit.html', dict(app=request.args[0], editarea_preferences=editarea_preferences)) + + """ File edit handler """ + # Load json only if it is ajax edited... + app = get_app(request.vars.app) filename = '/'.join(request.args) response.title = request.args[-1] if request.vars.app: @@ -708,7 +726,7 @@ def edit(): cfilename = os.path.join(request.args[0], 'controllers', request.args[2] + '.py') if os.path.exists(apath(cfilename, r=request)): - edit_controller = URL('edit',args=[cfilename.replace(os.sep, "/")]) + edit_controller = URL('edit', args=[cfilename.replace(os.sep, "/")]) view = request.args[3].replace('.html', '') view_link = URL(request.args[0], request.args[2], view) elif filetype == 'python' and request.args[1] == 'controllers': @@ -730,6 +748,7 @@ def edit(): vf = os.path.split(v)[-1] vargs = "/".join([viewpath.replace(os.sep, "/"), vf]) editviewlinks.append(A(vf.split(".")[0], + _class="editor_filelink", _href=URL('edit', args=[vargs]))) if len(request.args) > 2 and request.args[1] == 'controllers': @@ -741,17 +760,7 @@ def edit(): if 'from_ajax' in request.vars: return response.json({'file_hash': file_hash, 'saved_on': saved_on, 'functions': functions, 'controller': controller, 'application': request.args[0], 'highlight': highlight}) else: - - editarea_preferences = {} - editarea_preferences['FONT_SIZE'] = '10' - editarea_preferences['FULL_SCREEN'] = 'false' - editarea_preferences['ALLOW_TOGGLE'] = 'true' - editarea_preferences['REPLACE_TAB_BY_SPACES'] = '4' - editarea_preferences['DISPLAY'] = 'onload' - for key in editarea_preferences: - if key in globals(): - editarea_preferences[key] = globals()[key] - return dict(app=request.args[0], + file_details = dict(app=request.args[0], filename=filename, filetype=filetype, data=data, @@ -761,9 +770,13 @@ def edit(): controller=controller, functions=functions, view_link=view_link, - editarea_preferences=editarea_preferences, - editviewlinks=editviewlinks) - + editviewlinks=editviewlinks, + id=IS_SLUG()(filename)[0], + force= True if (request.vars.restore or request.vars.revert) else False) + plain_html = response.render('default/edit_js.html', file_details) + file_details['plain_html'] = plain_html + return response.json(file_details) + def resolve(): """ diff --git a/applications/admin/static/js/ajax_editor.js b/applications/admin/static/js/ajax_editor.js index 168236d4..a406ba8a 100644 --- a/applications/admin/static/js/ajax_editor.js +++ b/applications/admin/static/js/ajax_editor.js @@ -54,25 +54,28 @@ function doHighlight(highlight) { } function doClickSave() { - var data = getData(); + var currentTabID = '#' + jQuery('#edit_placeholder div.tab-pane.active').attr('id'); + var editor = jQuery (currentTabID + ' textarea').data('editor'); + var data = editor.getValue(); var dataForPost = prepareMultiPartPOST(new Array( prepareDataForSave('data', data), prepareDataForSave('file_hash', - jQuery("input[name='file_hash']").val()), + jQuery(currentTabID + " input[name='file_hash']").val()), prepareDataForSave('saved_on', - jQuery("input[name='saved_on']").val()), + jQuery(currentTabID + " input[name='saved_on']").val()), prepareDataForSave('saved_on', - jQuery("input[name='saved_on']").val()), + jQuery(currentTabID + " input[name='saved_on']").val()), prepareDataForSave('from_ajax','true'))); // console.info(area.textarea.value); - jQuery("input[name='saved_on']").attr('style', + jQuery(currentTabID + " input[name='saved_on']").attr('style', 'background-color:yellow'); - jQuery("input[name='saved_on']").val('saving now...') + jQuery(currentTabID + " input[name='saved_on']").val('saving now...') + currentUrl = jQuery(currentTabID + ' form').attr('action'); jQuery.ajax({ type: "POST", contentType: 'multipart/form-data;boundary="' + dataForPost[1] + '"', - url: self.location.href, + url: currentUrl, dataType: "json", data: dataForPost[0], timeout: 5000, @@ -100,12 +103,12 @@ function doClickSave() { window.location.href=json.redirect; } else { // console.info( json.file_hash ); - jQuery("input[name='file_hash']").val(json.file_hash); - jQuery("input[name='saved_on']").val(json.saved_on); + jQuery(currentTabID + " input[name='file_hash']").val(json.file_hash); + jQuery(currentTabID + " input[name='saved_on']").val(json.saved_on); if (json.highlight) { doHighlight(json.highlight); } else { - jQuery("input[name='saved_on']").attr('style','background-color:#99FF99'); + jQuery(currentTabID + " input[name='saved_on']").attr('style','background-color:#99FF99'); //jQuery(".flash").delay(1000).fadeOut('slow'); } // console.info(jQuery("input[name='file_hash']").val()); @@ -134,10 +137,12 @@ function getSelectionRange() { sel['end'] = range.end.row; sel['data'] = ''; } else if (window.mirror) { - sel = {}; - sel['start'] = window.mirror.getCursor(true).line; - sel['end'] = window.mirror.getCursor(false).line; - sel['data'] = ''; + var currentTabID = '#' + jQuery('#edit_placeholder div.tab-pane.active').attr('id'); + var editor = jQuery (currentTabID + ' textarea').data('editor'); + sel = {}; + sel['start'] = editor.getCursor(true).line; + sel['end'] = editor.getCursor(false).line; + sel['data'] = ''; } else if (window.eamy) { sel = {}; // not implemented @@ -150,6 +155,9 @@ function getSelectionRange() { } function doToggleBreakpoint(filename, url, sel) { + var currentTabID = '#' + jQuery('#edit_placeholder div.tab-pane.active').attr('id'); + var editor = jQuery (currentTabID + ' textarea').data('editor'); + if (sel==null) { // use cursor position to determine the breakpoint line // (gutter already tell us the selected line) @@ -222,16 +230,17 @@ function doListBreakpoints(filename, url) { xhr.setRequestHeader('web2py-component-element', 'doListBreakpoints');}, success: function(json,text,xhr){ - try { - if (json.error) { - window.location.href=json.redirect; - } else { - if (window.mirror) { + try { + if (json.error) { + window.location.href=json.redirect; + } else { + var currentTabID = '#' + jQuery('#edit_placeholder div.tab-pane.active').attr('id'); + var editor = jQuery (currentTabID + ' textarea').data('editor'); + if (window.mirror) { for (i in json.breakpoints) { lineno = json.breakpoints[i]; // mark the breakpoint if ok=True - editor.setMarker(lineno-1, - " %N%"); + editor.setMarker(lineno-1, " %N%"); } } } @@ -250,3 +259,29 @@ function keepalive(url) { success: function(){}, error: function(x) { on_error(); } }); } + +function load_file (url) { + jQuery.ajax({ + type: "GET", + dataType: 'json', + url: url, + timeout: 1000, + success: function(json){ + if (typeof(json['plain_html']) !== undefined) { + if (jQuery('#' + json['id']).length === 0 || json['force'] === true) { + // Create a tab and put the code in it + var tab_header = '
  • filenameDefault
  • '.replace(/idDefault/, json['id']).replace(/filenameDefault/, json['filename'] ); + var tab_body = '
    htmlDefault
    '.replace(/htmlDefault/, json['plain_html']).replace(/idDefault/, json['id']); + if (json['force'] === false) { + jQuery('#filesTab').append(jQuery(tab_header)); + jQuery('#myTabContent').append(jQuery(tab_body)); + } else { + jQuery('#' + json['id']).html(jQuery(tab_body)); + } + } + jQuery("a[href='#" + json['id'] + "']" ).click(); + } + }, + error: function(x) { on_error(); } + }); +} diff --git a/applications/admin/views/default/edit.html b/applications/admin/views/default/edit.html index a3ed3eff..de6d6720 100644 --- a/applications/admin/views/default/edit.html +++ b/applications/admin/views/default/edit.html @@ -10,13 +10,10 @@ return files def editfile(path,file,vars={}): - args=(path,file) if 'app' in vars else (app,path,file) - return A(file, _class='', _href=URL('edit', args=args, vars=vars), _style='word-wrap: break-word;') - + args=(path,file) if 'app' in vars else (app,path,file) + url = URL('edit', args=args, vars=vars) + return A(file, _class='editor_filelink', _href=url, _style='word-wrap: break-word;') }} -{{if TEXT_EDITOR == 'amy':}} -{{include 'default/amy_ajax.html'}} -{{elif TEXT_EDITOR == 'codemirror':}} {{cm=URL('static','codemirror')}} @@ -37,306 +34,132 @@ -{{elif TEXT_EDITOR == 'ace':}} - - - - {{if filetype == 'python':}} - - - {{elif filetype in ('html', 'load'):}} - - - {{elif filetype == 'js':}} - - - {{elif filetype == 'css':}} - - - {{else:}} - - - {{pass}} - {{if TEXT_EDITOR_KEYBINDING == 'emacs':}} - - - {{elif TEXT_EDITOR_KEYBINDING == 'vi':}} - - - {{else:}} - - {{pass}} - -{{else:}} - - - -{{pass}} {{block sectionclass}}edit{{end}} -

    {{=T('Editing file "%s"',filename)}}

    -{{if functions:}} -

    - - {{=B(T('exposes:'))}} {{=XML(', '.join([A(f,_href=URL(a=app,c=controller,f=f)).xml() for f in functions]))}} - - {{if editviewlinks:}}
    - {{=B(T('edit views:'))}} - {{=XML(', '.join([v.xml() for v in editviewlinks]))}} - {{pass}} -

    -{{pass}}

    - {{if filetype=='python':}} - {{=A(SPAN(T('toggle breakpoint')), - _value="breakpoint", _name="breakpoint", - _onclick="return doToggleBreakpoint('%s','%s://%s%s',null);" % (filename, - request.env['wsgi_url_scheme'], request.env['http_host'], - URL(c='debug', f='toggle_breakpoint')), - _class="button special btn btn-inverse")}} - {{pass}} {{=button(URL('design',args=request.vars.app if request.vars.app else request.args[0], anchor=request.vars.id), T('back'))}} - {{if edit_controller:}} - {{=button(edit_controller, T('edit controller'))}} - {{pass}} - {{if view_link:}} - {{=button(view_link, T('try view'))}} - {{pass}} - {{if request.args[1]=='models':}} + {{#if request.args[1]=='models':}} {{=T('online designer')}} - {{pass}} + {{#pass}} {{=T('docs')}}

    - - - -
    - -
    -
    -
    - - -
    -
    - - -
    -
    -
    - {{if TEXT_EDITOR == 'amy':}} - - - {{elif TEXT_EDITOR == 'codemirror':}} - - - {{elif TEXT_EDITOR == 'ace':}} -
    {{=data}}
    - - {{else:}} - - - {{pass}} -
    - - {{=T('currently saved or')}} - - {{=T('to previous version.')}} -
    -
    -
    -
    - -
    -
    - {{if TEXT_EDITOR=='edit_area' and filetype=='html':}} -

    {{=T('Key bindings for ZenCoding Plugin')}}

    -
      - {{=shortcut('Ctrl+S', T('Save via Ajax'))}} - {{=shortcut('Ctrl+,', T('Expand Abbreviation'))}} - {{=shortcut('Ctrl+M', T('Match Pair'))}} - {{=shortcut('Ctrl+H', T('Wrap with Abbreviation'))}} - {{=shortcut('Shift+Ctrl+M', T('Merge Lines'))}} - {{=shortcut('Ctrl+Shift+←', T('Previous Edit Point'))}} - {{=shortcut('Ctrl+Shift+→', T('Next Edit Point'))}} - {{=shortcut('Ctrl+Shift+↑', T('Go to Matching Pair'))}} -
    - {{elif TEXT_EDITOR == 'codemirror' and filetype=='html':}} -

    {{=T('Key bindings for ZenCoding Plugin')}}

    -
      - {{=shortcut('Ctrl+S', T('Save via Ajax'))}} - {{=shortcut('Ctrl+F11', T('Toggle Fullscreen'))}} - {{=shortcut('Ctrl-F / Cmd-F', T('Start searching'))}} - {{=shortcut('Ctrl-G / Cmd-G', T('Find Next'))}} - {{=shortcut('Shift-Ctrl-G / Shift-Cmd-G', T('Find Previous'))}} - {{=shortcut('Shift-Ctrl-F / Cmd-Option-F', T('Replace'))}} - {{=shortcut('Shift-Ctrl-R / Shift-Cmd-Option-F', T('Replace All'))}} - {{=shortcut('Tab', T('Expand Abbreviation'))}} -
    - {{elif TEXT_EDITOR == 'codemirror':}} -

    {{=T("Key bindings")}}

    -
      - {{=shortcut('Ctrl+S', T('Save via Ajax'))}} - {{=shortcut('Ctrl+F11', T('Toggle Fullscreen'))}} - {{=shortcut('Ctrl-F / Cmd-F', T('Start searching'))}} - {{=shortcut('Ctrl-G / Cmd-G', T('Find Next'))}} - {{=shortcut('Shift-Ctrl-G / Shift-Cmd-G', T('Find Previous'))}} - {{=shortcut('Shift-Ctrl-F / Cmd-Option-F', T('Replace'))}} - {{=shortcut('Shift-Ctrl-R / Shift-Cmd-Option-F', T('Replace All'))}} -
    - {{else:}} -

    {{=T("Key bindings")}}

    -
      - {{=shortcut('Ctrl+S', T('Save via Ajax'))}} -
    + +
    + +
    +
    diff --git a/applications/admin/views/default/edit_js.html b/applications/admin/views/default/edit_js.html new file mode 100644 index 00000000..b4d99ff6 --- /dev/null +++ b/applications/admin/views/default/edit_js.html @@ -0,0 +1,116 @@ +{{def shortcut(combo, description): + return XML('
  • %s%s
  • ' % (combo, description)) + +##TODO +#eseguire dolistbreakpoint ogni volta che si fa una load +}} + +
    +
    + + {{=IMG(_src=URL('static', 'images/save_icon.png'), _alt=T('Save'))}} + + + + +{{if filetype=='python':}} + {{=A(SPAN(T('toggle breakpoint')), + _value="breakpoint", _name="breakpoint", + _onclick="return doToggleBreakpoint('%s','%s://%s%s',null);" % (filename, + request.env['wsgi_url_scheme'], request.env['http_host'], + URL(c='debug', f='toggle_breakpoint')), + _class="button special btn btn-inverse")}} +{{pass}} +{{if view_link:}} + {{=button(view_link, T('try view'))}} +{{pass}} +

    +{{if functions:}} + + {{=B(T('exposes:'))}} {{=XML(', '.join([A(f,_target="_blank", _href=URL(a=app,c=controller,f=f)).xml() for f in functions]))}} + +{{if editviewlinks:}}
    + {{=B(T('edit views:'))}} + {{=XML(', '.join([v.xml() for v in editviewlinks]))}} +{{pass}} +{{pass}} +{{if edit_controller:}} + {{=B(T('edit controller:'))}} + {{=A(request.args[2]+'.py', _class="editor_filelink", _target="_blank", _href=edit_controller)}} +{{pass}} +

    +
    + + + + +
    + {{=T('restore')}} + {{=T('currently saved or')}} + {{=T('revert')}} + {{=T('to previous version.')}} +
    +
    +
    + +
    +
    + {{if TEXT_EDITOR == 'codemirror' and filetype=='html':}} +

    {{=T('Key bindings for ZenCoding Plugin')}}

    +
      + {{=shortcut('Ctrl+S', T('Save via Ajax'))}} + {{=shortcut('Ctrl+F11', T('Toggle Fullscreen'))}} + {{=shortcut('Ctrl-F / Cmd-F', T('Start searching'))}} + {{=shortcut('Ctrl-G / Cmd-G', T('Find Next'))}} + {{=shortcut('Shift-Ctrl-G / Shift-Cmd-G', T('Find Previous'))}} + {{=shortcut('Shift-Ctrl-F / Cmd-Option-F', T('Replace'))}} + {{=shortcut('Shift-Ctrl-R / Shift-Cmd-Option-F', T('Replace All'))}} + {{=shortcut('Tab', T('Expand Abbreviation'))}} +
    + {{elif TEXT_EDITOR == 'codemirror':}} +

    {{=T("Key bindings")}}

    +
      + {{=shortcut('Ctrl+S', T('Save via Ajax'))}} + {{=shortcut('Ctrl+F11', T('Toggle Fullscreen'))}} + {{=shortcut('Ctrl-F / Cmd-F', T('Start searching'))}} + {{=shortcut('Ctrl-G / Cmd-G', T('Find Next'))}} + {{=shortcut('Shift-Ctrl-G / Shift-Cmd-G', T('Find Previous'))}} + {{=shortcut('Shift-Ctrl-F / Cmd-Option-F', T('Replace'))}} + {{=shortcut('Shift-Ctrl-R / Shift-Cmd-Option-F', T('Replace All'))}} +
    + {{pass}} +
    +