--- 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>