You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2013/12/05 22:13:10 UTC

[1/3] git commit: Extract out a service for formatting Dates into ISO-8601 format

Updated Branches:
  refs/heads/master 8f3d75395 -> bc1c43acc


Extract out a service for formatting Dates into ISO-8601 format


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/8cadab65
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/8cadab65
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/8cadab65

Branch: refs/heads/master
Commit: 8cadab6510609b1edaf8ae2e19f22c2df49a0b9e
Parents: 8f3d753
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Thu Dec 5 11:18:57 2013 -0800
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Thu Dec 5 11:18:57 2013 -0800

----------------------------------------------------------------------
 .../tapestry5/corelib/components/LocalDate.java | 12 ++----
 .../internal/services/DateUtilitiesImpl.java    | 43 ++++++++++++++++++++
 .../tapestry5/modules/TapestryModule.java       |  1 +
 .../tapestry5/services/DateUtilities.java       | 34 ++++++++++++++++
 4 files changed, 82 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8cadab65/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
index 5091176..4a66b46 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
@@ -21,12 +21,10 @@ import org.apache.tapestry5.annotations.Environmental;
 import org.apache.tapestry5.annotations.Parameter;
 import org.apache.tapestry5.annotations.SupportsInformalParameters;
 import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.services.DateUtilities;
 import org.apache.tapestry5.services.javascript.JavaScriptSupport;
 
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
 import java.util.Date;
-import java.util.TimeZone;
 
 /**
  * Used to present a date, formatted in the time zone of the client browser.
@@ -68,21 +66,19 @@ public class LocalDate
     @Environmental
     JavaScriptSupport javaScriptSupport;
 
-    private static TimeZone tz = TimeZone.getTimeZone("UTC");
+    @Inject
+    DateUtilities dateUtilities;
 
     boolean beginRender(MarkupWriter writer)
     {
         if (value != null)
         {
-            DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
-            df.setTimeZone(tz);
-
             writer.element(resources.getElementName("span"),
                     "data-localdate-format", format);
 
             resources.renderInformalParameters(writer);
 
-            writer.write(df.format(value));
+            writer.write(dateUtilities.formatISO8601(value));
 
             writer.end();
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8cadab65/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java
new file mode 100644
index 0000000..6f75d4d
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java
@@ -0,0 +1,43 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.internal.services;
+
+import org.apache.tapestry5.ioc.ScopeConstants;
+import org.apache.tapestry5.ioc.annotations.Scope;
+import org.apache.tapestry5.services.DateUtilities;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+@Scope(ScopeConstants.PERTHREAD)
+public class DateUtilitiesImpl implements DateUtilities
+{
+    private static final TimeZone tz = TimeZone.getTimeZone("UTC");
+
+    private DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
+
+    {
+        df.setTimeZone(tz);
+    }
+
+    public String formatISO8601(Date date)
+    {
+        assert date != null;
+
+        return df.format(date);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8cadab65/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
index b9ff2d8..aa79a57 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
@@ -370,6 +370,7 @@ public final class TapestryModule
         binder.bind(StringInterner.class, StringInternerImpl.class);
         binder.bind(ValueEncoderSource.class, ValueEncoderSourceImpl.class);
         binder.bind(PathConstructor.class, PathConstructorImpl.class);
+        binder.bind(DateUtilities.class, DateUtilitiesImpl.class);
     }
 
     // ========================================================================

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8cadab65/tapestry-core/src/main/java/org/apache/tapestry5/services/DateUtilities.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/DateUtilities.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/DateUtilities.java
new file mode 100644
index 0000000..bfb7634
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/DateUtilities.java
@@ -0,0 +1,34 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.services;
+
+import java.util.Date;
+
+/**
+ * Formatting utilities for dates; this is primarily used when communicating server-side dates to the clients in ISO-8601    format.
+ *
+ * @since 5.4
+ */
+public interface DateUtilities
+{
+    /**
+     * Formats the time instant in ISO-8601 format for the UTC time zone.
+     *
+     * @param date
+     *         to format, may not be null
+     * @return formatted date
+     */
+    String formatISO8601(Date date);
+}


[2/3] git commit: Add missing URL to link to Moment.js

Posted by hl...@apache.org.
Add missing URL to link to Moment.js


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/af6a0e02
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/af6a0e02
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/af6a0e02

Branch: refs/heads/master
Commit: af6a0e0289f5e3547fa23b6b1cc35bcffefc76f5
Parents: 8cadab6
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Thu Dec 5 11:24:03 2013 -0800
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Thu Dec 5 11:24:03 2013 -0800

----------------------------------------------------------------------
 .../java/org/apache/tapestry5/corelib/components/LocalDate.java  | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/af6a0e02/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
index 4a66b46..9ca0e27 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
@@ -47,8 +47,8 @@ import java.util.Date;
 public class LocalDate
 {
     /**
-     * The format to use, as defined by <a href="">Moment.js</a>. The factory default
-     * is "lll", which is a short form of the month, day, year, hour, minute and am/pm,
+     * The format to use, as defined by <a href="http://momentjs.com/docs/#/displaying/format/">Moment.js</a>.
+     * The factory default is "lll", which is a short form of the month, day, year, hour, minute and am/pm,
      * e.g. "Sep 4 1986 8:30 PM".
      */
     @Parameter(defaultPrefix = BindingConstants.LITERAL, allowNull = false, value = "message:private-default-localdate-format")


[3/3] git commit: TAP5-2253: TimeInterval component - display localized interval between two dates

Posted by hl...@apache.org.
TAP5-2253: TimeInterval component - display localized interval between two dates


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/bc1c43ac
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/bc1c43ac
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/bc1c43ac

Branch: refs/heads/master
Commit: bc1c43acc8f0ccdfb641790fd1092bc57493ed72
Parents: af6a0e0
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Thu Dec 5 13:12:50 2013 -0800
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Thu Dec 5 13:12:50 2013 -0800

----------------------------------------------------------------------
 .../modules/t5/core/time-interval.coffee        |  53 ++++++++++
 .../tapestry5/corelib/components/LocalDate.java |   1 +
 .../corelib/components/TimeInterval.java        | 100 +++++++++++++++++++
 .../internal/services/DateUtilitiesImpl.java    |   2 +-
 .../src/test/app1/TimeIntervalDemo.tml          |  26 +++++
 .../tapestry5/integration/app1/MiscTests.groovy |   9 ++
 .../app1/pages/TimeIntervalDemo.groovy          |  29 ++++++
 .../tapestry5/integration/app1/pages/Index.java |   3 +
 8 files changed, 222 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/time-interval.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/time-interval.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/time-interval.coffee
new file mode 100644
index 0000000..f386760
--- /dev/null
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/time-interval.coffee
@@ -0,0 +1,53 @@
+# Copyright 2013 The Apache Software Foundation
+#
+# 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.
+
+# ## t5/core/time-interval
+#
+# Used with the Interval component to express the interval between two timestamps,
+# or the dynamic difference between now and an end point in the past or future.
+define ["./dom", "./moment"],
+(dom, moment) ->
+
+  ATTR = "data-timeinterval"
+
+  toMoment = (s) -> if s then moment s else moment()
+
+  updateElement = (el) ->
+    start = toMoment el.attr "data-timeinterval-start"
+    end = toMoment el.attr "data-timeinterval-end"
+    plain = el.attr "data-timeinterval-plain"
+
+    el.update end.from start, plain
+    return
+
+  updateDynamics = ->
+    for el in dom.body.find "[#{ATTR}=dynamic]"
+      updateElement el
+    return
+
+  # Update any dynamic intervals (the ones without a specific start date) about once a second
+  setInterval updateDynamics, 1000
+
+  dom.scanner "[#{ATTR}=true]", (el) ->
+
+    updateElement el
+
+    if (el.attr "data-timeinterval-start") and (el.attr "data-timeinterval-end")
+      el.attr ATTR, null
+    else
+      el.attr ATTR, "dynamic"
+
+    return
+
+  return # no exports

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
index 9ca0e27..bf33f30 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
@@ -41,6 +41,7 @@ import java.util.Date;
  * zone.
  *
  * @tapestrydoc
+ * @see TimeInterval
  * @since 5.4
  */
 @SupportsInformalParameters

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/TimeInterval.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/TimeInterval.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/TimeInterval.java
new file mode 100644
index 0000000..789fce9
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/TimeInterval.java
@@ -0,0 +1,100 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.corelib.components;
+
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.annotations.Import;
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.SupportsInformalParameters;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.services.DateUtilities;
+
+import java.util.Date;
+
+/**
+ * Used to present an interval value using Moment.js's from() or fromNow() functions. The interval
+ * is determined in terms of a start and end date; either (but not both) may be omitted, in which
+ * case the client will dynamically update the element.  In that case, the value will live update, approximately every second.
+ * <p/>
+ * This component will render an empty element. The element will match the template element,
+ * or a "span" if the template did not provide an element. Informal parameters will be rendered
+ * into the element.
+ * <p/>
+ * When the end date is after the start date, the rendered text will be prefixed with "in".
+ * When the end date precedes the start date, the rendered text will be suffixed with "ago".
+ * The plain parameter is used to turn off the prefix or suffix.
+ *
+ * @tapestrydoc
+ * @see LocalDate
+ * @since 5.4
+ */
+@SupportsInformalParameters
+@Import(module = "t5/core/time-interval")
+public class TimeInterval
+{
+    /**
+     * The start date for the interval. If omitted, the start time is considered "now" and will automatically
+     * update in the browser.
+     */
+    @Parameter
+    Date start;
+
+    /**
+     * The end date for the interval. If omitted, the end time is considered "now" and will update automatically
+     * in the browser.
+     */
+    @Parameter()
+    Date end;
+
+    /**
+     * If true, then output is plain: no "in" prefix or "ago" suffix.
+     */
+    @Parameter
+    boolean plain;
+
+    @Inject
+    ComponentResources resources;
+
+    @Inject
+    DateUtilities dateUtilities;
+
+    private String toISO(Date date)
+    {
+        return date == null ? null : dateUtilities.formatISO8601(date);
+    }
+
+    boolean beginRender(MarkupWriter writer)
+    {
+        writer.element(resources.getElementName("span"),
+                // Trigger the client-side logic:
+                "data-timeinterval", "true",
+                "data-timeinterval-start", toISO(start),
+                "data-timeinterval-end", toISO(end));
+
+        if (plain)
+        {
+            writer.attributes("data-timeinterval-plain", true);
+        }
+
+        resources.renderInformalParameters(writer);
+
+        writer.end();
+
+        // Skip the body regardless.
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java
index 6f75d4d..8eaaff3 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java
@@ -28,7 +28,7 @@ public class DateUtilitiesImpl implements DateUtilities
 {
     private static final TimeZone tz = TimeZone.getTimeZone("UTC");
 
-    private DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
+    private DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S'Z'");
 
     {
         df.setTimeZone(tz);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/test/app1/TimeIntervalDemo.tml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/app1/TimeIntervalDemo.tml b/tapestry-core/src/test/app1/TimeIntervalDemo.tml
new file mode 100644
index 0000000..c937474
--- /dev/null
+++ b/tapestry-core/src/test/app1/TimeIntervalDemo.tml
@@ -0,0 +1,26 @@
+<html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
+
+    <h1>Interval Demo</h1>
+
+    <dl>
+        <dt>Current time</dt>
+        <dd t:type="localdate" value="now" format="HH:mm:ss"/>
+        <dt>Previous render</dt>
+        <dd>
+            <t:localdate value="previousRender" format="HH:mm:ss"/>
+            -
+            <t:timeinterval id="time-since-prev-render" end="previousRender"/>
+        </dd>
+        <dt>Jacob's Age</dt>
+        <dd id="jacob-age" t:type="timeinterval" start="jacobBirth" plain="true"></dd>
+        <dt>Jacob can Vote</dt>
+        <dd id="jacob-vote" t:type="timeinterval" end="jacobVote"/>
+    </dl>
+
+    <div class="btn-toolbar">
+        <t:actionlink t:id="english" class="btn btn-default">English</t:actionlink>
+        <t:actionlink t:id="french" class="btn btn-default">French</t:actionlink>
+    </div>
+
+</html>
+

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/MiscTests.groovy
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/MiscTests.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/MiscTests.groovy
index 2db2c52..5947362 100644
--- a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/MiscTests.groovy
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/MiscTests.groovy
@@ -63,4 +63,13 @@ class MiscTests extends App1TestCase {
         assertNotEquals defaultFormat, customFormat
     }
 
+    @Test
+    void timeinterval_component() {
+        openLinks "TimeInterval Demo", "English"
+
+        assert getText("time-since-prev-render").endsWith(" ago")
+        assert getText("jacob-age").contains("years")
+        assert getText("jacob-vote").startsWith("in ")
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/TimeIntervalDemo.groovy
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/TimeIntervalDemo.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/TimeIntervalDemo.groovy
new file mode 100644
index 0000000..4495db3
--- /dev/null
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/TimeIntervalDemo.groovy
@@ -0,0 +1,29 @@
+package org.apache.tapestry5.integration.app1.pages
+
+import org.apache.tapestry5.annotations.Persist
+import org.apache.tapestry5.annotations.Property
+
+
+class TimeIntervalDemo extends LocalDateDemo {
+
+    @Persist
+    @Property
+    private Date previousRender;
+
+    void setupRender() {
+        if (previousRender == null)
+            previousRender = new Date().clearTime()
+    }
+
+    void afterRender() {
+        previousRender = new Date()
+    }
+
+    Date getJacobBirth() {
+        return new Date(2010 - 1900, 1, 15) // Feb 15 2010
+    }
+
+    Date getJacobVote() {
+        return new Date(2010 + 18 - 1900, 1, 15) // Feb 15 2028
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
index 388c5c6..8b2e3fe 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
@@ -58,6 +58,9 @@ public class Index
 
     private static final List<Item> ITEMS = CollectionFactory
             .newList(
+
+                    new Item("TimeIntervalDemo", "TimeInterval Demo", "Interval component, based on Moment.js"),
+
                     new Item("LocalDateDemo", "LocalDate Demo", "LocalDate component, based on Moment.js"),
 
                     new Item("EmptyIfDemo", "Empty If Demo", "Ensure an empty If can still render."),


[3/3] git commit: TAP5-2253: TimeInterval component - display localized interval between two dates

Posted by hl...@apache.org.
TAP5-2253: TimeInterval component - display localized interval between two dates


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/bc1c43ac
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/bc1c43ac
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/bc1c43ac

Branch: refs/heads/master
Commit: bc1c43acc8f0ccdfb641790fd1092bc57493ed72
Parents: af6a0e0
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Thu Dec 5 13:12:50 2013 -0800
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Thu Dec 5 13:12:50 2013 -0800

----------------------------------------------------------------------
 .../modules/t5/core/time-interval.coffee        |  53 ++++++++++
 .../tapestry5/corelib/components/LocalDate.java |   1 +
 .../corelib/components/TimeInterval.java        | 100 +++++++++++++++++++
 .../internal/services/DateUtilitiesImpl.java    |   2 +-
 .../src/test/app1/TimeIntervalDemo.tml          |  26 +++++
 .../tapestry5/integration/app1/MiscTests.groovy |   9 ++
 .../app1/pages/TimeIntervalDemo.groovy          |  29 ++++++
 .../tapestry5/integration/app1/pages/Index.java |   3 +
 8 files changed, 222 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/time-interval.coffee
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/time-interval.coffee b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/time-interval.coffee
new file mode 100644
index 0000000..f386760
--- /dev/null
+++ b/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/time-interval.coffee
@@ -0,0 +1,53 @@
+# Copyright 2013 The Apache Software Foundation
+#
+# 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.
+
+# ## t5/core/time-interval
+#
+# Used with the Interval component to express the interval between two timestamps,
+# or the dynamic difference between now and an end point in the past or future.
+define ["./dom", "./moment"],
+(dom, moment) ->
+
+  ATTR = "data-timeinterval"
+
+  toMoment = (s) -> if s then moment s else moment()
+
+  updateElement = (el) ->
+    start = toMoment el.attr "data-timeinterval-start"
+    end = toMoment el.attr "data-timeinterval-end"
+    plain = el.attr "data-timeinterval-plain"
+
+    el.update end.from start, plain
+    return
+
+  updateDynamics = ->
+    for el in dom.body.find "[#{ATTR}=dynamic]"
+      updateElement el
+    return
+
+  # Update any dynamic intervals (the ones without a specific start date) about once a second
+  setInterval updateDynamics, 1000
+
+  dom.scanner "[#{ATTR}=true]", (el) ->
+
+    updateElement el
+
+    if (el.attr "data-timeinterval-start") and (el.attr "data-timeinterval-end")
+      el.attr ATTR, null
+    else
+      el.attr ATTR, "dynamic"
+
+    return
+
+  return # no exports

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
index 9ca0e27..bf33f30 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
@@ -41,6 +41,7 @@ import java.util.Date;
  * zone.
  *
  * @tapestrydoc
+ * @see TimeInterval
  * @since 5.4
  */
 @SupportsInformalParameters

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/TimeInterval.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/TimeInterval.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/TimeInterval.java
new file mode 100644
index 0000000..789fce9
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/TimeInterval.java
@@ -0,0 +1,100 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.corelib.components;
+
+import org.apache.tapestry5.ComponentResources;
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.annotations.Import;
+import org.apache.tapestry5.annotations.Parameter;
+import org.apache.tapestry5.annotations.SupportsInformalParameters;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.services.DateUtilities;
+
+import java.util.Date;
+
+/**
+ * Used to present an interval value using Moment.js's from() or fromNow() functions. The interval
+ * is determined in terms of a start and end date; either (but not both) may be omitted, in which
+ * case the client will dynamically update the element.  In that case, the value will live update, approximately every second.
+ * <p/>
+ * This component will render an empty element. The element will match the template element,
+ * or a "span" if the template did not provide an element. Informal parameters will be rendered
+ * into the element.
+ * <p/>
+ * When the end date is after the start date, the rendered text will be prefixed with "in".
+ * When the end date precedes the start date, the rendered text will be suffixed with "ago".
+ * The plain parameter is used to turn off the prefix or suffix.
+ *
+ * @tapestrydoc
+ * @see LocalDate
+ * @since 5.4
+ */
+@SupportsInformalParameters
+@Import(module = "t5/core/time-interval")
+public class TimeInterval
+{
+    /**
+     * The start date for the interval. If omitted, the start time is considered "now" and will automatically
+     * update in the browser.
+     */
+    @Parameter
+    Date start;
+
+    /**
+     * The end date for the interval. If omitted, the end time is considered "now" and will update automatically
+     * in the browser.
+     */
+    @Parameter()
+    Date end;
+
+    /**
+     * If true, then output is plain: no "in" prefix or "ago" suffix.
+     */
+    @Parameter
+    boolean plain;
+
+    @Inject
+    ComponentResources resources;
+
+    @Inject
+    DateUtilities dateUtilities;
+
+    private String toISO(Date date)
+    {
+        return date == null ? null : dateUtilities.formatISO8601(date);
+    }
+
+    boolean beginRender(MarkupWriter writer)
+    {
+        writer.element(resources.getElementName("span"),
+                // Trigger the client-side logic:
+                "data-timeinterval", "true",
+                "data-timeinterval-start", toISO(start),
+                "data-timeinterval-end", toISO(end));
+
+        if (plain)
+        {
+            writer.attributes("data-timeinterval-plain", true);
+        }
+
+        resources.renderInformalParameters(writer);
+
+        writer.end();
+
+        // Skip the body regardless.
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java
index 6f75d4d..8eaaff3 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DateUtilitiesImpl.java
@@ -28,7 +28,7 @@ public class DateUtilitiesImpl implements DateUtilities
 {
     private static final TimeZone tz = TimeZone.getTimeZone("UTC");
 
-    private DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
+    private DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S'Z'");
 
     {
         df.setTimeZone(tz);

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/test/app1/TimeIntervalDemo.tml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/app1/TimeIntervalDemo.tml b/tapestry-core/src/test/app1/TimeIntervalDemo.tml
new file mode 100644
index 0000000..c937474
--- /dev/null
+++ b/tapestry-core/src/test/app1/TimeIntervalDemo.tml
@@ -0,0 +1,26 @@
+<html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd">
+
+    <h1>Interval Demo</h1>
+
+    <dl>
+        <dt>Current time</dt>
+        <dd t:type="localdate" value="now" format="HH:mm:ss"/>
+        <dt>Previous render</dt>
+        <dd>
+            <t:localdate value="previousRender" format="HH:mm:ss"/>
+            -
+            <t:timeinterval id="time-since-prev-render" end="previousRender"/>
+        </dd>
+        <dt>Jacob's Age</dt>
+        <dd id="jacob-age" t:type="timeinterval" start="jacobBirth" plain="true"></dd>
+        <dt>Jacob can Vote</dt>
+        <dd id="jacob-vote" t:type="timeinterval" end="jacobVote"/>
+    </dl>
+
+    <div class="btn-toolbar">
+        <t:actionlink t:id="english" class="btn btn-default">English</t:actionlink>
+        <t:actionlink t:id="french" class="btn btn-default">French</t:actionlink>
+    </div>
+
+</html>
+

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/MiscTests.groovy
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/MiscTests.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/MiscTests.groovy
index 2db2c52..5947362 100644
--- a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/MiscTests.groovy
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/MiscTests.groovy
@@ -63,4 +63,13 @@ class MiscTests extends App1TestCase {
         assertNotEquals defaultFormat, customFormat
     }
 
+    @Test
+    void timeinterval_component() {
+        openLinks "TimeInterval Demo", "English"
+
+        assert getText("time-since-prev-render").endsWith(" ago")
+        assert getText("jacob-age").contains("years")
+        assert getText("jacob-vote").startsWith("in ")
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/TimeIntervalDemo.groovy
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/TimeIntervalDemo.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/TimeIntervalDemo.groovy
new file mode 100644
index 0000000..4495db3
--- /dev/null
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/pages/TimeIntervalDemo.groovy
@@ -0,0 +1,29 @@
+package org.apache.tapestry5.integration.app1.pages
+
+import org.apache.tapestry5.annotations.Persist
+import org.apache.tapestry5.annotations.Property
+
+
+class TimeIntervalDemo extends LocalDateDemo {
+
+    @Persist
+    @Property
+    private Date previousRender;
+
+    void setupRender() {
+        if (previousRender == null)
+            previousRender = new Date().clearTime()
+    }
+
+    void afterRender() {
+        previousRender = new Date()
+    }
+
+    Date getJacobBirth() {
+        return new Date(2010 - 1900, 1, 15) // Feb 15 2010
+    }
+
+    Date getJacobVote() {
+        return new Date(2010 + 18 - 1900, 1, 15) // Feb 15 2028
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/bc1c43ac/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
index 388c5c6..8b2e3fe 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
@@ -58,6 +58,9 @@ public class Index
 
     private static final List<Item> ITEMS = CollectionFactory
             .newList(
+
+                    new Item("TimeIntervalDemo", "TimeInterval Demo", "Interval component, based on Moment.js"),
+
                     new Item("LocalDateDemo", "LocalDate Demo", "LocalDate component, based on Moment.js"),
 
                     new Item("EmptyIfDemo", "Empty If Demo", "Ensure an empty If can still render."),


[2/3] git commit: Add missing URL to link to Moment.js

Posted by hl...@apache.org.
Add missing URL to link to Moment.js


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/af6a0e02
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/af6a0e02
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/af6a0e02

Branch: refs/heads/master
Commit: af6a0e0289f5e3547fa23b6b1cc35bcffefc76f5
Parents: 8cadab6
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Thu Dec 5 11:24:03 2013 -0800
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Thu Dec 5 11:24:03 2013 -0800

----------------------------------------------------------------------
 .../java/org/apache/tapestry5/corelib/components/LocalDate.java  | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/af6a0e02/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
index 4a66b46..9ca0e27 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/components/LocalDate.java
@@ -47,8 +47,8 @@ import java.util.Date;
 public class LocalDate
 {
     /**
-     * The format to use, as defined by <a href="">Moment.js</a>. The factory default
-     * is "lll", which is a short form of the month, day, year, hour, minute and am/pm,
+     * The format to use, as defined by <a href="http://momentjs.com/docs/#/displaying/format/">Moment.js</a>.
+     * The factory default is "lll", which is a short form of the month, day, year, hour, minute and am/pm,
      * e.g. "Sep 4 1986 8:30 PM".
      */
     @Parameter(defaultPrefix = BindingConstants.LITERAL, allowNull = false, value = "message:private-default-localdate-format")