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 <
[email protected]> 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 <
> [email protected]> 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 <
>> [email protected]> 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 <[email protected]>wrote:
>>>
>>>>
>>>> ok but can you send me a patch that does 1,2,3?
>>>>
>>>> On Feb 23, 9:59 am, Boris Manojlovic <[email protected]>
>>>> 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 <[email protected]>
>>>> 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 <[email protected]>
>>>> > > wrote:
>>>> > > > Please try this patch last one was non working...
>>>> >
>>>> > > > On Sun, Feb 22, 2009 at 7:16 PM, Boris Manojlovic <
>>>> >
>>>> > > > [email protected]> 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 [email protected]
To unsubscribe from this group, send email to
[email protected]
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();});