src/main/scala/fis/crm/ui/ContactSnippet.scala
author Tomas Zeman <tzeman@volny.cz>
Tue, 03 Apr 2012 11:46:36 +0200
changeset 27 3a1eb640ff95
parent 16 7be37d58997c
child 35 d77d8194ee59
permissions -rw-r--r--
Snippet package obj.

/*
 * Copyright 2011 Tomas Zeman <tzeman@volny.cz>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package fis.crm.ui

import fis.crm.model._
import net.liftweb.common._
import net.liftweb.http._
import net.liftweb.sitemap._
import net.liftweb.util._
import net.liftweb.util.Helpers._
import net.tz.lift.snippet.{A, CssTr, DataTable, LocTpl, TplPanel, SnippetHelpers}
import scala.xml.{Elem, NodeSeq, Text}

sealed trait ContactLoc {
  def title: String
  def url: List[String]
  def tpl: String
}

case object ListContacts extends ContactLoc {
  def title = "Contacts"
  def url = Nil
  def tpl = "entity/list"
}

case object AddContact extends ContactLoc {
  def title = "Add contact"
  def url = List("add")
  def tpl = "entity/form"
}

case class ShowContact(c: Contact) extends ContactLoc {
  def title = "Contact " + c.linkName
  def url = List(c.id.toString)
  def tpl = "entity/view"
}

case class EditContact(c: Contact) extends ContactLoc {
  def title = "Edit contact " + c.linkName
  def url = List(c.id.toString, "edit")
  def tpl = "entity/form"
}

case class DeleteContact(c: Contact) extends ContactLoc {
  def title = "Delete contact " + c.linkName
  def url = List(c.id.toString, "delete")
  def tpl = "entity/form"
}

object AsContactLoc extends Loggable {
  def apply(pars: List[String]): Box[ContactLoc] = {
    logger.debug("Params: " + pars)
    pars match {
    case List("add") => Full(AddContact)
    case AsLong(id) :: xs => Contact.findByKey(id) map { c => xs match {
      case List("edit") => EditContact(c)
      case List("delete") => DeleteContact(c)
      case _ => ShowContact(c)
    }}
    case Nil => Full(ListContacts)
    case _ => Empty
  }
  }
}

object ContactSnippet extends SnippetHelpers {
  import Loc._

  val prefix = "contact"

  lazy val menu: Menu = Menu("contact.list", ListContacts.title) / "contacts" >>
    EarlyResponse(() => Full(RedirectResponse(url(ListContacts)))) submenus(
      Menu("contact.add", AddContact.title) / prefix / "add",
      Menu.params[ContactLoc]("contact.edit", "Edit contact", parMenu.parser,
        parMenu.encoder) / prefix / * / "edit" >> CalcValue(() => cur.is match {
          case ShowContact(c) => Full(ShowContact(c))
          case _ => Empty
        }) ,
      Menu.params[ContactLoc]("contact.delete", "Delete contact", parMenu.parser,
        parMenu.encoder) / prefix / * / "delete" >> CalcValue(() => cur.is match {
          case ShowContact(c) => Full(ShowContact(c))
          case _ => Empty
        }) ,
      menu1)

  lazy val menu1: Menu = parMenu >> new DispatchLocSnippets {
      def dispatch = { n => (n, cur.is) match {
        case ("list", ListContacts) => listContacts
        case ("panel", ShowContact(c)) => ContactPanel(c)
        case ("form", EditContact(c)) => ContactForm(c).dispatch("")
        case ("form", AddContact) => ContactForm(Contact.createRecord).
          dispatch("")
        case ("form", DeleteContact(c)) => DeleteContactForm(c).dispatch("")
      }}
    } >> LocTpl(_.tpl) >> Hidden

  lazy val parMenu = Menu.params[ContactLoc]("contact",
    Loc.LinkText(l => Text(l.title)),
    AsContactLoc(_) pass { _.foreach { cur(_) } }, _.url) / prefix / **

  def url(l: ContactLoc) = parMenu.toLoc.calcHref(l)

  object cur extends RequestVar[ContactLoc](ListContacts)

  def listContacts: CssTr = {
    val cols = Contact.fieldsForList.map { _.displayName }
    val cells = Contact.contacts.map { c =>
      A(url(ShowContact(c)), Text(c.linkName)) ::
      (Contact.fieldsForList.map { f =>
      c.fieldByName(f.name).map { _.asHtml } openOr NodeSeq.Empty
    }.toList) }.toList
    new DataTable((S ? "Full name") :: cols, cells)
  }

  case class ContactPanel(c: Contact) extends TplPanel(c.fieldsForView.map
    { f => (f.displayHtml, f.asHtml) })

  case class ContactForm(c: Contact) extends LiftScreen {
    object contact extends ScreenVar(c)
    contact.is.fieldsForView.map { f => addFields(() => f) }
    override def finishButton: Elem = <button>{S ? "Save"}</button>
    protected def finish() {
      val c = contact.is
      Contact.getTable.insertOrUpdate(c)
      S.notice("Contact " + c.linkName + " saved")
      S.redirectTo(url(ShowContact(c)))
      ()
    }
  }

  case class DeleteContactForm(c: Contact) extends LiftScreen {
    val confirm = field("Really delete this contact?", false)
    override def finishButton: Elem = <button>{S ? "Delete"}</button>
    protected def finish() {
      confirm.is match {
        case true =>
          Contact.delete(c)
          S.notice("Contact " + c.linkName + " deleted")
          S.redirectTo(url(ListContacts))
        case false =>
          S.redirectTo(url(ShowContact(c)))
      }
      ()
    }
  }
}

import fis.base.ui._

object ContactSnippet2 extends EntitySnippet[Contact] {
  implicit def str2ns(s: String): NodeSeq = Text(s)
  def prefix = "contact2"
  def asEntity(id: Long): Box[Contact] = Contact.findByKey(id)
  def titleList = "Contacts"
  def titleAdd = "Create a contact"
  def titleShow(c: Contact) = "Contact " + c.linkName
  def titleEdit(c: Contact) = "Edit contact " + c.linkName
  def titleDelete(c: Contact) = "Delete contact " + c.linkName
}

// vim: set ts=2 sw=2 et: