ALF-11687 Update the site Calendar listing to optionally expand out repeating events for the period, and add tests for this

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@32515 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Nick Burch
2011-12-05 05:04:25 +00:00
parent 9f9a44dd56
commit d33252bf60
5 changed files with 166 additions and 25 deletions

View File

@@ -5,8 +5,9 @@
<#elseif events?exists && events?size &gt; 0> <#elseif events?exists && events?size &gt; 0>
<#assign prev = ""> <#assign prev = "">
<#list events as item> <#list events as item>
<#-- Note - use item not event start for repeating events expansion -->
<#assign date = item.start?string("M/d/yyyy")>
<#assign event = item.event> <#assign event = item.event>
<#assign date = event.start?string("M/d/yyyy")>
<#if date != prev> <#if date != prev>
<#assign counter = 0> <#assign counter = 0>
<#if item_index &gt; 0>],</#if> <#if item_index &gt; 0>],</#if>
@@ -14,17 +15,17 @@
</#if> </#if>
<#if counter &gt; 0>,</#if> <#if counter &gt; 0>,</#if>
{ {
"name": "${event.title}", "name": "${item.title}",
"uri": "calendar/event/${siteId}/${event.systemName}", "uri": "calendar/event/${siteId}/${event.systemName}",
"startAt": { "startAt": {
"iso8601": "${xmldate(event.start)}", "iso8601": "${xmldate(item.start)}",
"legacyDate": "${event.start?string("M/d/yyyy")}", "legacyDate": "${item.start?string("M/d/yyyy")}",
"legacyTime": "${event.start?string("HH:mm")}" "legacyTime": "${item.start?string("HH:mm")}"
}, },
"endAt": { "endAt": {
"iso8601": "${xmldate(event.end)}", "iso8601": "${xmldate(item.end)}",
"legacyDate": "${event.end?string("M/d/yyyy")}", "legacyDate": "${item.end?string("M/d/yyyy")}",
"legacyTime": "${event.end?string("HH:mm")}" "legacyTime": "${item.end?string("HH:mm")}"
}, },
"tags": [<#list item.tags as tag>"${tag}"<#if tag_has_next>,</#if></#list>], "tags": [<#list item.tags as tag>"${tag}"<#if tag_has_next>,</#if></#list>],

View File

@@ -38,7 +38,8 @@ import org.alfresco.service.cmr.calendar.CalendarRecurrenceHelper;
*/ */
public abstract class AbstractCalendarListingWebScript extends AbstractCalendarWebScript public abstract class AbstractCalendarListingWebScript extends AbstractCalendarWebScript
{ {
protected static final String RESULT_NAME = "name"; protected static final String RESULT_EVENT = "event";
protected static final String RESULT_NAME = "name";
protected static final String RESULT_TITLE = "title"; protected static final String RESULT_TITLE = "title";
protected static final String RESULT_START = "start"; protected static final String RESULT_START = "start";
protected static final String RESULT_END = "end"; protected static final String RESULT_END = "end";

View File

@@ -20,6 +20,7 @@ package org.alfresco.repo.web.scripts.calendar;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -40,31 +41,55 @@ import org.springframework.extensions.webscripts.WebScriptRequest;
/** /**
* This class is the controller for the slingshot calendar eventList.get webscript. * This class is the controller for the slingshot calendar eventList.get webscript.
* *
* TODO Improve what we give to the FTL
* TODO Switch to using {@link AbstractCalendarListingWebScript}
*
* @author Nick Burch * @author Nick Burch
* @since 4.0 * @since 4.0
*/ */
public class CalendarEntriesListGet extends AbstractCalendarWebScript public class CalendarEntriesListGet extends AbstractCalendarListingWebScript
{ {
@Override @Override
protected Map<String, Object> executeImpl(SiteInfo site, String eventName, protected Map<String, Object> executeImpl(SiteInfo site, String eventName,
WebScriptRequest req, JSONObject json, Status status, Cache cache) WebScriptRequest req, JSONObject json, Status status, Cache cache)
{ {
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); // Evil... // Evil format needed for compatibility with old API...
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
// Decide on date ranges and repeating rules
Date fromDate = parseDate(req.getParameter("from"));
Date toDate = parseDate(req.getParameter("to"));
boolean resortNeeded = false;
boolean repeatingFirstOnly = true;
String repeatingEvents = req.getParameter("repeating");
if (repeatingEvents != null)
{
if ("first".equals(repeatingEvents))
{
repeatingFirstOnly = true;
}
else if ("all".equals(repeatingEvents))
{
repeatingFirstOnly = false;
resortNeeded = true;
}
}
// Get the entries for the list // Get the entries for the list
PagingRequest paging = buildPagingRequest(req); PagingRequest paging = buildPagingRequest(req);
PagingResults<CalendarEntry> entries = PagingResults<CalendarEntry> entries = calendarService.listCalendarEntries(
calendarService.listCalendarEntries(site.getShortName(), paging); new String[] {site.getShortName()}, fromDate, toDate, paging);
// For each one in our page, grab details of any ignored instances // For each one in our page, grab details of any ignored instances
List<Map<String,Object>> results = new ArrayList<Map<String,Object>>(); List<Map<String,Object>> results = new ArrayList<Map<String,Object>>();
for (CalendarEntry entry : entries.getPage()) for (CalendarEntry entry : entries.getPage())
{ {
Map<String, Object> result = new HashMap<String, Object>(); Map<String, Object> result = new HashMap<String, Object>();
result.put("event", entry); result.put(RESULT_EVENT, entry);
result.put(RESULT_NAME, entry.getSystemName());
result.put(RESULT_TITLE, entry.getTitle());
result.put(RESULT_START, entry.getStart());
result.put(RESULT_END, entry.getEnd());
result.put("fromDate", entry.getStart()); result.put("fromDate", entry.getStart());
result.put("tags", entry.getTags()); result.put("tags", entry.getTags());
@@ -86,9 +111,23 @@ public class CalendarEntriesListGet extends AbstractCalendarWebScript
result.put("ignoreEvents", ignoreEvents); result.put("ignoreEvents", ignoreEvents);
result.put("ignoreEventDates", ignoreEventDates); result.put("ignoreEventDates", ignoreEventDates);
// For repeating events, push forward if needed
boolean orderChanged = handleRecurring(entry, result, results, fromDate, toDate, repeatingFirstOnly);
if (orderChanged)
{
resortNeeded = true;
}
// All done with this one
results.add(result); results.add(result);
} }
// If they asked for repeating events to be expanded, then do so
if (resortNeeded)
{
Collections.sort(results, getEventDetailsSorter());
}
// All done // All done
Map<String, Object> model = new HashMap<String, Object>(); Map<String, Object> model = new HashMap<String, Object>();
model.put("events", results); model.put("events", results);

View File

@@ -18,7 +18,10 @@
*/ */
package org.alfresco.repo.web.scripts.calendar; package org.alfresco.repo.web.scripts.calendar;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
import org.alfresco.repo.calendar.CalendarServiceImpl; import org.alfresco.repo.calendar.CalendarServiceImpl;
@@ -195,7 +198,7 @@ public class CalendarRestApiTest extends BaseWebScriptTest
} }
if (from != null) if (from != null)
{ {
if (url.indexOf('/') > 0) if (url.indexOf('?') > 0)
{ {
url += "&"; url += "&";
} }
@@ -265,10 +268,8 @@ public class CalendarRestApiTest extends BaseWebScriptTest
json.put("page", "calendar"); json.put("page", "calendar");
// Copy in the date properties // Copy in the date properties
Iterator<String> datesIT = datesJSON.keys(); for (String key : getKeys(datesJSON, false))
while(datesIT.hasNext())
{ {
String key = datesIT.next();
json.put(key, datesJSON.get(key)); json.put(key, datesJSON.get(key));
} }
@@ -368,6 +369,25 @@ public class CalendarRestApiTest extends BaseWebScriptTest
return response.getContentAsString(); return response.getContentAsString();
} }
/**
* Returns the Keys of a JSON Object, optionally sorted
*/
private String[] getKeys(JSONObject json, boolean sorted)
{
@SuppressWarnings("unchecked")
Iterator<String> ki = json.keys();
List<String> keys = new ArrayList<String>(json.length());
while (ki.hasNext())
{
keys.add(ki.next());
}
if(sorted) { Collections.sort(keys); }
return keys.toArray(new String[keys.size()]);
}
// Tests // Tests
@@ -985,9 +1005,10 @@ public class CalendarRestApiTest extends BaseWebScriptTest
} }
/** /**
* Repeating events support * Repeating events support, across both the site
* specific and user wide listings.
*/ */
public void testRepeatingEventsInUserListing() throws Exception public void testRepeatingEventsInListings() throws Exception
{ {
JSONObject result; JSONObject result;
JSONArray events; JSONArray events;
@@ -1007,10 +1028,13 @@ public class CalendarRestApiTest extends BaseWebScriptTest
String entryName2 = getNameFromEntry(entry2); String entryName2 = getNameFromEntry(entry2);
// Have it repeat on wednesdays and fridays every two weeks // Have it repeat on wednesdays and fridays every two weeks
updateEntry(entryName2, EVENT_TITLE_TWO, "Somewhere", "Thing 2", true, Status.STATUS_OK); updateEntry(entryName2, EVENT_TITLE_TWO, "Somewhere", "Thing 2", true, Status.STATUS_OK);
// Get all the entries, without repeats expanded // Get all the entries, without repeats expanded
result = getEntries("admin", "2011-06-27"); // ---------------------------------------------
// For the user
result = getEntries("admin", "2011-06-27&repeating=first");
events = result.getJSONArray("events"); events = result.getJSONArray("events");
assertEquals(2, events.length()); assertEquals(2, events.length());
assertEquals(entryName2, events.getJSONObject(0).getString("name")); assertEquals(entryName2, events.getJSONObject(0).getString("name"));
@@ -1019,7 +1043,25 @@ public class CalendarRestApiTest extends BaseWebScriptTest
assertEquals(EVENT_TITLE_ONE, events.getJSONObject(1).getString("title")); assertEquals(EVENT_TITLE_ONE, events.getJSONObject(1).getString("title"));
// For the site (JSON format is different)
result = getEntries(null, "2011-06-27&repeating=first");
assertEquals(2, result.length());
assertEquals("6/28/2011", getKeys(result, true)[0]);
assertEquals("6/29/2011", getKeys(result, true)[1]);
events = result.getJSONArray("6/28/2011");
assertEquals(1, events.length());
assertEquals(EVENT_TITLE_TWO + " (Repeating)", events.getJSONObject(0).getString("name"));
events = result.getJSONArray("6/29/2011");
assertEquals(1, events.length());
assertEquals(EVENT_TITLE_ONE, events.getJSONObject(0).getString("name"));
// Get all the entries, with repeats expanded // Get all the entries, with repeats expanded
// ------------------------------------------
// For the user
result = getEntries("admin", "2011/06/27"); result = getEntries("admin", "2011/06/27");
events = result.getJSONArray("events"); events = result.getJSONArray("events");
assertEquals(7, Math.min(events.length(),7)); // At least assertEquals(7, Math.min(events.length(),7)); // At least
@@ -1057,6 +1099,42 @@ public class CalendarRestApiTest extends BaseWebScriptTest
assertEquals("2011-07-27T", events.getJSONObject(6).getJSONObject("startAt").getString("iso8601").substring(0,11)); assertEquals("2011-07-27T", events.getJSONObject(6).getJSONObject("startAt").getString("iso8601").substring(0,11));
// 3rd repeat Friday // 3rd repeat Friday
assertEquals("2011-07-29T", events.getJSONObject(7).getJSONObject("startAt").getString("iso8601").substring(0,11)); assertEquals("2011-07-29T", events.getJSONObject(7).getJSONObject("startAt").getString("iso8601").substring(0,11));
// For the site
result = getEntries(null, "2011-06-28&repeating=all");
assertEquals(7, Math.min(result.length(),7)); // At least
// Repeating original
assertEquals("6/28/2011", getKeys(result, true)[0]);
assertEquals(1, result.getJSONArray("6/28/2011").length());
assertEquals(EVENT_TITLE_TWO, result.getJSONArray("6/28/2011").getJSONObject(0).get("name"));
// 1st repeat Wednesday, then Non-repeating original
assertEquals("6/29/2011", getKeys(result, true)[1]);
assertEquals(2, result.getJSONArray("6/29/2011").length());
assertEquals(EVENT_TITLE_TWO, result.getJSONArray("6/29/2011").getJSONObject(0).get("name"));
assertEquals(EVENT_TITLE_ONE, result.getJSONArray("6/29/2011").getJSONObject(1).get("name"));
// 1st repeat Friday
assertEquals("7/1/2011", getKeys(result, true)[2]);
assertEquals(1, result.getJSONArray("7/1/2011").length());
assertEquals(EVENT_TITLE_TWO, result.getJSONArray("7/1/2011").getJSONObject(0).get("name"));
// 2nd repeat Wednesday
assertEquals("7/13/2011", getKeys(result, true)[3]);
assertEquals(1, result.getJSONArray("7/13/2011").length());
assertEquals(EVENT_TITLE_TWO, result.getJSONArray("7/13/2011").getJSONObject(0).get("name"));
// 2nd repeat Friday
assertEquals("7/15/2011", getKeys(result, true)[4]);
assertEquals(1, result.getJSONArray("7/15/2011").length());
assertEquals(EVENT_TITLE_TWO, result.getJSONArray("7/15/2011").getJSONObject(0).get("name"));
// 3rd repeat Wednesday
assertEquals("7/27/2011", getKeys(result, true)[5]);
assertEquals(1, result.getJSONArray("7/27/2011").length());
assertEquals(EVENT_TITLE_TWO, result.getJSONArray("7/27/2011").getJSONObject(0).get("name"));
// 3rd repeat Friday
assertEquals("7/29/2011", getKeys(result, true)[6]);
assertEquals(1, result.getJSONArray("7/29/2011").length());
assertEquals(EVENT_TITLE_TWO, result.getJSONArray("7/29/2011").getJSONObject(0).get("name"));
// Ask for events from a date in the future // Ask for events from a date in the future
@@ -1080,5 +1158,26 @@ public class CalendarRestApiTest extends BaseWebScriptTest
assertEquals("2011-09-07T", events.getJSONObject(2).getJSONObject("startAt").getString("iso8601").substring(0,11)); assertEquals("2011-09-07T", events.getJSONObject(2).getJSONObject("startAt").getString("iso8601").substring(0,11));
// Friday, final repeating instance date // Friday, final repeating instance date
assertEquals("2011-09-09T", events.getJSONObject(3).getJSONObject("startAt").getString("iso8601").substring(0,11)); assertEquals("2011-09-09T", events.getJSONObject(3).getJSONObject("startAt").getString("iso8601").substring(0,11));
// Check by site, should see the same
result = getEntries(null, "2011-08-20&repeating=all");
assertEquals(4, result.length());
assertEquals("8/24/2011", getKeys(result, true)[0]);
assertEquals(1, result.getJSONArray("8/24/2011").length());
assertEquals(EVENT_TITLE_TWO, result.getJSONArray("8/24/2011").getJSONObject(0).get("name"));
assertEquals("8/26/2011", getKeys(result, true)[1]);
assertEquals(1, result.getJSONArray("8/26/2011").length());
assertEquals(EVENT_TITLE_TWO, result.getJSONArray("8/26/2011").getJSONObject(0).get("name"));
assertEquals("9/7/2011", getKeys(result, true)[2]);
assertEquals(1, result.getJSONArray("9/7/2011").length());
assertEquals(EVENT_TITLE_TWO, result.getJSONArray("9/7/2011").getJSONObject(0).get("name"));
assertEquals("9/9/2011", getKeys(result, true)[3]);
assertEquals(1, result.getJSONArray("9/9/2011").length());
assertEquals(EVENT_TITLE_TWO, result.getJSONArray("9/9/2011").getJSONObject(0).get("name"));
} }
} }

View File

@@ -158,6 +158,7 @@ public class UserCalendarEntriesGet extends AbstractCalendarListingWebScript
{ {
// Build the object // Build the object
Map<String, Object> result = new HashMap<String, Object>(); Map<String, Object> result = new HashMap<String, Object>();
result.put(RESULT_EVENT, entry);
result.put(RESULT_NAME, entry.getSystemName()); result.put(RESULT_NAME, entry.getSystemName());
result.put(RESULT_TITLE, entry.getTitle()); result.put(RESULT_TITLE, entry.getTitle());
result.put("description", entry.getDescription()); result.put("description", entry.getDescription());