AJAX editor is functional Still missing Revert and resolve but relogin works ! pull it from launchpad or use attached file against latest mdipierro devel branch
Good night All... On Thu, Feb 26, 2009 at 1:03 AM, Boris Manojlovic < boris.manojlo...@gmail.com> wrote: > update on development: > > all (hopefully) messages from system are implemented - session expired > shown. > Still not handling "Revert" (button) and "resolve" (server) actions. > Created repository at > https://code.launchpad.net/~stekoje/web2py/ajaxeditor<https://code.launchpad.net/%7Estekoje/web2py/ajaxeditor> > > > On Mon, Feb 23, 2009 at 9:28 PM, Boris Manojlovic < > boris.manojlo...@gmail.com> wrote: > >> Changed files: >> web2py/applications/admin/controllers/default.py >> web2py/applications/admin/static/ajax_editor.js >> web2py/applications/admin/views/default/edit.html >> web2py/applications/admin/views/layout.html >> web2py/applications/admin/views/web2py_ajax.html >> >> this time patch is more intrusive than from last time, because i had to >> change html layout to make "flash" field available. >> Still missing part is relogin but this time this is just response to your >> request :) >> >> I don't know why it does not work from konqueror as jquery should be >> portable that much? >> Anyway for now this is MozillaFirefox only untill I found out what is not >> working in my JavaScript code :-\ >> >> >> On Mon, Feb 23, 2009 at 7:52 PM, Boris Manojlovic < >> boris.manojlo...@gmail.com> wrote: >> >>> will try to do it asap :) >>> only missing will be "relogin" as i still didn't look into session issue. >>> You would have to open new window(tab) and login there untill i find some >>> nice solution for session timeout. >>> >>> >>> On Mon, Feb 23, 2009 at 7:16 PM, mdipierro <mdipie...@cs.depaul.edu>wrote: >>> >>>> >>>> ok but can you send me a patch that does 1,2,3? >>>> >>>> On Feb 23, 9:59 am, Boris Manojlovic <boris.manojlo...@gmail.com> >>>> wrote: >>>> > hello, >>>> > 1) what exactly you need is very simple to achive as putting with JS >>>> value >>>> > into some <div> (or I'm missing your point, which i think is case >>>> here) >>>> > 2) this is done already trough javascript (ajax_editor.js) as that was >>>> > needed for successful "save" functionality (or resolve redirect is >>>> received >>>> > if it is not sent) >>>> > 3) that is still to be done on client side - server side is same (and >>>> > implemented) code as it was before for /edit/ control,JSON should >>>> contain >>>> > standard errors you receive by HTML as you can see in patch >>>> > >>>> > >>>> > >>>> > On Mon, Feb 23, 2009 at 4:41 AM, mdipierro <mdipie...@cs.depaul.edu> >>>> wrote: >>>> > >>>> > > Boris. I really like this but we need >>>> > >>>> > > 1) make hash value visible and readonly >>>> > > 2) return the same when it was saved as well >>>> > > 3) some kind of notification (possibly in the form of flash) that >>>> > > informs the user if the file was saved or not. >>>> > >>>> > > Massimo >>>> > >>>> > > On Feb 22, 12:43 pm, Boris Manojlovic <boris.manojlo...@gmail.com> >>>> > > wrote: >>>> > > > Please try this patch last one was non working... >>>> > >>>> > > > On Sun, Feb 22, 2009 at 7:16 PM, Boris Manojlovic < >>>> > >>>> > > > boris.manojlo...@gmail.com> wrote: >>>> > > > > Hello to All, >>>> > >>>> > > > > i have started to work on something called "ajax" code editor. >>>> > > > > What exactly does it mean? >>>> > >>>> > > > > 1. No need for reloads on editor page (just think about undo >>>> redo in >>>> > > > > editor window) >>>> > > > > 2. No "terrible loss of code" if you are logged out >>>> (application >>>> > > > > timeout... with that "great" redirect to login page...) >>>> > > > > 3. speed gain >>>> > >>>> > > > > Current implementation has "save" functionality only and it >>>> works just >>>> > > from >>>> > > > > firefox (konqueror ignores my jquery code and same for >>>> opera...). >>>> > > > > Most coding as it would be expected should (and is) done on >>>> client side >>>> > > and >>>> > > > > will degrade depending if user use javascript at all - no script >>>> no >>>> > > ajax >>>> > > > > anyway. >>>> > > > > All messages in current stage are json passed to client. >>>> > > > > Patch against latest SVN from google code >>>> > >>>> > > > > P.S. Comments welcome and needed (to continue on this idea or >>>> not) >>>> > > > > -- >>>> > > > > "Only two things are infinite, the universe and human stupidity, >>>> and >>>> > > I'm >>>> > > > > not sure about the former."-Albert Einstein >>>> > >>>> > > > -- >>>> > > > "Only two things are infinite, the universe and human stupidity, >>>> and I'm >>>> > > not >>>> > > > sure about the former."-Albert Einstein >>>> > >>>> > > > ajax_editor.patch >>>> > > > 7KViewDownload >>>> > >>>> > -- >>>> > "Only two things are infinite, the universe and human stupidity, and >>>> I'm not >>>> > sure about the former."-Albert Einstein >>>> >>>> >>>> >>> >>> >>> -- >>> "Only two things are infinite, the universe and human stupidity, and I'm >>> not sure about the former."-Albert Einstein >>> >> >> >> >> -- >> "Only two things are infinite, the universe and human stupidity, and I'm >> not sure about the former."-Albert Einstein >> > > > > -- > "Only two things are infinite, the universe and human stupidity, and I'm > not sure about the former."-Albert Einstein > -- "Only two things are infinite, the universe and human stupidity, and I'm not sure about the former."-Albert Einstein --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "web2py Web Framework" group. To post to this group, send email to web2py@googlegroups.com To unsubscribe from this group, send email to web2py+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/web2py?hl=en -~----------~----~----~----~------~----~------~--~---
=== modified file 'applications/admin/controllers/default.py' --- applications/admin/controllers/default.py 2009-02-17 05:27:43 +0000 +++ applications/admin/controllers/default.py 2009-02-26 18:14:28 +0000 @@ -42,6 +42,9 @@ socket.gethostbyname(http_host)) remote_addr = request.env.remote_addr +# Load json only if it is ajax edited... +if request.vars.has_key('from_ajax'): + import gluon.contrib.simplejson as json if request.env.http_x_forwarded_for or request.env.wsgi_url_scheme\ in ['https', 'HTTPS']: @@ -121,7 +124,10 @@ query_string = '' url = request.env.path_info + query_string - redirect(URL(r=request, f='index', vars=dict(send=url))) + if not request.vars.has_key('from_ajax'): + redirect(URL(r=request, f='index', vars=dict(send=url))) + else: + raise HTTP(200, json.dumps({'status': 'EXPIRED', 'text': 'Session has expired please relogin'})) def index(): @@ -144,9 +150,15 @@ if isinstance(send, list): # ## why does this happen? send = str(send[0]) - redirect(send) + if request.vars.has_key('from_ajax'): + return json.dumps({'status': 'LOGGED_IN','text':'Succesfully Logged In'}) + else: + redirect(send) else: - response.flash = T('invalid password') + if request.vars.has_key('from_ajax'): + return json.dumps({'status': 'WRONG_PASSWORD','text':'Admin Password is incorrect'}) + else: + response.flash = T('invalid password') # f == file apps = [f for f in os.listdir(apath()) if f.find('.') < 0] @@ -425,7 +437,6 @@ def edit(): """ File edit handler """ - filename = '/'.join(request.args) # Try to discover the file type @@ -450,7 +461,10 @@ data1 = open(path, 'r').read() except IOError: session.flash = 'Invalid action' - redirect(URL(r=request, f='site')) + if request.vars.has_key('from_ajax'): + return json.dumps({'status': 'INVALID_ACTION','text':'Invalid action'}) + else: + redirect(URL(r=request, f='site')) file_hash = md5_hash(data) open(path, 'w').write(data) @@ -461,7 +475,10 @@ data = open(path, 'r').read() except IOError: session.flash = 'Invalid action' - redirect(URL(r=request, f='site')) + if request.vars.has_key('from_ajax'): + return json.dumps({'status': 'INVALID_ACTION','text':'Invalid action'}) + else: + redirect(URL(r=request, f='site')) file_hash = md5_hash(data) @@ -469,7 +486,11 @@ session.flash = T('file changed on disk') data = request.vars.data.replace('\r\n', '\n').strip() + '\n' open(path + '.1', 'w').write(data) - redirect(URL(r=request, f='resolve', args=request.args)) + if request.vars.has_key('from_ajax'): + #return json.dumps({'status': session.flash, 'resolve': 'true'}) + return json.dumps({'status': 'FILE_CHANGED', 'resolve': 'true','text': 'file changed on disk'}) + else: + redirect(URL(r=request, f='resolve', args=request.args)) elif request.vars.data: open(path + '.bak', 'w').write(data) data = request.vars.data.replace('\r\n', '\n').strip() + '\n' @@ -504,15 +525,18 @@ else: (controller, functions) = (None, None) - return dict(app=request.args[0], - filename=filename, - filetype=filetype, - data=data, - edit_controller=edit_controller, - file_hash=file_hash, - controller=controller, - functions=functions) - + if request.vars.has_key('from_ajax'): + return json.dumps({'file_hash': file_hash,'status' :'FILE_SAVED','text': 'File Successfully saved','time_saved': time.ctime()}) + #return response.json(file_hash) # maybe? + else: + return dict(app=request.args[0], + filename=filename, + filetype=filetype, + data=data, + edit_controller=edit_controller, + file_hash=file_hash, + controller=controller, + functions=functions) def resolve(): """ """ === added file 'applications/admin/static/ajax_editor.js' --- applications/admin/static/ajax_editor.js 1970-01-01 00:00:00 +0000 +++ applications/admin/static/ajax_editor.js 2009-02-26 23:54:06 +0000 @@ -0,0 +1,80 @@ +function prepareDataForSave(name,data) { + var obj = new Object(); + obj.Name = name; + obj.Data = data; + return obj; +} + +function prepareMultiPartPOST(data) { + var boundary = 'sPlItME' + Math.floor(Math.random()*10000); + var reqdata = '--' + boundary; + //console.log(data.length); + for (var i=0;i < data.length;i++) + { + reqdata += "\r\n" ; + reqdata += 'content-disposition: form-data; name="' + data[i].Name + '"'; + reqdata += "\r\n" ; + reqdata += data[i].Data; + reqdata += "\r\n" ; + reqdata += '--' + boundary; + } + return new Array(reqdata,boundary); +} + +function doClickSave() { + var dataForPost = prepareMultiPartPOST( + new Array( + prepareDataForSave('data', area.textarea.value), + prepareDataForSave('file_hash', $("input[name='file_hash']").val()), + prepareDataForSave('from_ajax','true') + ) + ) + //console.info(area.textarea.value); + $.ajax({ + type: "POST", + contentType: 'multipart/form-data;boundary="' + dataForPost[1] + '"', + url: self.location.href, + dataType: "json", + data: dataForPost[0], + success: function(json){ + //console.info( json.file_hash ); + if (json.status == 'FILE_SAVED') { + $("input[name='file_hash']").val(json.file_hash); + //console.info($("input[name='file_hash']").val()); + //$('.flash').text(json.text + ' at ' + json.time_saved + " hash=" + json.file_hash); + $('.flash').text(json.text + ' at ' + json.time_saved + ' (Server time)'); + $('.flash').removeClass('error'); // remove error class if we had it in previous call... + $('.flash').slideDown('slow'); + } else if (json.status == 'INVALID_ACTION') { + $('.flash').addClass('error'); + $('.flash').text(json.text); + $('.flash').slideDown('slow'); + } else if (json.status == 'FILE_CHANGED') { + $('.flash').addClass('error'); + $('.flash').text(json.text); + $('.flash').slideDown('slow'); + } else if (json.status == 'EXPIRED') { + $('.ajaxlogin').slideDown('slow'); + $('.flash').text(json.text); + $('.flash').slideDown('slow'); + //$('.flash').slideUp('slow'); + } + } + }); +} + +function doClickReLogin() { + $.post('/admin/default/index', { password: $('#password').val(), 'from_ajax': 'true' }, //hardcoded post url hmm not very portable in my opinion + function(json) { + if (json.status == 'LOGGED_IN') { + $('.flash').text(json.text); + $('.flash').removeClass('error'); // remove error class if we had it in previous call... + $('.flash').slideDown('slow'); + $('.ajaxlogin').slideUp('slow'); + } else if (json.status == 'WRONG_PASSWORD') { + $('.flash').text(json.text); + $('.flash').slideDown('slow'); + } + },"json" + ); +} === modified file 'applications/admin/static/styles.css' --- applications/admin/static/styles.css 2008-09-15 20:32:14 +0000 +++ applications/admin/static/styles.css 2009-02-26 22:10:19 +0000 @@ -78,5 +78,7 @@ .center { text-align: center; } /* Flash */ .flash { margin: 0 auto; text-align: center; clear: both; border: 1px #000000; background-color: #FF5C1F; color: white; margin-top: 0.0em; margin-bottom: 1.0em; padding-top: 1.0em; padding-bottom: 1.0em; cursor: pointer; } + /* Login window from ajax */ + .ajaxlogin { margin: 0 auto; text-align: center; clear: both; border: 1px #000000; background-color: #FF5C1F; color: white; margin-top: 0.0em; margin-bottom: 1.0em; padding-top: 1.0em; padding-bottom: 1.0em; cursor: pointer; } div.error { background-color: red; color: white; padding: 3px} /* Footer */ === modified file 'applications/admin/views/default/edit.html' --- applications/admin/views/default/edit.html 2009-02-12 05:27:08 +0000 +++ applications/admin/views/default/edit.html 2009-02-26 23:25:41 +0000 @@ -2,7 +2,15 @@ <script language="Javascript" type="text/javascript" src="{{=URL(r=request,c='static',f='edit_area/edit_area_full.js')}}"></script><script language="Javascript" type="text/javascript"> editAreaLoader.init({id: "body",start_highlight: true,allow_resize: "both",allow_toggle: true,language: "en",syntax: "{{=filetype}}",replace_tab_by_spaces: 4}); </script> +<script language="Javascript" type="text/javascript" src="/{{=request.application}}/static/ajax_editor.js"></script><script language="Javascript" type="text/javascript"> +$(document).ready(function(){ + $("form").bind("submit",function() { return false;}); //globaly remove submit... + $("form input[value='save']").bind("click", function() { doClickSave(); }); // force click action this is VALUE not NAME! + $("form input[name='login']").bind("click", function() { doClickReLogin(); }); // force click action + $("form input[name='restore']").bind("click", function() { alert('NOT YET IMPLEMENTED!!!');}); // force click action +}); +</script> <h1>Editing file "{{=filename}}"</h1> {{if functions:}} === modified file 'applications/admin/views/layout.html' --- applications/admin/views/layout.html 2009-02-19 12:51:07 +0000 +++ applications/admin/views/layout.html 2009-02-26 22:21:26 +0000 @@ -31,9 +31,19 @@ <div id="main_inner" class="fixed"> <div id="primaryContent_columnless"> <div id="columnA_columnless"> + <div class="ajaxlogin"> + <form action="" method="post"> + <table> + <tr><td>Administrator Password:</td><td><input type="password" name="password" id="password"/></td></tr> + <tr><td></td><td><input type="submit" name="login"/></td></tr> + </table> + </form> + </div> + <div class="flash"> {{if response.flash:}} - <div class="flash">{{=response.flash}}</div> + {{=response.flash}} {{pass}} + </div> {{include}} </div> </div> === modified file 'applications/admin/views/web2py_ajax.html' --- applications/admin/views/web2py_ajax.html 2008-12-09 21:44:36 +0000 +++ applications/admin/views/web2py_ajax.html 2009-02-26 23:16:30 +0000 @@ -22,8 +22,12 @@ $(document).ready(function() { $('.hidden').hide(); $('.error').hide().slideDown('slow'); -$('.flash').hide().slideDown('slow') -$('.flash').click(function() { $(this).fadeOut('slow'); return false; }); +if ($('.flash').text() == '') + $('.flash').hide().slideDown('slow'); +else + $('.flash').hide(); +$('.ajaxlogin').hide(); // don't show it by default +$('.flash').click(function() { $(this).slideUp('slow'); return false; }); //changed from default fadeout as it is too much intrusive :) $('input.string').attr('size',50); $('textarea.text').attr('cols',50).attr('rows',10); $('input.integer').keyup(function(){this.value=this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g,'').reverse();});