Best way to fill in grid like page?

252 views
Skip to first unread message

Diego Medina

unread,
Dec 23, 2010, 10:59:56 AM12/23/10
to lif...@googlegroups.com
Hi,

I'm working on this application where I need to fill in a grid/table
with test results.
The final table would have about 40-50 rows and about 10 columns.

The way I get the test results from the database is something like this:


val testResultNoSSL= Map(
"Sol 10 Sparc 32Bit" -> ("Solaris", "PASS"),
"Sol 10 Sparc 64" -> ("Solaris", "PASS"),
"Sol 10 x86 64" -> ("Solaris", "FAIL")
)
val testResultSSL= Map(
"Sol 10 Sparc 32Bit" -> ("Solaris", "PASS"),
"Sol 10 Sparc 64" -> ("Solaris", "FAIL"),
"Sol 10 x86 64" -> ("Solaris", "FAIL")
)


in the final app, those maps would have about 40-50 different entries,
and they may not all have the same "keys", because we do not get the
results for all tests at the same time. In the UI, the "missing
entries" should show as N/A or something like that.

testResultNoSSL has the results for "the first column, testResultSSL
for the second column and I have 8 more vals with similar results.

What I can't get in a clean way is a way to add this information to a
page, so I was hoping someone on the list would be able to help me.

As this may be a bit confusing, I posted a small lift app on github
https://github.com/fmpwizard/lift-grid
so that you guys can try different things.

Once you get the branch, you can run it under sbt

sbt

> update
> ~jetty-run

and you can go to

http://127.0.0.1:8080/agent-details?v=2.4.0.1090

to see the page I'm talking about.

Thanks

Diego


--
Diego Medina
Web Developer
http://www.fmpwizard.com

David Pollak

unread,
Dec 23, 2010, 12:25:46 PM12/23/10
to lif...@googlegroups.com
See this patch: https://github.com/dpp/lift-grid/

First we define some data structures (case classes) and load the results into collections:

    case class Result(OS: String, pass: Boolean) {
      def clss = if (pass) "success" else "error"
    }

    case class TestRow(tests: Map[Int, Option[Result]])

    // a list of all our tests
    val tests = List(testResultNoSSL, testResultSSL, testResultNoSSLQuan, testResultSSLQuan, testResult200Scalability)

    // a set of the keys of the tests
    val osSet = Set(tests.flatMap(_.keys) :_*)

Next, take the tests and normalize them:

    val results: Map[String, TestRow] = Map(osSet.toSeq.map{
      set =>
        (set, TestRow(Map(tests.zipWithIndex.map {
          case (test, idx) => idx -> test.get(set).map{ case (os, pass) => Result(os, pass == "PASS")}
        } :_*)))
      }:_*)

Define a convenience method:

def *(f: NodeSeq => NodeSeq): NodeSeq => NodeSeq = {case e: Elem => f(e.child) case x => f(x)}

And bind the results:

ClearClearable andThen
    "h2 *" #> *(_ ++ Text(showingVersion)) &
    "#row *" #> results.map {
      case (name, row) => "#col" #> (
        ("* *" #> name) :: row.tests.toList.map {
          case (pos, Some(res)) => "* *" #> res.OS & "* [class]" #> res.clss
          case (pos, _) => "* *" #> "N/A"
        }
        )
    }

ClearClearable gets rid of the elements marked with the class Clearable

"h2 *" #> *(_ ++ Text(showingVersion))

Takes the contents of the h2 block and appends the version name

"#row *" #> results.map {

For each of the operating systems, create a row.

#col" #> (
        ("* *" #> name) :: row.tests.toList.map {
          case (pos, Some(res)) => "* *" #> res.OS & "* [class]" #> res.clss
          case (pos, _) => "* *" #> "N/A"
        }
        )

Create a column containing the name and for each test in our list of tests, if there is a test result, insert the OS into the column element and set the class to success or error.  If there is no test, insert an N/A.

Note that this code will work identically if your designer chooses table/tr/td or ul/li.

Hope this helps.

Markup:

    <lift:AgentDetails.renderAgentResult>
      <h2>Agent results for version: </h2>
      <table>
<tr>
          <th>Platform</th>
          <th>NO SSL</th>
          <th>SSL</th>
          <th>Agent, Proxy <br />(No SSL, QUAN)</th>
          <th>Agent, Proxy <br />(SSL, QUAN)</th>
          <th>200 Agent scalability</th>
</tr>


<tr id="row">
          <td id="col">Sol 10 Sparc 32Bit</td>
          <td class="clearable"> No SSL </td>
          <td class="clearable"> ssl </td>
          <td class="clearable"> agent_proxy_no_ssl_quan </td>
          <td class="clearable"> agent_proxy_ssl_quan </td>
          <td class="clearable"> 200_agent_scalability </td>
</tr>

        <tr class="clearable">
          <td id="col">Sol 10 Sparc 32Bit</td>
          <td > No SSL </td>
          <td class="clearbale"> ssl </td>
          <td class="clearable"> agent_proxy_no_ssl_quan </td>
          <td class="clearable"> agent_proxy_ssl_quan </td>
          <td class="clearable"> 200_agent_scalability </td>
        </tr>

        <tr class="clearable">
          <td id="col">Sol 10 Sparc 32Bit</td>
          <td > No SSL </td>
          <td class="clearbale"> ssl </td>
          <td class="clearable"> agent_proxy_no_ssl_quan </td>
          <td class="clearable"> agent_proxy_ssl_quan </td>
          <td class="clearable"> 200_agent_scalability </td>
        </tr>
      </table>
    </lift:AgentDetails.renderAgentResult>

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




--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Blog: http://goodstuff.im
Surf the harmonics

Diego Medina

unread,
Dec 24, 2010, 12:10:27 AM12/24/10
to lif...@googlegroups.com
Thanks David, it works great!

Just one question:

On Thu, Dec 23, 2010 at 12:25 PM, David Pollak
<feeder.of...@gmail.com> wrote:
[snip]


> Next, take the tests and normalize them:
>
>     val results: Map[String, TestRow] = Map(osSet.toSeq.map{
>       set =>
>         (set, TestRow(Map(tests.zipWithIndex.map {
>           case (test, idx) => idx -> test.get(set).map{ case (os, pass) =>
> Result(os, pass == "PASS")}
>         } :_*)))
>       }:_*)
>

what does the :_*) do/mean?

Again, thanks, I did not think of using case classes, but even if I
did, the way you used it and the css selectors is something I need to
read more about.

Diego

It did everything I asked for :)

David Pollak

unread,
Dec 24, 2010, 10:00:41 AM12/24/10
to lif...@googlegroups.com
On Thu, Dec 23, 2010 at 9:10 PM, Diego Medina <di...@fmpwizard.com> wrote:
Thanks David, it works great!

Just one question:



On Thu, Dec 23, 2010 at 12:25 PM, David Pollak
<feeder.of...@gmail.com> wrote:
[snip]
> Next, take the tests and normalize them:
>
>     val results: Map[String, TestRow] = Map(osSet.toSeq.map{
>       set =>
>         (set, TestRow(Map(tests.zipWithIndex.map {
>           case (test, idx) => idx -> test.get(set).map{ case (os, pass) =>
> Result(os, pass == "PASS")}
>         } :_*)))
>       }:_*)
>

what does the     :_*)  do/mean?


It's a Scala thing.

If you have a var arg method:

def myMeth(s: String*)

But you've already got a collection:

val myVar: Seq[String] = ....

you want to be able to tell the compiler that you've already put together the var arg:

myMeth(myVar :_*)


 
Reply all
Reply to author
Forward
0 new messages