--- a/db/db-schema.sql Fri Apr 20 08:44:36 2012 +0200
+++ b/db/db-schema.sql Fri Apr 20 09:45:51 2012 +0200
@@ -34,22 +34,6 @@
create sequence "code_list_item_id_seq";
-- indexes on code_list_item
create index "code_list_item_code_list_idx" on "code_list_item" ("code_list");
-create table "user" (
- "name" varchar(100) not null,
- "updated_at" timestamp not null,
- "id" bigint primary key not null,
- "note" varchar(10240),
- "created_at" timestamp not null,
- "created_by" bigint,
- "login" varchar(40) not null,
- "updated_by" bigint,
- "deleted" boolean not null,
- "active" boolean not null,
- "password" varchar(128) not null
- );
-create sequence "user_id_seq";
--- indexes on user
-create index "user_login_idx" on "user" ("login");
create table "city" (
"name" varchar(100) not null,
"updated_at" timestamp not null,
@@ -142,6 +126,26 @@
"contact" bigint not null,
"entity" bigint not null
);
+create table "user" (
+ "name" varchar(100) not null,
+ "updated_at" timestamp not null,
+ "id" bigint primary key not null,
+ "note" varchar(10240),
+ "created_at" timestamp not null,
+ "created_by" bigint,
+ "login" varchar(40) not null,
+ "updated_by" bigint,
+ "deleted" boolean not null,
+ "active" boolean not null,
+ "password" varchar(128) not null
+ );
+create sequence "user_id_seq";
+-- indexes on user
+create index "user_login_idx" on "user" ("login");
+create table "user_contact" (
+ "contact" bigint not null,
+ "entity" bigint not null
+ );
-- foreign key constraints :
alter table "address" add constraint "addressFK1" foreign key ("city_id") references "city"("id");
alter table "city" add constraint "cityFK2" foreign key ("country_id") references "country"("id");
@@ -150,7 +154,10 @@
alter table "bank_account" add constraint "bank_accountFK5" foreign key ("company_id") references "company"("id") on delete cascade;
alter table "company_contact" add constraint "company_contactFK6" foreign key ("entity") references "company"("id") on delete cascade;
alter table "company_contact" add constraint "company_contactFK7" foreign key ("contact") references "contact"("id") on delete cascade;
+alter table "user_contact" add constraint "user_contactFK8" foreign key ("entity") references "user"("id") on delete cascade;
+alter table "user_contact" add constraint "user_contactFK9" foreign key ("contact") references "contact"("id") on delete cascade;
-- composite key indexes :
alter table "company_contact" add constraint "company_contactCPK" unique("entity","contact");
+alter table "user_contact" add constraint "user_contactCPK" unique("entity","contact");
-- column group indexes :
create index "user_deleted_active_idx" on "user" ("deleted","active");
--- a/src/main/scala/fis/aaa/model/AaaSchema.scala Fri Apr 20 08:44:36 2012 +0200
+++ b/src/main/scala/fis/aaa/model/AaaSchema.scala Fri Apr 20 09:45:51 2012 +0200
@@ -16,12 +16,13 @@
package fis.aaa.model
import fis.base.model.BaseSchema
+import fis.crm.model.{Contact, CrmSchema, EntityContact}
import net.liftweb.squerylrecord.RecordTypeMode._
/**
* Database schema for users, ...
*/
-trait AaaSchema extends BaseSchema {
+trait AaaSchema extends BaseSchema with CrmSchema {
val userT = tableWithSeq[User]
on(userT)(t => declare(
t.login defineAs(indexed("user_login_idx")),
@@ -38,8 +39,28 @@
val activeUsersF = () => from(userT)(u =>
where(u.deleted === false and u.active === true) select(u)
orderBy(u.name asc))
+
+ val userContacts = manyToManyRelation(userT, contactT).
+ via[UserContact]((u, c, uc) => (
+ u.id === uc.entity,
+ c.id === uc.contact
+ ))
+ userContacts.leftForeignKeyDeclaration.constrainReference(onDelete cascade)
+ userContacts.rightForeignKeyDeclaration.constrainReference(onDelete cascade)
+
}
object AaaSchema extends AaaSchema
+case class UserContact(entity: Long, contact: Long) extends
+ EntityContact[User]
+
+object UserContacts {
+ def apply(u: User): Iterable[Contact] =
+ from(AaaSchema.userContacts.left(u)) (c =>
+ select(c) orderBy(c.lastName asc, c.firstName asc)
+ )
+}
+
+
// vim: set ts=2 sw=2 et:
--- a/src/main/scala/fis/aaa/ui/UserSnippet.scala Fri Apr 20 08:44:36 2012 +0200
+++ b/src/main/scala/fis/aaa/ui/UserSnippet.scala Fri Apr 20 09:45:51 2012 +0200
@@ -18,8 +18,11 @@
import fis.base.model._
import fis.base.ui._
import fis.aaa.model._
+import fis.crm.model.{Contact, ContactCrud, CrmSchema}
+import fis.crm.ui.ContactTable
import net.liftweb.common._
import net.liftweb.http._
+import net.liftweb.http.js.JsCmds.RedirectTo
import net.liftweb.sitemap._
import net.liftweb.sitemap.Loc._
import net.liftweb.util._
@@ -41,7 +44,8 @@
private val viewPre = Menu.param[User]("user.view", l10n("User"), parse,
encode) / prefix / * >> Title(c => i18n("User %s", c.linkName)) >>
- locTpl("entity/view") >> Snippet("panel", panel) >> Hidden
+ locTpl("user/view") >> Snippet("panel", panel) >>
+ Snippet("contacts", contacts.contacts) >> Hidden
private val editPre = Menu.param[User]("user.edit", l10n("Edit"), parse,
encode) / prefix / * / EDIT >>
@@ -55,7 +59,8 @@
private val listM = listPre >> SecNav(createPre).build
private val createM = createPre >> SecNav(listPre).build
- private val viewM = viewPre >> (SecNav(editPre) + deletePre).build
+ private val viewM = viewPre >>
+ (SecNav(editPre) + deletePre + contacts.chooseM).build
private val editM = editPre >> SecNav(viewPre).build
private val deleteM = deletePre >> SecNav(viewPre).build
@@ -63,7 +68,8 @@
private lazy val editLoc = editM.toLoc
private lazy val deleteLoc = deleteM.toLoc
- val menu = listM submenus(viewM, editM, createM, deleteM)
+ val menu = listM submenus(viewM, editM, createM, deleteM,
+ contacts.chooseM, contacts.confirmM)
private def cur = viewLoc.currentValue or editLoc.currentValue or
deleteLoc.currentValue
@@ -135,6 +141,79 @@
}
}
+ /* Contacts view + add contact op. */
+ private object contacts {
+
+ private val choosePreM = Menu.param[User]("user.addContact",
+ l10n("Add contact"), parse, encode) / prefix / * / "add-contact" >>
+ Title(c => i18n("Add contact to %s", c.linkName)) >>
+ locTpl("entity/add-contact") >> Snippet("panel", chooseContact) >> Hidden
+
+ val confirmM = Menu.params[(User, Contact)](
+ "user.addContactId", l10n("Add contact"), { _ match {
+ case AsLong(uId) :: AsLong(cntId) :: Nil => for {
+ u <- get(uId)
+ cnt <- ContactCrud.get(cntId)
+ } yield (u, cnt)
+ case _ => Empty
+ }},
+ { p => List(p._1, p._2) map(_.id.toString) }) / prefix /
+ * / "add-contact" / * >>
+ Title(p => i18n("Add contact %s to %s", p._2.linkName, p._1.linkName)) >>
+ locTpl("entity/form") >> Snippet("form", addContact) >> Hidden
+
+ val chooseM = choosePreM >> SecNav(viewPre).build
+
+ private case class RemoveContactLink(u: User, cnt: Contact) extends
+ ReadOnlyField("actions", "", ConfirmationLink(i18n("Remove"),
+ l10n("Really remove contact?"), {
+ AaaSchema.userContacts.left(u).dissociate(cnt)
+ RedirectTo(viewLoc.calcHref(u))
+ }), Empty)
+
+ def contacts: CssTr = "*" #> cur.map { u =>
+ FieldTable[Contact]({ c => ContactTable.fields(c).toSeq :+
+ RemoveContactLink(u, c) }, Contact)(UserContacts(u)) }
+
+ private case class AddContactLink(u: User, c: Contact) extends
+ EntityLink[Contact](c,
+ { _ => Full(confirmM.toLoc.calcHref((u, c))) })
+
+ private def chooseContact: CssTr = "*" #> chooseM.toLoc.currentValue.map {
+ u =>
+ FieldTable[Contact]({ c =>
+ List(AddContactLink(u, c)) }, Contact)(CrmSchema.allContacts)
+ }
+
+ private object addContact extends HorizontalScreen with CancelButton
+ with SaveButton {
+
+ override def screenFields: List[BaseField] = (for {
+ (u, c) <- confirmM.toLoc.currentValue
+ ul <- EntityLink(u)
+ cl <- EntityLink(c)
+ } yield {
+ List(ReadOnlyField(l10n("User"), ul),
+ ReadOnlyField(l10n("Contact"), cl)) flatMap(_.allFields)
+ }) openOr Nil
+
+ def finish() { for {
+ (u, c) <- confirmM.toLoc.currentValue
+ } {
+ val fk = AaaSchema.userContacts.left(u)
+ fk.exists(_.id == c.id) match {
+ case true =>
+ S notice l10n("Contact %s is already associated with %s",
+ c.linkName, u.linkName)
+ case false =>
+ fk.associate(c)
+ S notice l10n("Added contact %s", c.linkName)
+ }
+ S redirectTo viewLoc.calcHref(u)
+ }}
+ }
+ }
+
}
// vim: set ts=2 sw=2 et:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/webapp/entity/add-contact.html Fri Apr 20 09:45:51 2012 +0200
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta content="text/html; charset=UTF-8" http-equiv="content-type" />
+ <title>Entity View</title>
+ </head>
+ <body class="lift:content_id=main">
+ <div id="main" class="lift:surround?with=default;at=content">
+ <div class="row">
+ <div class="span5">
+ <span class="lift:panel"></span>
+ </div>
+ </div> <!-- /row -->
+ </div>
+ </body>
+</html>
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/webapp/user/view.html Fri Apr 20 09:45:51 2012 +0200
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta content="text/html; charset=UTF-8" http-equiv="content-type" />
+ <title>Entity View</title>
+ </head>
+ <body class="lift:content_id=main">
+ <div id="main" class="lift:surround?with=default;at=content">
+ <div class="row">
+ <div class="span12">
+ <span class="lift:panel"></span>
+ </div>
+ </div> <!-- /row -->
+ <div class="row section">
+ <div class="span12">
+ <h3><span class="lift:loc?locid=Contacts"></span></h3>
+ <span class="lift:contacts"></span>
+ </div>
+ </div> <!-- /row -->
+ </div>
+ </body>
+</html>
+
+