Forum OpenACS Development: Using the richtext widget

Collapse
Posted by Janine Ohmer on
Here I go again... I really need to stop heading out without a compass and sextant... these uncharted waters can be brutal! :)

I'm attempting to make forum posting use the enhanced text widget.  Forums is an older module so it uses form create directly instead of ad_form.  Ok, that's not too bad.  But I can't seem to make it do what I want.

I changed the content textarea in message-post.tcl into a richtext widget called message_body, and did away with the format choices.  So far, so good.

When you click ok on that page, it comes back to message-post, but it uses a different template: message-post-confirm.  You can view the source for that page and see that there is a hidden variable called message_body and that it looks correct.

When you click confirm, you come back to message-post a third time.  This is where the trouble is happening.  The value displayed in the richtext widget is the entire string in message_body, which contains both the actual content and the format, and I get an error from the richtext widget that the format is invalid because it's empty.

I have found by experimentation that if I add message_body to the ad_page_contract block and do an explicit "element set_properties" of message_body it fixes the display problem;  I get just the content without the format string.  But I can't seem to get the format to be set correctly, and it does not seem like I should have to do this anyway.

Any suggestions?

Thanks in advance!

Collapse
Posted by Lars Pind on
Janine,

I think message_body should be the two-element list of (format, content), and that the problem is that somehow the information that this is a list of two elements gets lost.

One way you could test my hypothesis would be to do something like

ns_log Notice "len=[llength $message_body] ; format=[lindex $message_body 0] ; content=[lindex $message_body 1]"

on message-post when you get back to that page after confirmation, just to see what the value is.

If that doesn't show what it should, you can try tracking it by doing the same log statement upon passing the message_body variable to the confirm page, and on the confirm page upon receiving it.

/Lars

Collapse
Posted by Janine Ohmer on
Hi Lars,

That's what I was thinking too, except that template::richtext:;get_property (from memory so may be slightly wrong) has no trouble parsing message_body into content and format.  However, you still may be right - I ran into a similar problem with passing around a multiple for checkboxes.  Maybe my experiment calling get_property wasn't executed when I thought it was.

I'll give it a try and let you know what happens.

thanks,

janine

Collapse
Posted by Janine Ohmer on
Unfortunately, that doesn't seem to be the problem.  I added message_body to the ad_page_contract block and then used a validate block to check it.  It's a proper list.  I even split it up and reconstituted it, just to be sure.

I don't know much at all about how forms are evaluated and values checked.  I can't see any reason for this to be failing, but it is.  I have to go off and work on something else now, but any suggestions on what else to look at are welcome!

Collapse
Posted by Lars Pind on
Try posting a patch, and I'll try to take a look.
Collapse
Posted by Janine Ohmer on
Ok, here's the diff (with context so you should be able to use this with patch).  Commentary to follow.

$ cvs diff -c message-post.tcl
Index: message-post.tcl
===================================================================
RCS file: /usr/local/cvsroot/bp/packages/forums/www/message-post.tcl,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 message-post.tcl
*** message-post.tcl    15 Apr 2003 18:45:43 -0000      1.1.1.1
--- message-post.tcl    25 Aug 2003 17:54:22 -0000
***************
*** 38,63 ****
      -html {size 60} \
      -validate { {expr ![empty_string_p [string trim $value]]} {Please enter a subject} }

! # we use ns_queryget to get the value of html_p because it won't be defined
! # until the next element -DaveB
!
! element create message content \
      -label Body \
!    -datatype text \
!    -widget textarea \
      -html {rows 20 cols 60 wrap soft} \
      -validate {
        empty {expr ![empty_string_p [string trim $value]]} {Please enter a message}
-      html { expr {( [string match [set l_html_p [ns_queryget html_p f]] "t"] && [empty_string_p [set v_message [ad_quotehtml [ad_html_security_check $value]]]] ) || [string match $l_html_p "f"] } }
-            {}
        }

  element create message html_p \
      -label Format \
      -datatype text \
!    -widget radio \
!    -value $html_p \
!    -options {{text f} {html t}}

  element create message parent_id \
      -label "parent ID" \
--- 38,58 ----
      -html {size 60} \
      -validate { {expr ![empty_string_p [string trim $value]]} {Please enter a subject} }

! element create message message_body \
      -label Body \
!    -datatype richtext \
!    -widget richtext \
      -html {rows 20 cols 60 wrap soft} \
      -validate {
        empty {expr ![empty_string_p [string trim $value]]} {Please enter a message}
        }

+ # dummy for now - need to go back and remove html_p entirely
  element create message html_p \
      -label Format \
      -datatype text \
!    -widget hidden \
!    -value 't'

  element create message parent_id \
      -label "parent ID" \
***************
*** 93,106 ****

  if {[form is_valid message]} {
      form get_values message \
!        message_id forum_id parent_id subject content html_p confirm_p subscribe_p

      if {!$confirm_p} {
          forum::get -forum_id $forum_id -array forum

          set confirm_p 1
!        set content [string trimright $content]
!        set exported_vars [export_form_vars message_id forum_id parent_id subject content html_p confirm_p]

          set message(html_p) $html_p
          set message(subject) [ad_quotehtml $subject]
--- 88,103 ----

  if {[form is_valid message]} {
      form get_values message \
!        message_id forum_id parent_id subject html_p confirm_p subscribe_p message_body
!
!    set content [template::util::richtext::get_property contents $message_body]
!    set format [template::util::richtext::get_property format $message_body]

      if {!$confirm_p} {
          forum::get -forum_id $forum_id -array forum

          set confirm_p 1
!        set exported_vars [export_form_vars message_id forum_id parent_id subject html_p confirm_p message_body]

          set message(html_p) $html_p
          set message(subject) [ad_quotehtml $subject]

This is (I think) the smallest set of changes I can make.  html_p is obviously not relevant anymore but we're just passing it around.

So here's what I've done:
- changed the textarea widget to richtext and renamed it to message_body
- turned html_p into an ignored hidden field (temporarily, will get rid of it after I get this working)
- set the value of content from $message_body

The result of this is that the format is showing up in the text area following the actual content, and the format is set to the empty string which causes form validation to bomb.

What seems to be going on (and confirmed with ns_log statements) is that $message_body is still a list going into the confirm page, but that's lost when it is passed along to the final run through message-post, where the actual insert is supposed to take place.

The next thing I tried was adding message_body to ad_page_contract and using a validation block to split up the string.  However, ns_log statements here showed a new problem.  The value of message_body when coming into the confirm page doesn't contain the format - it's just the text the user typed into the widget.  So using this method the format is lost entirely.

So, to summarize:

message_body is turned into a string when it is passed through the confirm page in a hidden variable.  The only way to get at the string and split it up before form validation happens for the insert step seems to be to grab it via ad_page_contract, but if I do that for one page I have to do it for all, and this does not work when going into the confirm page because (I'm guessing) "form get_values" is calling a richtext widget proc to get the value ad_page_contract isn't.

Whew. I hope that was somewhat clear.  :)

Collapse
Posted by Janine Ohmer on
The only way I can think of to fix this somewhat gracefully is to split the third "page", where the message actually gets inserted into the database, into it's own file.  That way I can always treat the incoming message as a string, and I can work with it to do what I need to do.  Any better suggestions?
Collapse
Posted by Lars Pind on
Janine,

I've now taken a look and found the problem.

When you export the value, you export the { body format } list as the value of element "message_body".

But if you look at the source behind the edit form with the richtext widget, you see that there are two widgets:

message_body is the textarea into which the text gets entered.

message_body.format is the select box which lets you pick the format.

If you export the values the same way, it works:

set exported_vars [export_vars -form { message_id forum_id parent_id subject html_p confirm_p { message_body $content} { message_body.format $format } }]

Here's a complete patch against the version I have running here:

Index: message-post.tcl
===================================================================
RCS file: /cvsroot/openacs-4/packages/forums/www/message-post.tcl,v
retrieving revision 1.13.2.6
diff -u -r1.13.2.6 message-post.tcl
--- message-post.tcl    24 Mar 2003 09:11:10 -0000      1.13.2.6
+++ message-post.tcl    1 Sep 2003 19:31:17 -0000
@@ -41,10 +41,10 @@
# we use ns_queryget to get the value of html_p because it won't be defined
# until the next element -DaveB

-element create message content \
+element create message message_body \
    -label Body \
-    -datatype text \
-    -widget textarea \
+    -datatype richtext \
+    -widget richtext \
    -html {rows 20 cols 60 wrap soft} \
    -validate {
        empty {expr ![empty_string_p [string trim $value]]} {Please enter a message}
@@ -55,8 +55,8 @@
element create message html_p \
    -label Format \
    -datatype text \
-    -widget radio \
-    -value $html_p \
+    -widget hidden \
+    -value "t" \
    -options {{text f} {html t}}

element create message parent_id \
@@ -93,14 +93,17 @@

if {[form is_valid message]} {
    form get_values message \
-        message_id forum_id parent_id subject content html_p confirm_p subscribe_p
+        message_id forum_id parent_id subject html_p confirm_p subscribe_p message_body
+
+    set content [template::util::richtext::get_property contents $message_body]
+    set format [template::util::richtext::get_property format $message_body]

    if {!$confirm_p} {
        forum::get -forum_id $forum_id -array forum

        set confirm_p 1
        set content [string trimright $content]
-        set exported_vars [export_form_vars message_id forum_id parent_id subject content html_p confirm_p]
+        set exported_vars [export_vars -form { message_id forum_id parent_id subject html_p confirm_p { message_body $content} { m\
essage_body.format $format } }]

        set message(html_p) $html_p
        set message(subject) [ad_quotehtml $subject]

----------

If you would provide a fix for this for 5.0, that would be awesome!

/Lars

Collapse
Posted by Talli Somekh on
Talli the PBC says, "Janine should file a bug, assign it to Lars, then submit a patch. At which point it Lars will take Janine's patch and merge it into 5.0."

talli the PBC

Collapse
Posted by Janine Ohmer on
Thanks, Lars, I'll try that out ASAP.

Talli, why would I go through all that instead of just submitting a fix?

Collapse
Posted by Talli Somekh on
Submitting a fix where? And how? And how should we track those kinds of things so that the next person with an issue can figure out the prob?

It seems what you're suggesting is that its best to announce bugs on the forums and then submit fixes on the forums, too. That would result in having bugs all over the place and no one paying attention to the bug tracker - resulting in over 400 open bugs and over 250 unassigned bugs, some of which have been in the BT for nearly a year.

(In fact, today I looked and out of 8 bugs marked critical, some of which had been marked critical in Nov, 2002, 7 were unassigned.)

Not to be bureacratic, but it would be nice to have a transparent, normalized process. Just because that's the way it's always been done doesn't mean that its the right way.

talli

Collapse
Posted by Janine Ohmer on
Generally speaking, fixes get submitted to CVS.  That's what I've been doing all along - I don't see much need to file a bug report on a bug I can fix!
Collapse
Posted by Janine Ohmer on
And anyway, Lars was providing a fix to a change I'm making that's not publicly avaiable yet.  So there is no fix to provide for 5.0, only a corrected version of my code to be contributed when it's done.

I think a little more process would be a good thing, but it's a very easy thing to overdo.

Collapse
Posted by Talli Somekh on
Because it may be easier for *you* to just fix it, but it's a pain in the ass for the package maintainer to keep track, the release manager to keep track and the rest of the people who have the problem in the future.

Having CVS committers "just do it" may be worse than having the bug fixes show up in the forums. The reason is that then no one hears about it - when someone comes to the forums asking how to fix something in their code, the answer is inevitable, "this is fixed in HEAD - you can try to upgrade or wait until the next version comes out."

It also freezes out those who contribute fixes but don't get it into CVS because the current committers aren't paying attention to the bug tracker or spending their time "just doing it".

Not to pick on you Janine, but we do need to figure out a way for greater developer transparency. The forums were used well here, but in order for development transparency and scalability to be implemented the process should finished with a short bug report stating that there is a fix for a certain problem relating to a certain version with a short patch.

This may seem like the bureacracy of a large corporate software enviro, but it's not. It's the environment of a medium to large open source software community with many users and developers trying to keep track.

The amount of time that will be saved for everyone will make up for any short inconvenience that the developer may face.

talli

Collapse
Posted by Tom Jackson on

If you are not a cvs guru, keeping up with improvements is quite a hassel. I either get the latest buggy release, or download the sometimes broken HEAD.

I seem to stumble over myself every time I try to checkout something, or submit a patch.

I'm never quite sure what there is to checkout and I can't ever locate instructions for doing so. Usually I hunt through the forum archives to locate my last 'call for help with cvs' thread.

Then there is some kind of cvs browse thing setup somewhere. But it isn't really working, or at least it wasn't the last time I tried. I'm not complaining (or am I) but the non-dedicated developer or absent minded types have limited options.

Without a dedicated "Patch Tzar" to go with the "Bug Tzar", I fear the situation will remain about the same. Anyway the easiest "Patch Tzar" is probably cvsweb, no?

I'm not sure there is necessarily a need to file a bug report when you fix a bug that no one else has noticed. As someone who runs into other developers bugs quite often, I can swear that you have to track it down yourself anyway, at least to the file. Then you could look at a recent version (assuming we had cvsweb, or you were a cvs guru). Or you could just fix it yourself, but sometimes you might consult the forums first to see what others think about the problem.

It might be nice to notify package owners when any change is made. Once someone changed the one line of code I contributed to OpenACS. Turns out a bug was introduced, and I found it and fixed it.

Collapse
Posted by Lars Pind on
The cvs web browser it at http://cvs.openacs.org, and it works prefectly.

I added the information to the cvs checkout instructions page:

https://openacs.org/xowiki/Get_the_Code

Thanks for pointing out that there was no pointer to it.

I think the best way to keep package maintainers informed is through cvs notifications. I'm sure there's a way to scope them to particular packages, etc. Would be good to have a nice way to let people subscribe to those.

/Lars

Collapse
Posted by Carl Robert Blesius on
There is a rss feed that Jeff hosts to keep track of the OpenACS CVS http://xarg.net/tools/cvs/rss/ and Simon wrote an OpenACS based aggregator...
Collapse
Posted by Tom Jackson on

I think some kind of cvs notification would work best for me anyway. If I don't get an email, it doesn't exist.