Forum OpenACS Development: Trying to get it right with ad_form

Collapse
Posted by Janine Ohmer on
These may well have been asked already, but searching for ad_form returns such a huge number of hits that, well, I'll never know.

I am adding the ability to upload content from a file to static-portlet (client request) and thought it would be "fun" to convert it to ad_form while I was at it.  I have it working, and even mananged to consolidate the separate new and edit features into one set of files, but I'm stuck on a couple of things:

1.
I'm using content_id as my key.  This works, in the sense that it leads the code to use the right block (edit or new).  But I'm not using the value that's being generated for me.  New static portlets are created by a call to static_portlet_content::new, which returns the id of the new object.  Yes, I know there's no double-click protection here but only admins can do this and I don't really have time to rewrite the entire package (this was enough of a diversion).

So, given that I'm not using the value and a number in the acs_object sequence is being wasted, how bad is this?  Bad enough to not use the key management feature at all?

2.
When editing an existing portlet I'd like to be able to use it's title in the page template, but it's not available outside the form.  Is there any way to get at it besides pulling it from the database a second time?

Thanks in advance!

janine

Collapse
Posted by Don Baccus on
I wouldn't worry about the hole in the acs_object sequence, chalk this up to poor design - all "new" Tcl and PL/[pg]SQL procs should allow the caller to provide the new object_id optionally.  That's been the 4.x design since [aD] day one and there's no excuse for its having been violated.

I don't understand the second problem ...

Collapse
Posted by Janine Ohmer on
Thanks, Don!

Let me try again.  The title of a custom portlet is stored in the field pretty_name.  It's pulled out of the database for use in the for by the query specified in the select_query_name clause.  But I can't use it in the template, say to put "Editing Custom Portlet $pretty_name" at the top, because it's not defined outside the form.

What I wanted to know is is there some syntax by which I can reference the variable within the form, or do I have to also get it from the database myself in the .tcl script if I want to use it?

Is that more clear?

Collapse
Posted by Dave Bauer on
If the title is being retreived from the database and assigned to an element on the form it should be available.

If you element is named title, a tcl variable of the same name should exist.

Collapse
Posted by Janine Ohmer on
This just doesn't seem to be working for me.

I've got two forms, one called static_element and the other called static_file.  Each of them contains a variable called pretty_name, which happens to be the same for both (you can either edit the content in a text area or upload a file, and in either case you can edit the portlet's title).

I've tried referring to it as @pretty_name@ and also as @static_element.pretty_name@, but it's not found either way.  What am I doing wrong?

Collapse
Posted by Don Baccus on
Can you post the full script here?
Collapse
Posted by Janine Ohmer on
Ok, here we go:

element.tcl:

ad_page_contract {
    edit a static element

    @author arjun (arjun@openforce)
    @cvs_id $Id: element.tcl,v 1.2 2003/05/30 16:15:56 janine Exp $
} -query {
    content_id:optional
    referer:notnull
    portal_id:integer,notnull
    {package_id:integer ""}
}  -properties {
    title:onevalue
}

set element_pretty_name [ad_parameter static_admin_portlet_element_pretty_name static-portlet]
if { [ad_form_new_p -key content_id] } {
  set title "New $element_pretty_name"
  set new_p 1
} else {
  set title "Edit $element_pretty_name"
  set new_p 0
}

#these are set for display and instructions.
set community_id $package_id

set portal_name [portal::get_name $portal_id]

ad_form -name static_element -form {
    content_id:key
    {pretty_name:text(text)     {label "Name"} {html {size 60}}}     {content:text(textarea)     {label "Content"} {html {rows 15 cols 80 wrap soft}}} 
    {portal_id:text(hidden)     {value $portal_id}}
    {package_id:text(hidden)    {value $package_id}}
    {referer:text(hidden)       {value $referer}}
} -select_query_name get_content_element -validate {
} -new_data {
    db_transaction {
        set item_id [static_portal_content::new \ 
                         -package_id $package_id  \
                         -content $content \
                         -pretty_name $pretty_name
        ]
        
        static_portal_content::add_to_portal \
            -portal_id $portal_id \ 
            -package_id $package_id \
            -content_id $item_id
    }
        
    # redirect and abort
    ad_returnredirect $referer
    ad_script_abort
} -edit_data {
    db_transaction {
        static_portal_content::update \
                -portal_id $portal_id \ 
                -content_id $content_id \ 
                -pretty_name $pretty_name \
                -content $content
    }
    
    # redirect and abort
    ad_returnredirect $referer
    ad_script_abort
}


ad_form -name static_file -html {enctype multipart/form-data} -form {
    content_id:key
    {pretty_name:text(text)     {label "Name"} {html {size 60}}}
    {upload_file:file           {label "File"}}
    {portal_id:text(hidden)     {value $portal_id}}
    {package_id:text(hidden)    {value $package_id}}
    {referer:text(hidden)       {value $referer}}
} -select_query_name get_content_element -validate {
} -new_data {
    set filename [template::util::file::get_property filename $upload_file]    set tmp_filename [template::util::file::get_property tmp_filename $upload_file]   
    set mime_type [template::util::file::get_property mime_type $upload_file]    if { [string equal -length 4 "text" $mime_type] || [string length $mime_type] == 0 } {
      # it's a text file, we can do something with this
      set fd [open $tmp_filename "r"]
      set content [read $fd]
      close $fd
    } else { 
      # they probably wanted to attach this file, but we can't do that.      set content "Binary file $filename was uploaded but we only support text files here"
    }
    
    db_transaction {
        set item_id [static_portal_content::new \ 
                         -package_id $package_id  \
                         -content $content \
                         -pretty_name $pretty_name
        ]
        static_portal_content::add_to_portal \
            -portal_id $portal_id \ 
            -package_id $package_id \
            -content_id $item_id
    }
        
    # redirect and abort
    ad_returnredirect $referer
    ad_script_abort
} -edit_data {
    set filename [template::util::file::get_property filename $upload_file]
    set tmp_filename [template::util::file::get_property tmp_filename $upload_file]       set mime_type [template::util::file::get_property mime_type $upload_file]
    if { [string equal -length 4 "text" $mime_type] || [string length $mime_type] == 0 } {
      # it's a text file, we can do something with this
      set fd [open $tmp_filename "r"]
      set content [read $fd]
      close $fd
    } else {      # they probably wanted to attach this file, but we can't do that.
      set content "Binary file $filename was uploaded but we only support text files here"
    }
        
    db_transaction {
        static_portal_content::update \ 
                -portal_id $portal_id \
                -content_id $content_id \
                -pretty_name $pretty_name \
                -content $content
    } 
    
    # redirect and abort
    ad_returnredirect $referer
    ad_script_abort
}
I was going to include element.adp also but the HTML filter goes haywire on all the things it thinks are invalid tags, like master. Let me know if you need to see it and I'll send it via e-mail.

If I've done anything wrong here please let me know, even if it's unrelated to my question - this is my first time using ad_form and I may well have gotten something wrong.

Now that I've posted all this I might as well ask if there's any objection to my committing this change to the toolkit? Seems like it would be generally useful.

Thanks!

Collapse
Posted by Dave Bauer on
Can you post the select query text? Also which element refers to the title? Pretty Name?

Does it work the way you have it now, where it grabs the name and pretty name in a tcl proc?

Collapse
Posted by Ola Hansson on
Janine

This has not got to do with the problem at hand, but I think you might be needing a "upload_file.tmpfile:tmpfile,optional" in your query section. But then again it may not be quite necessary ...

Collapse
Posted by Janine Ohmer on
Ok, here's the query text:
            select body as content, pretty_name
            from static_portal_content
            where content_id = :content_id
It does work the way it is now, because I'm not attempting to reference pretty_name in the template.

Don't get element_pretty_name, which is "Custom Portlet" in the default case, confused with pretty_name which is the title of the specific portlet you are working with. pretty_name is being retrieved from the database by the select query, and is showing up properly in the edit form, but doesn't seem to be available in the template.

Ola, it seems to be working ok without that, but it might be dumb beginner's luck. :)

I should explain about the "body as content" thing. Originally the text that appears in the static portlet was stored in a varchar called content. I changed that to a LOB, and in order to do the upgrade script it had to have a different name; I used body. But I didn't want to make people who had custom templates change the variable name, so I changed it in the database and left all references to it under the original name.

Collapse
Posted by Jun Yamog on
Hi Janine,

What dumb luck.  Anyway I have done something similar.  But normally i use -edit_request.

I know the use of -select_query_name is correct in your case.  But just try this for dumb luck:

-edit_request {
  do your query here

  ad_set_form_values content, pretty_name, etc.
}

Collapse
Posted by Janine Ohmer on
Jun, that worked. thanks!  I still don't quite understand why, but as long as it works I guess I'm ok.

BTW, sorry about the missing line breaks in the code I posted above.  For some reason on Mac OS X that happens sometimes when copying from a terminal window and pasting elsewhere, and I forgot to check for it before submitting.

If anyone thinks this would be a bad addition to static portlet speak up soon;  otherwise it will go in with my next batch of bug fixes.

Collapse
Posted by Jun Yamog on
Hi,

If that dumb luck suggestion worked.  Then -select_query_name has a bug... I think.  Either that or I have been using ad_form since a year ago wrongly.

If others think that its a bug, then if possible that Janine puts up a new bug report.

Collapse
Posted by Janine Ohmer on
Good idea, Jun - bug 746 now documents this for anyone who wants to look into it further.