[Lift] Re: Advice for maintaining application state

2010-02-25 Thread tiro
because I haven't yet encountered a use case where they correspond to
expected behaviour if the user happens to know how to work with a
tabbed browser.

-- 
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.



[Lift] Re: Advice for maintaining application state

2010-02-24 Thread tiro
Hi,

I had a similar discussion on this list a while ago.

http://groups.google.com/group/liftweb/browse_thread/thread/69898fb5191a074d

I haven't found THE idiomatic answer in Lift. For now I'm using
StatefulSnippets for the more complex cases; they work quite well.
SessionVars are almost always a bad idea IMHO. For the simple cases I
pass URL parameters around.
The thing to remember is that the StatefulSnippet lifecycle is held
together only by hidden fields whose value is posted back (as
explained in the Lift book). So the user can easily work with
different state sets (StatefulSnippets) in parallel on different tabs.

Best wishes,

Tim

-- 
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.



[Lift] Re: Advice for maintaining application state

2010-02-24 Thread tiro
not sure if I posted the link: 
http://groups.google.com/group/liftweb/browse_thread/thread/69898fb5191a074d

-- 
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.



[Lift] Mapper binding Deluxe

2010-02-11 Thread tiro
Hello fellow Heavylifters,

the following small utility classes could be useful for those who
develop somewhat classic data-oriented applications in Lift and with
Mapper:

http://wiki.github.com/tromberg/Winglet/

In short:
 * Do more with less template and snippet code
 * Only execute the parts of your snippet needed by the current
template
 * Deal flexibly with empty fields
 * Display field errors on input forms by default
 * Display result lists in a table

Feedback welcome (work in progress),

Tim

-- 
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.



[Lift] Re: csv request answer

2009-12-30 Thread tiro
I've been happy with the CSV support provided by h2database because
that was already included in the PocketChange example
http://www.h2database.com/html/tutorial.html#csv

But there are over a dozen alternatives I think. Google for java csv
library

It's a good idea IMHO to use a library for handling all the special
cases, escaping etc., and let the user choose some parameters (e.g.
some country versions MS Excel expect semicolons instead of commas)

--

You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.




[Lift] Signup Form: Some error messages are hidden by default

2009-12-27 Thread tiro
Just discovered this issue (1.1-m8): The sign-up form will not display
field errors by default. The user therefore gets the impression that
the application has simply stopped responding. The validation I
checked (and this may be the only one) was the unique e-mail address
validation. If the e-mail address has already been used before, it
sends a FieldError to S.error. Displaying the message would require a
specific call to the Msg-Snippet for that field afaik; but this call
is not generated by the localForm method.

For now I will explicitly call the snippet for the email field in the
surrounding template, so that the message will be displayed above the
whole form.

--

You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.




[Lift] Re: Catch file upload exceptions?

2009-12-22 Thread tiro
Well LiftRules.exceptionHandler was new to me so thanks. Great way to
deal with the really unexpected (like OutOfMemory). Would do in the
short run.
However, the other Tim is correct in that I (and probably other
people) really want to handle this like similarly to a validation
error on any other field. LiftRules.exceptionHandler catches so far
outside, as far as I understand, that the only way to get back into
the workflow would be to kindly ask the user to press the Back button.

--

You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.




[Lift] Re: Catch file upload exceptions?

2009-12-22 Thread tiro
Hi Tim,

thanks for raising this, I did wrap the whole thing like so:


LiftRules.maxMimeSize = 6 * 1024 * 1024
LiftRules.maxMimeFileSize = 5 * 1024 * 1024

LiftRules.handleMimeFile = (fieldName, contentType, fileName,
inputStream) =  {
  try {
OnDiskFileParamHolder(fieldName, contentType, fileName,
inputStream)
  }
  catch {
case e:Exception =
  S.error(Failure in upload (file too large?). Details:  +
e.toString)
  new InMemFileParamHolder(, , , null)
case _ = new InMemFileParamHolder(, , , null)
  }
}

and now I remember that I did manage to catch an exception once when I
set the maxMimeFileSize to very low. Then I set it back to where it
was and tested with a 7MB file.
I think I understand now: The above will catch based on
maxMimeFileSize. It will not work when the file you upload also
exceeds the maxMimeSize, which is when you get the stack trace at the
beginning of my post.

So I suppose the solution is to set the maxMimeSize to Infinity.

Marius, thanks for the hint. Was just a quick idea how to keep face
with users in such a case, since I'm running on a virtual server, but
it's clear such conditions should really be avoided by proper
configuration and load testing.

Best wishes, Tim


--

You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.




[Lift] Beware of using a body tag in a surrounded template, especially with nested surrounds

2009-12-01 Thread tiro
Hi,

I think it is documented somewhere in the Liftbook that one should not
use body tags inside a surround tag, but Lift doesn't seem to
complain.

I thought I would document the phenomenon I had here since people
usually look in the mailing list first.

I had used two nested surround templates, where both templates used a
body tag. (The inner template would start by surrounding itself with
the outer template, then bind the working content itself inside the
body tag).

Worked fine in Lift 1.0, but in 1.1, the working content would appear
twice in the generated HTML, once at the very beginning, and then in
the correct place inside the two nested surround templates.

Long-term, it would be great to get an error message in this case.

Regards,
Tim


--

You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to lift...@googlegroups.com.
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.




[Lift] Re: A Critique On Lift

2009-10-22 Thread tiro

 override def validations = validPriority _ :: super.validations
funny, I had stumbled on exactly the same line of code when beginning.
Took me more than a day to understand what's going on. Especially
because when you copied code from the PDF version of the Liftbook/Lift
getting started guide, it would mess up spaces, so I would keep
loooking for a _:: operator.
The Scala guys have really pushed it a bit hard on the use of the
underscore. At least four different uses:
- it for defining anonymous functions like above
- default value
- matching placeholder whose value is ignored
- use for constructing setter method names boolean functions (empty_?)


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: Tabbed browsing and session state

2009-09-27 Thread tiro


Naftoli,
thanks for providing these insights into the inner workings of
Stateful Snippets. The mapSnippet solution sounds interesting. I knew
that snippets don't live on when not needed, but assumed that IF one
is alive in the current session, you would always get that one
instance. Hence at most one instance would be alive per snippet class
and per session. What you seem to indicate is that the lifecycle is
held together by redirects and such (and therefore page ids) rather
than two requests being in the same session. I will experiment how
that works with tabs. I guess one has to still be very careful since
the user may go from the view initiating a snippet and open several
tabs from there, whereafter you could still get unwanted interference
between the tabs if you don't pay attention.


Marius, thanks for your points
Wizard code
exciting.. since the wizardiness probably won't jump into my eye, if
you happen to stumble on it in the next few days, could you perhaps
post a classname here?

That data needs to be preserved into a RequestVar,
That is precisely what I meant by passing state on from a response to
the next request :-) RequestVars are benign.

AJAX Tabs
Had briefly thought of that. Makes good sense with some types of apps.
In this particular app I've already made other compromises to preserve
standard behavior and let the user bookmark the current URL etc.
Actually things would already be much simpler if browsers allowed you
to address tabs by Javascript (close current tab, jump to search
results tab). One could then keep the results list open in a user-
friendly way. But apparently browsers have been getting quite
restrictive on that, for obvious reasons.


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Tabbed browsing and session state

2009-09-26 Thread tiro

Hi,
has anyone investigated or built a way to support tabbed browsing when
there is considerable view/workflow state? Or have I missed an elegant
way for this to be done in Lift?

If I am not mistaken, Lift currently supports
 1. Sending continuations (things that will need to be done) from one
Request to the next in the form of FuncHolders that are attached to an
ID that is unique for a sent page. This works perfectly in a tabbed
environment, and you can send state this way, but the state doesn't
live on in the response sent by the snippet that has received it.
 2. Session variables that are global to the session, as well as
 3. Stateful snippets that are instantiated at most once in each
session.
When assuming that your user knows how to browse tabbed, I can
currently not imagine what 2. and 3. could be practically useful for.
Very often though, it seems, people use these mechanisms and then
later realize the mess they are in.

E.g. (quite funny) 
http://www.highdots.com/forums/javascript/browser-tab-269390.html
More serious:
http://www.codeodor.com/index.cfm/2007/7/19/Why-tabbed-browsing-makes-holding-form-state-with-sessions-obsolete/1470

A simple example from an application I'm developing, and I'll bet more
than half of all Web apps, is this: I have one page where users can
search for a bunch of documents in a database (search form and result
list are on the same page - let's not make it too complicated).
Clicking on a result will navigate to the detail view of a document. I
am sure sooner or later the customer will want a link on the detail
view to go back to the search he came from.

If I put the last search parameters used into Session Vars, this will
not work if the customer uses several such result lists in parallel
(not unrealistic in this case). He will always end up going back to
the last search used, not the one that was used to open the detail
view. Very bad behavior for example when the user has edited an item,
and it then vanishes from his view.

What would work is: put the search parameters into hidden fields and/
or URL parameters of the detail view. But you break your fingers doing
that and it gets really messy when the detail view can be opened from
several different context, and the conversation that takes you back to
the original context has several steps. There is also a limit to what
you can put into a URL, I believe. You use a framework because it
saves you these kinds of headaches.

It seems to me, Lift already has 80% of what it takes for a great
solution. It is the mechanism mentioned under 1. Any tab that is still
open calls home regularly to say I'm still here, don't forget me.
This is good because otherwise we would have to consider any page ever
sent to the client to still be open and come back to haunt us,
demanding us to behave as if nothing had happened since. The existing
mechanism would only need to allow the state to be passed on, with a
delta, to the next response-request episode.







--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Re: Tabs + menu builder

2009-09-19 Thread tiro

Jeppe We've made primary/secondary navigation where primary
navigation is ...

I did something similar..found it difficult to work with the default
snippets.
But found it hard, when writing my own group snippet, to identify the
current Loc within the LocGroups Locs.

So Jeppe, would be very interested in your code for that snippet. Mine
is below (only slightly modified from Menu.group). But it's not yet
quite there.

I also had a fiendish problem (lift 1.0.2 scala 2.7.5) when trying to
use attributes li:class=x li_item:class=y on the tag. Isn't that a
standard technique? Does it work for everyone else? For me, Scala
chokes on that with a syntax error (further experiments suggest that
it doesn't like two attributes with same name and different prefix,
perhaps also because BOTH prefixes are from an unknown namespace). Of
course it doesn't show you the exact error but faults with an
IllegalArgumentException on scala.io.Source, but this has been
discussed elsewhere. Anyway, that's why I have the new unprefixed
attributes in the code below.

  def menuGroup(template: NodeSeq): NodeSeq = {
val a_attrs = S.prefixedAttrsToMetaData(a)
val li_attrs = S.attr(normalclass) match { case Full(c: String)
= new UnprefixedAttribute(class, c, Null); case _ = Null }
val li_sel_attrs = S.attr(selectedclass) match { case Full(c:
String) = new UnprefixedAttribute(class, c, Null); case _ = Null }
val currentLoc = LiftRules.siteMap.open_!.findLoc
(S.request.open_!) openOr null

for (group - S.attr(group).toList;
 siteMap - LiftRules.siteMap.toList;
 loc - siteMap.locForGroup(group);
 link - loc.createDefaultLink;
 linkText - loc.linkText) yield {
  val a = a href={link}{linkText}/a % a_attrs
  var li: Elem = li{a}/li
  if (loc == currentLoc)
li % li_sel_attrs
  else
li % li_attrs
}
  }

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---



[Lift] Mapper: Why is every SQL query sent twice? (second time with NULL parameters)

2009-09-14 Thread tiro

Dear all,

on every findAll request, lift seems to send the query twice (tested
1.0 and 1.0.2, working from the PocketChangeApp example on h2database,
and using
 DB.addLogFunc((query, time) =
  Log.info(query + : + time + ms)))

for logging

1. e.g. right after login; this must be framework code (ProtoUser):

INFO - prep91: SELECT users.firstname, users.lastname, users.email,
users.locale, users.timezone, users.password_pw, use
rs.password_slt, users.superuser, users.validated, users.uniqueid,
users.id FROM users  WHERE email = ?  {1: 't...@rombe
rg.be'};:14ms
INFO - prep91: SELECT users.firstname, users.lastname, users.email,
users.locale, users.timezone, users.password_pw, use
rs.password_slt, users.superuser, users.validated, users.uniqueid,
users.id FROM users  WHERE email = ?  {1: NULL};:65ms

same on practically all other statements

2nd example:

INFO - prep110: SELECT  DISTINCT resourcestopics.resourcetype,
resourcestopics.resourceid, resourcestopics.topicid FROM
resourcestopics   WHERE resourcetype = ?  AND resourceid = ?   {1: 2,
2: 3};:0ms
INFO - prep110: SELECT  DISTINCT resourcestopics.resourcetype,
resourcestopics.resourceid, resourcestopics.topicid FROM
resourcestopics   WHERE resourcetype = ?  AND resourceid = ?   {1:
NULL, 2: NULL};:27ms
INFO - Service request (POST) /editProject.html took 748 Milliseconds

my code: findAll(By(ResourcesTopics.resourceType, resourceType), By
(ResourcesTopics.resourceId, resourceId))


Is this desired behavior? Am only I seeing this? It also seems that
the useless query takes much more time than the real query..

Tried to compare with one of the most recent milestone (1.1-M5) but
this one only throws exceptions on me, starting from boot, so I
suppose there have been too many changes I am not aware of.


Thanks,

Tim

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Lift group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to 
liftweb+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~--~~~~--~~--~--~---