From d33252bf60fe8ec7ac9ecd39c1906f71c2cb9472 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Mon, 5 Dec 2011 05:04:25 +0000 Subject: [PATCH] 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 --- .../slingshot/calendar/eventList.get.json.ftl | 17 +-- .../AbstractCalendarListingWebScript.java | 3 +- .../calendar/CalendarEntriesListGet.java | 55 +++++++-- .../scripts/calendar/CalendarRestApiTest.java | 115 ++++++++++++++++-- .../calendar/UserCalendarEntriesGet.java | 1 + 5 files changed, 166 insertions(+), 25 deletions(-) diff --git a/config/alfresco/templates/webscripts/org/alfresco/slingshot/calendar/eventList.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/slingshot/calendar/eventList.get.json.ftl index d082b41f84..ca211e0037 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/slingshot/calendar/eventList.get.json.ftl +++ b/config/alfresco/templates/webscripts/org/alfresco/slingshot/calendar/eventList.get.json.ftl @@ -5,8 +5,9 @@ <#elseif events?exists && events?size > 0> <#assign prev = ""> <#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 date = event.start?string("M/d/yyyy")> <#if date != prev> <#assign counter = 0> <#if item_index > 0>], @@ -14,17 +15,17 @@ <#if counter > 0>, { - "name": "${event.title}", + "name": "${item.title}", "uri": "calendar/event/${siteId}/${event.systemName}", "startAt": { - "iso8601": "${xmldate(event.start)}", - "legacyDate": "${event.start?string("M/d/yyyy")}", - "legacyTime": "${event.start?string("HH:mm")}" + "iso8601": "${xmldate(item.start)}", + "legacyDate": "${item.start?string("M/d/yyyy")}", + "legacyTime": "${item.start?string("HH:mm")}" }, "endAt": { - "iso8601": "${xmldate(event.end)}", - "legacyDate": "${event.end?string("M/d/yyyy")}", - "legacyTime": "${event.end?string("HH:mm")}" + "iso8601": "${xmldate(item.end)}", + "legacyDate": "${item.end?string("M/d/yyyy")}", + "legacyTime": "${item.end?string("HH:mm")}" }, "tags": [<#list item.tags as tag>"${tag}"<#if tag_has_next>,], diff --git a/source/java/org/alfresco/repo/web/scripts/calendar/AbstractCalendarListingWebScript.java b/source/java/org/alfresco/repo/web/scripts/calendar/AbstractCalendarListingWebScript.java index 24f089cc7d..e5e7823553 100644 --- a/source/java/org/alfresco/repo/web/scripts/calendar/AbstractCalendarListingWebScript.java +++ b/source/java/org/alfresco/repo/web/scripts/calendar/AbstractCalendarListingWebScript.java @@ -38,7 +38,8 @@ import org.alfresco.service.cmr.calendar.CalendarRecurrenceHelper; */ 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_START = "start"; protected static final String RESULT_END = "end"; diff --git a/source/java/org/alfresco/repo/web/scripts/calendar/CalendarEntriesListGet.java b/source/java/org/alfresco/repo/web/scripts/calendar/CalendarEntriesListGet.java index 6c1c2a1ee3..4f3094bced 100644 --- a/source/java/org/alfresco/repo/web/scripts/calendar/CalendarEntriesListGet.java +++ b/source/java/org/alfresco/repo/web/scripts/calendar/CalendarEntriesListGet.java @@ -20,6 +20,7 @@ package org.alfresco.repo.web.scripts.calendar; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashMap; 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. * - * TODO Improve what we give to the FTL - * TODO Switch to using {@link AbstractCalendarListingWebScript} - * * @author Nick Burch * @since 4.0 */ -public class CalendarEntriesListGet extends AbstractCalendarWebScript +public class CalendarEntriesListGet extends AbstractCalendarListingWebScript { @Override protected Map executeImpl(SiteInfo site, String eventName, 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 PagingRequest paging = buildPagingRequest(req); - PagingResults entries = - calendarService.listCalendarEntries(site.getShortName(), paging); + PagingResults entries = calendarService.listCalendarEntries( + new String[] {site.getShortName()}, fromDate, toDate, paging); // For each one in our page, grab details of any ignored instances List> results = new ArrayList>(); for (CalendarEntry entry : entries.getPage()) { Map result = new HashMap(); - 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("tags", entry.getTags()); @@ -86,9 +111,23 @@ public class CalendarEntriesListGet extends AbstractCalendarWebScript result.put("ignoreEvents", ignoreEvents); 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); } + // If they asked for repeating events to be expanded, then do so + if (resortNeeded) + { + Collections.sort(results, getEventDetailsSorter()); + } + // All done Map model = new HashMap(); model.put("events", results); diff --git a/source/java/org/alfresco/repo/web/scripts/calendar/CalendarRestApiTest.java b/source/java/org/alfresco/repo/web/scripts/calendar/CalendarRestApiTest.java index 49af82cb2d..4bd205a9d8 100644 --- a/source/java/org/alfresco/repo/web/scripts/calendar/CalendarRestApiTest.java +++ b/source/java/org/alfresco/repo/web/scripts/calendar/CalendarRestApiTest.java @@ -18,7 +18,10 @@ */ package org.alfresco.repo.web.scripts.calendar; +import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; +import java.util.List; import org.alfresco.model.ContentModel; import org.alfresco.repo.calendar.CalendarServiceImpl; @@ -195,7 +198,7 @@ public class CalendarRestApiTest extends BaseWebScriptTest } if (from != null) { - if (url.indexOf('/') > 0) + if (url.indexOf('?') > 0) { url += "&"; } @@ -265,10 +268,8 @@ public class CalendarRestApiTest extends BaseWebScriptTest json.put("page", "calendar"); // Copy in the date properties - Iterator datesIT = datesJSON.keys(); - while(datesIT.hasNext()) + for (String key : getKeys(datesJSON, false)) { - String key = datesIT.next(); json.put(key, datesJSON.get(key)); } @@ -368,6 +369,25 @@ public class CalendarRestApiTest extends BaseWebScriptTest return response.getContentAsString(); } + /** + * Returns the Keys of a JSON Object, optionally sorted + */ + private String[] getKeys(JSONObject json, boolean sorted) + { + @SuppressWarnings("unchecked") + Iterator ki = json.keys(); + + List keys = new ArrayList(json.length()); + while (ki.hasNext()) + { + keys.add(ki.next()); + } + + if(sorted) { Collections.sort(keys); } + + return keys.toArray(new String[keys.size()]); + } + // 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; JSONArray events; @@ -1007,10 +1028,13 @@ public class CalendarRestApiTest extends BaseWebScriptTest String entryName2 = getNameFromEntry(entry2); // Have it repeat on wednesdays and fridays every two weeks updateEntry(entryName2, EVENT_TITLE_TWO, "Somewhere", "Thing 2", true, Status.STATUS_OK); - + // 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"); assertEquals(2, events.length()); 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")); + // 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 + // ------------------------------------------ + + // For the user result = getEntries("admin", "2011/06/27"); events = result.getJSONArray("events"); 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)); // 3rd repeat Friday 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 @@ -1080,5 +1158,26 @@ public class CalendarRestApiTest extends BaseWebScriptTest assertEquals("2011-09-07T", events.getJSONObject(2).getJSONObject("startAt").getString("iso8601").substring(0,11)); // Friday, final repeating instance date 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")); } } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/web/scripts/calendar/UserCalendarEntriesGet.java b/source/java/org/alfresco/repo/web/scripts/calendar/UserCalendarEntriesGet.java index 03d75f79ed..f6e03fad37 100644 --- a/source/java/org/alfresco/repo/web/scripts/calendar/UserCalendarEntriesGet.java +++ b/source/java/org/alfresco/repo/web/scripts/calendar/UserCalendarEntriesGet.java @@ -158,6 +158,7 @@ public class UserCalendarEntriesGet extends AbstractCalendarListingWebScript { // Build the object Map result = new HashMap(); + result.put(RESULT_EVENT, entry); result.put(RESULT_NAME, entry.getSystemName()); result.put(RESULT_TITLE, entry.getTitle()); result.put("description", entry.getDescription());