977f2e215a04b181 Task report
authorTomas Zeman <tzeman@volny.cz>
Tue, 05 Jun 2012 15:40:44 +0200
changeset 103 6a2a19785cd8
parent 102 c92afc825464
child 104 ef29ecada49d
977f2e215a04b181 Task report
src/main/scala/fis/base/ui/SecNav.scala
src/main/scala/fis/pm/model/PmSchema.scala
src/main/scala/fis/pm/model/Task.scala
src/main/scala/fis/pm/ui/Delayed.scala
src/main/scala/fis/pm/ui/TaskSnippet.scala
src/main/scala/fis/pm/ui/TaskTable.scala
src/main/webapp/css/base.css
src/main/webapp/task/list.html
src/main/webapp/templates-hidden/_resources.html
src/main/webapp/templates-hidden/_resources_cs.html
--- a/src/main/scala/fis/base/ui/SecNav.scala	Tue Jun 05 15:40:44 2012 +0200
+++ b/src/main/scala/fis/base/ui/SecNav.scala	Tue Jun 05 15:40:44 2012 +0200
@@ -91,6 +91,10 @@
       case _ => NodeSeq.Empty
     }
   }
+
+  def apply[T](m: Menuable): NodeSeq = (for {
+    l <- SiteMap.findAndTestLoc(m.name)
+  } yield <a href={l.calcDefaultHref}>{m.linkText.text()}</a>) toSeq
 }
 
 // vim: set ts=2 sw=2 et:
--- a/src/main/scala/fis/pm/model/PmSchema.scala	Tue Jun 05 15:40:44 2012 +0200
+++ b/src/main/scala/fis/pm/model/PmSchema.scala	Tue Jun 05 15:40:44 2012 +0200
@@ -59,6 +59,9 @@
 
   Task.users.default.set(activeUsersF)
 
+  def tasks: Iterable[Task] = from(taskT)(t =>
+    select(t) orderBy(t.createdAt asc))
+
   /* comment */
   val commentT = tableWithSeq[Comment]
 
--- a/src/main/scala/fis/pm/model/Task.scala	Tue Jun 05 15:40:44 2012 +0200
+++ b/src/main/scala/fis/pm/model/Task.scala	Tue Jun 05 15:40:44 2012 +0200
@@ -22,10 +22,13 @@
 import net.liftweb.common._
 import net.liftweb.record.{LifecycleCallbacks, MetaRecord, Record}
 import net.liftweb.record.field._
+import net.liftweb.squerylrecord.RecordTypeMode._
 import net.liftweb.util._
 import net.tz.lift.model._
 import net.tz.lift.model.{FieldLabel => FL}
 import org.squeryl.annotations.Column
+import org.squeryl.dsl.QueryDsl
+import org.squeryl.dsl.ast.LogicalBoolean
 import scala.xml.Text
 
 class Task private() extends Record[Task] with Entity[Task] {
@@ -50,6 +53,9 @@
 
   def state: TaskState =
     stateFld.item.map { TaskState(_) } openOr EmptyTaskState
+
+  def delayed = !state.complete &&
+    deadline.date.plusDays(1).isBefore(null) // null means now
 }
 
 object Task extends Task with MetaRecord[Task] with SimpleInjector {
@@ -71,6 +77,9 @@
 object TaskState {
   def apply(i: CodeListItem): TaskState =
     TaskStateItem(i.id, i.i1.get, i.i1.get == 100)
+
+  def unfinishedClause[T](i: CodeListItem)(implicit dsl: QueryDsl):
+    LogicalBoolean = (i.i1 <> 100)
 }
 
 private[model] class TaskNumber(t: Task) extends IntField[Task](t) with
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/fis/pm/ui/Delayed.scala	Tue Jun 05 15:40:44 2012 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012 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.pm.ui
+
+import fis.base.model._
+import fis.pm.model._
+import net.liftweb.common._
+import net.liftweb.util._
+import net.liftweb.util.Helpers._
+import net.tz.lift.model._
+
+object Delayed {
+  private def decorate(delayed: Boolean, f: ReadableField) =
+    delayed.box(new ReadOnlyField(f.name, f.displayName,
+    addAttributes(f.asHtml, "class" -> "delayed"), Empty)) openOr f
+
+  def apply(t: Task)(f: ReadableField) = decorate(t.delayed, f)
+}
+
+
+// vim: set ts=2 sw=2 et:
--- a/src/main/scala/fis/pm/ui/TaskSnippet.scala	Tue Jun 05 15:40:44 2012 +0200
+++ b/src/main/scala/fis/pm/ui/TaskSnippet.scala	Tue Jun 05 15:40:44 2012 +0200
@@ -17,6 +17,7 @@
 
 import fis.aaa.ui.IfLoggedIn
 import fis.base.ui._
+import fis.cl.model._
 import fis.fs.model._
 import fis.fs.ui._
 import fis.pm.model._
@@ -24,6 +25,7 @@
 import net.liftweb.http._
 import net.liftweb.sitemap._
 import net.liftweb.sitemap.Loc._
+import net.liftweb.squerylrecord.RecordTypeMode._
 import net.liftweb.util._
 import net.liftweb.util.Helpers._
 import net.tz.lift.model._
@@ -35,7 +37,21 @@
 
   private val listM = Menu("task.list", l10n("Tasks")) / prefix >>
     Title(_ => i18n("Tasks")) >>
-    locTpl("entity/list") >> Snippet("list", ClearNodes) >> Hidden
+    locTpl("task/list") >> Snippet("list", list)
+
+  private val listUnfinishedM = Menu("task.list-unfinished",
+    l10n("tasks.unfinished")) / prefix >>
+    Title(_ => i18n("Tasks")) >>
+    new TaskReport(() => from(PmSchema.taskT, CodeListSchema.cli)((t, i) =>
+      where(t.stateFld === i.id and TaskState.unfinishedClause(i))
+      select(t) orderBy(t.deadline asc))) >>
+    locTpl("task/list") >> Snippet("list", list) >> Hidden
+
+  private val listAllM = Menu("task.list-all",
+    l10n("tasks.all")) / prefix / "all" >>
+    Title(_ => i18n("All Tasks")) >>
+    new TaskReport(() => PmSchema.tasks) >>
+    locTpl("task/list") >> Snippet("list", list) >> Hidden
 
   private val viewPre = Menu.param[Task]("task.view", l10n("Task"), parse,
     encode) / prefix / * >> Title(t => i18n("Task %s", t.linkName)) >>
@@ -71,12 +87,28 @@
   private lazy val deleteLoc = deleteM.toLoc
   private lazy val postCommentLoc = postCommentM.toLoc
 
-  val menu = listM submenus(viewM, editM, deleteM, postCommentM,
-    attachments.menu)
+  val menu = listM submenus(listUnfinishedM, listAllM, viewM, editM, deleteM,
+    postCommentM, attachments.menu)
 
   private def cur = viewLoc.currentValue or editLoc.currentValue or
     deleteLoc.currentValue or postCommentLoc.currentValue
 
+  private def list: CssTr = {
+    val curM = Box(for {
+      m <- List(listUnfinishedM, listAllM)
+      cur <- S.location
+      loc <- SiteMap.findAndTestLoc(m.name) if cur.calcDefaultHref == loc.calcDefaultHref
+    } yield m) openOr listUnfinishedM
+
+    "li" #> (List(listUnfinishedM, listAllM) map { m => 
+      val nav = (new SecNavMenu(m)).toHtml
+      (m == curM).box(addAttributes(nav, "class" -> "active")) openOr nav }) &
+    ".content *" #> curM.params.flatMap {
+      case v: TaskReport => _TaskTable(v.tasks)
+      case _ => Nil
+    }
+  }
+
   private def panel: CssTr = "*" #> cur.map { t => ViewPanel(fields(t)) }
 
   private def comments: CssTr = "*" #> cur.map { t =>
@@ -96,6 +128,17 @@
 
   EntityLink.register[Task](TaskLink(_))
 
+  private object _TaskTable extends TaskTable {
+    override def fields(t: Task) = (Seq(identField(t)) ++ EntityLink(t) ++
+      Seq(t.project, t.stateFld, t.deadline, t.responsible, t.note)
+      ) map Delayed(t)
+  }
+
+  private class TaskReport(f: () => Iterable[Task]) extends LocInfo[Iterable[Task]] {
+    def apply() = Full(f)
+    def tasks = f()
+  }
+
   private object form extends TaskForm {
 
     override def localSetup() {
--- a/src/main/scala/fis/pm/ui/TaskTable.scala	Tue Jun 05 15:40:44 2012 +0200
+++ b/src/main/scala/fis/pm/ui/TaskTable.scala	Tue Jun 05 15:40:44 2012 +0200
@@ -19,13 +19,19 @@
 import fis.base.ui._
 import fis.pm.model._
 import net.liftweb.common._
+import net.liftweb.util._
+import net.liftweb.util.Helpers._
+import net.tz.lift.model._
 import net.tz.lift.snippet._
 
 trait TaskTable extends FieldTable[Task] {
   protected def identField(t: Task) = new ReadOnlyField(t.ident.name, t.ident.displayName,
     a(TaskSnippet.url.view(t))(t.ident.asHtml), Empty)
-  def fields(t: Task) = Seq(identField(t)) ++ EntityLink(t) ++ Seq(t.deadline,
-    t.responsible, t.note)
+
+  def fields(t: Task) =
+    (Seq(identField(t)) ++ EntityLink(t) ++ Seq(t.stateFld, t.deadline,
+    t.responsible, t.note)) map Delayed(t)
+
   def apply(l: Iterable[Task]) = build(Task, l)
 }
 
--- a/src/main/webapp/css/base.css	Tue Jun 05 15:40:44 2012 +0200
+++ b/src/main/webapp/css/base.css	Tue Jun 05 15:40:44 2012 +0200
@@ -87,3 +87,8 @@
 input.latitude, input.longitude {
   width: 60px;
 }
+
+/* task */
+.delayed {
+  color: #b94a48;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/webapp/task/list.html	Tue Jun 05 15:40:44 2012 +0200
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta content="text/html; charset=UTF-8" http-equiv="content-type" />
+    <title>Entity List</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:list">
+            <ul class="nav nav-tabs">
+              <li></li>
+            </ul>
+            <div class="content"></div>
+          </span>
+        </div>
+      </div> <!-- /row -->
+    </div>
+  </body>
+</html>
+
+
--- a/src/main/webapp/templates-hidden/_resources.html	Tue Jun 05 15:40:44 2012 +0200
+++ b/src/main/webapp/templates-hidden/_resources.html	Tue Jun 05 15:40:44 2012 +0200
@@ -243,6 +243,7 @@
       Really delete this task?
       Task %s deleted.
       Task %s saved.
+      All Tasks
   -->
   <!-- task fields -->
   <res name="task.name" lang="en" default="true">Name</res>
@@ -255,6 +256,8 @@
   <res name="task.stateFld" lang="en" default="true">State [%%]</res>
   <res name="task.comments" lang="en" default="true">Comments</res>
   <res name="task.attachments" lang="en" default="true">Attachments</res>
+  <res name="tasks.unfinished" lang="en" default="true">Unfinished</res>
+  <res name="tasks.all" lang="en" default="true">All</res>
   <!-- task types:
     Task type 1
     Task type 2
--- a/src/main/webapp/templates-hidden/_resources_cs.html	Tue Jun 05 15:40:44 2012 +0200
+++ b/src/main/webapp/templates-hidden/_resources_cs.html	Tue Jun 05 15:40:44 2012 +0200
@@ -230,6 +230,7 @@
   <res name="Really delete this task?" lang="cs">Skutečně smazat úkol?</res>
   <res name="Task %s deleted." lang="cs">Úkol %s smazán.</res>
   <res name="Task %s saved." lang="cs">Úkol %s uložen.</res>
+  <res name="All Tasks" lang="cs">Všechny úkoly</res>
   <!-- task fields -->
   <res name="task.name" lang="cs">Název</res>
   <res name="task.note" lang="cs">Popis</res>
@@ -241,6 +242,8 @@
   <res name="task.stateFld" lang="cs">Stav [%%]</res>
   <res name="task.comments" lang="cs">Komentáře</res>
   <res name="task.attachments" lang="cs">Přílohy</res>
+  <res name="tasks.unfinished" lang="cs">Nedokončené</res>
+  <res name="tasks.all" lang="cs">Všechny</res>
   <!-- task types: -->
   <res name="Task type 1" lang="cs">Typ 1</res>
   <res name="Task type 2" lang="cs">Typ 2</res>