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:12 UTC
[3/3] git commit: TAP5-2253: TimeInterval component - display
localized interval between two dates
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."),