From 0bede69b362014318edc727b18f554c6192bd952 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Mon, 18 Aug 2008 22:45:59 +0000 Subject: [PATCH] Monotone-Parent: 82c1108954dbd812828ef1b00b0345b524a062a7 Monotone-Revision: 1bc4da9c10aec9ded2d443f77aedb8ceeaaf7ce8 Monotone-Author: flachapelle@inverse.ca Monotone-Date: 2008-08-18T22:45:59 Monotone-Branch: ca.inverse.sogo --- NEWS | 1 + UI/Scheduler/UIxAppointmentEditor.m | 31 ++++ UI/Scheduler/product.plist | 5 + UI/Templates/SchedulerUI/UIxCalMainView.wox | 9 ++ UI/Templates/SchedulerUI/UIxCalMonthView.wox | 1 + UI/WebServerResources/SchedulerUI.css | 61 +++++-- UI/WebServerResources/SchedulerUI.js | 159 ++++++++++++++----- UI/WebServerResources/dialog-left.png | Bin 0 -> 456 bytes UI/WebServerResources/dialog-right.png | Bin 0 -> 453 bytes UI/WebServerResources/generic.js | 7 +- 10 files changed, 223 insertions(+), 51 deletions(-) create mode 100644 UI/WebServerResources/dialog-left.png create mode 100644 UI/WebServerResources/dialog-right.png diff --git a/NEWS b/NEWS index e213cadaf..177bdfc06 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,7 @@ - fixed a bug where deleting a contact would leave it listed in the contact list until the next refresh - fixed a bug where events shared among different attendees would no longer be updated automatically - changed the look of the Calendar module to match the look of Lightning 0.9 +- the event details now appear when clicking on it 0.9.0-20080729 (1.0 rc7) ------------------------ diff --git a/UI/Scheduler/UIxAppointmentEditor.m b/UI/Scheduler/UIxAppointmentEditor.m index 4a747391a..3658bd27f 100644 --- a/UI/Scheduler/UIxAppointmentEditor.m +++ b/UI/Scheduler/UIxAppointmentEditor.m @@ -22,6 +22,8 @@ #include +#import + #import #import #import @@ -36,6 +38,7 @@ #import #import +#import #import #import #import @@ -267,6 +270,34 @@ return [self jsCloseWithRefreshMethod: @"refreshEventsAndDisplay()"]; } +- (id ) viewAction +{ + id result; + NSDictionary *data; + SOGoAppointmentFolder *co; + SOGoDateFormatter *dateFormatter; + SOGoUser *user; + + result = [context response]; + user = [context activeUser]; + co = [self clientObject]; + dateFormatter = [user dateFormatterInContext: context]; + [self event]; + + data = [NSDictionary dictionaryWithObjectsAndKeys: + [dateFormatter formattedDate: [event startDate]], @"startDate", + [dateFormatter formattedTime: [event startDate]], @"startTime", + ([event hasRecurrenceRules]?@"1":@"0"), @"isReccurent", + ([event isAllDay]?@"1":@"0"), @"isAllDay", + [event summary], @"summary", + [event location], @"location", + [event comment], @"description", + nil]; + [(WOResponse*)result appendContentString: [data jsonRepresentation]]; + + return result; +} + - (BOOL) shouldTakeValuesFromRequest: (WORequest *) request inContext: (WOContext*) context { diff --git a/UI/Scheduler/product.plist b/UI/Scheduler/product.plist index 490a2b64e..ef7eab304 100644 --- a/UI/Scheduler/product.plist +++ b/UI/Scheduler/product.plist @@ -172,6 +172,11 @@ }; }; methods = { + view = { + protectedBy = "ViewAllComponent"; + pageName = "UIxAppointmentEditor"; + actionName = "view"; + }; edit = { protectedBy = "ViewAllComponent"; pageName = "UIxAppointmentEditor"; diff --git a/UI/Templates/SchedulerUI/UIxCalMainView.wox b/UI/Templates/SchedulerUI/UIxCalMainView.wox index 1abd7a5b9..b91e06d61 100644 --- a/UI/Templates/SchedulerUI/UIxCalMainView.wox +++ b/UI/Templates/SchedulerUI/UIxCalMainView.wox @@ -76,6 +76,15 @@
  • + +
    diff --git a/UI/Templates/SchedulerUI/UIxCalMonthView.wox b/UI/Templates/SchedulerUI/UIxCalMonthView.wox index 0428018a6..5bed9e2a6 100644 --- a/UI/Templates/SchedulerUI/UIxCalMonthView.wox +++ b/UI/Templates/SchedulerUI/UIxCalMonthView.wox @@ -6,6 +6,7 @@ xmlns:const="http://www.skyrix.com/od/constant" xmlns:rsrc="OGo:url" xmlns:label="OGo:label"> + LI._selected, TABLE._unfocused#eventsList TR._selected TD @@ -354,19 +398,13 @@ SPAN.monthsHeader A:active border-right: 1px solid #fff; } SPAN.week2, SPAN.month2 -{ - font-size: small; -} +{ font-size: small; } SPAN.day2, SPAN.week1, SPAN.month1 -{ - font-size: medium; -} +{ font-size: medium; } SPAN.day1, SPAN.week0, SPAN.month0 -{ - font-size: large; -} +{ font-size: large; } SPAN.day0 { font-size: x-large; } @@ -891,6 +929,9 @@ DIV.monthView DIV.event padding: 1px; height: 1.2em; } +DIV#calendarHeader DIV.event +{ height: 1.5em; } + DIV.event DIV.text { font-size: 92%; } diff --git a/UI/WebServerResources/SchedulerUI.js b/UI/WebServerResources/SchedulerUI.js index 883e3069b..89513dcd0 100644 --- a/UI/WebServerResources/SchedulerUI.js +++ b/UI/WebServerResources/SchedulerUI.js @@ -77,7 +77,7 @@ function _editEventId(id, calendar, recurrence) { urlstr += "/" + recurrence; targetname += recurrence; } - urlstr += "/edit"; + urlstr += "/edit"; log (urlstr); var win = window.open(urlstr, "_blank", "width=490,height=470,resizable=0"); if (win) @@ -315,14 +315,96 @@ function _editRecurrenceDialog(eventDiv, method) { win.focus(); } +function onViewEvent(event) { + if (event.detail == 2) return; + var url = ApplicationBaseURL + this.calendar + "/" + this.cname + "/view"; + if (document.viewEventAjaxRequest) { + document.viewEventAjaxRequest.aborted = true; + document.viewEventAjaxRequest.abort(); + } + document.viewEventAjaxRequest = triggerAjaxRequest(url, onViewEventCallback, this); +} + +function onViewEventCallback(http) { + if (http.readyState == 4 + && http.status == 200) { + if (http.responseText.length > 0) { + var data = http.responseText.evalJSON(true); +// $H(data).keys().each(function(key) { +// log (key + " = " + data[key]); +// }); + var cell = http.callbackData; + var cellPosition = cell.cumulativeOffset(); + var cellDimensions = cell.getDimensions(); + var div = $("eventDialog"); + var divDimensions = div.getDimensions(); + var view; + var left = cellPosition[0]; + var top = cellPosition[1]; + + if (currentView != "monthview") { + view = $("daysView"); + var viewPosition = view.cumulativeOffset(); + + if (parseInt(data["isAllDay"]) == 0) { + top -= view.scrollTop; + if (viewPosition[1] > top + 2) { + view.stopObserving("scroll", onBodyClickHandler); + view.scrollTop = cell.offsetTop; + top = viewPosition[1]; + Event.observe.delay(0.1, view, "scroll", onBodyClickHandler); + } + } + } + else { + view = $("calendarView"); + top -= cell.up("DIV.day").scrollTop; + } + + if (left > parseInt(window.width()*0.75)) { + left = left - divDimensions["width"] + 10; + div.removeClassName("left"); + div.addClassName("right"); + } + else { + left = left + cellDimensions["width"] - parseInt(cellDimensions["width"]/3); + div.removeClassName("right"); + div.addClassName("left"); + } + + // Put the event's data in the DIV + div.down("h1").update(data["summary"]); + if (parseInt(data["isAllDay"]) == 0) { + div.down("P", 0).down("SPAN", 1).update(data["startTime"]); + div.down("P", 0).show(); + } else + div.down("P", 0).hide(); + if (data["location"].length) { + div.down("P", 1).down("SPAN", 1).update(data["location"]); + div.down("P", 1).show(); + } else + div.down("P", 1).hide(); + + if (data["description"].length) { + div.down("P", 2).update(data["description"]); + div.down("P", 2).show(); + } else + div.down("P", 2).hide(); + + div.setStyle({ left: left + "px", + top: top + "px" }); + div.show(); + } + } +} + function editDoubleClickedEvent(event) { if (this.recurrenceTime) _editRecurrenceDialog(this, "confirmEditing"); else _editEventId(this.cname, this.calendar); - preventDefault(event); - event.cancelBubble = true; + Event.stop(event); } function performEventEdition(folder, event, recurrence) { @@ -667,7 +749,7 @@ function changeCalendarDisplay(data, newView) { day = currentDay; if (day) { - if (data && newView != "monthview") { + if (data) { var divs = $$('div.day[day='+day+']'); if (divs.length) { // Don't reload the view if the event is present in current view @@ -703,14 +785,10 @@ function changeCalendarDisplay(data, newView) { } url += "?day=" + day; } - // if (newView) - // log ("switching to view: " + newView); - // log ("changeCalendarDisplay: " + url); selectedCalendarCell = null; if (document.dayDisplayAjaxRequest) { - // log ("aborting day ajaxrq"); document.dayDisplayAjaxRequest.aborted = true; document.dayDisplayAjaxRequest.abort(); } @@ -747,39 +825,30 @@ function onMonthOverview() { } function scrollDayView(scrollEvent) { - var divs; - - // Select event in calendar view if (scrollEvent) { + var contentView; var eventRow = $(scrollEvent); - selectCalendarEvent(eventRow.calendar, eventRow.cname, eventRow.recurrenceTime); + var eventBlocks = selectCalendarEvent(eventRow.calendar, eventRow.cname, eventRow.recurrenceTime); + var firstEvent = eventBlocks.first(); + + if (currentView == "monthview") + contentView = firstEvent.up("DIV.day"); + else + contentView = $("daysView"); + + var top = firstEvent.cumulativeOffset()[1] - contentView.scrollTop; + + // Don't scroll if the event is visible to the user + if (top < contentView.cumulativeOffset()[1]) + contentView.scrollTop = firstEvent.cumulativeOffset()[1] - contentView.cumulativeOffset()[1]; + else if (top > contentView.cumulativeOffset()[1] + contentView.getHeight() - firstEvent.getHeight()) + contentView.scrollTop = firstEvent.cumulativeOffset()[1] - contentView.cumulativeOffset()[1]; } - - // Don't scroll if in month view - if (currentView == "monthview") - return; - - var offset = 0; - var daysView = $("daysView"); - var hours = $(daysView.childNodesWithTag("div")[0]) - .childNodesWithTag("div"); - - offset = hours[dayStartHour].offsetTop; - - if (scrollEvent && calendarEvents) { - var event = calendarEvents[scrollEvent]; - if (event) { - // FIXME siblings - var classes = $w(event.siblings[0].className); - for (var i = 0; i < classes.length; i++) - if (classes[i].startsWith("starts")) { - var starts = Math.floor(parseInt(classes[i].substr(6)) / 4); - offset = hours[starts].offsetTop; - } - } + else if (currentView != "monthview") { + var contentView = $("daysView"); + var hours = (contentView.childNodesWithTag("div")[0]).childNodesWithTag("div"); + contentView.scrollTop = hours[dayStartHour].offsetTop; } - - daysView.scrollTop = offset - 5; } function onClickableCellsDblClick(event) { @@ -916,6 +985,7 @@ function newBaseEventDIV(eventRep, event, eventText) { eventDiv.observe("mousedown", listRowMouseDownHandler); eventDiv.observe("click", onCalendarSelectEvent); eventDiv.observe("dblclick", editDoubleClickedEvent); + eventDiv.observe("click", onViewEvent); event.blocks.push(eventDiv); @@ -1015,9 +1085,11 @@ function calendarDisplayCallback(http) { var contentView; if (currentView == "monthview") contentView = $("calendarContent"); - else + else { contentView = $("daysView"); - + contentView.observe("scroll", onBodyClickHandler); + } + refreshCalendarEvents(http.callbackData.scrollEvent); var days = document.getElementsByClassName("day", contentView); @@ -1027,6 +1099,8 @@ function calendarDisplayCallback(http) { days[i].observe("dblclick", onClickableCellsDblClick); days[i].observe("selectstart", listRowMouseDownHandler); //days[i].down(".dayHeader").observe("selectstart", listRowMouseDownHandler); + if (currentView == "monthview") + days[i].observe("scroll", onBodyClickHandler); } else { var headerDivs = $("calendarHeader").childNodesWithTag("div"); @@ -1307,6 +1381,8 @@ function selectCalendarEvent(calendar, cname, recurrenceTime) { selection[i].selectElement(); selectedCalendarCell = selection; } + + return selection; } function onCalendarSelectEvent() { @@ -1863,6 +1939,10 @@ function initDateSelectorEvents() { menuButton.observe("click", popupMonthMenu); } +function onBodyClickHandler(event) { + $("eventDialog").hide(); +} + function initCalendars() { sorting["attribute"] = "start"; sorting["ascending"] = true; @@ -1875,6 +1955,7 @@ function initCalendars() { var selector = $("calendarSelector"); if (selector) selector.attachMenu("calendarsMenu"); + $(document.body).observe("click", onBodyClickHandler); } } diff --git a/UI/WebServerResources/dialog-left.png b/UI/WebServerResources/dialog-left.png new file mode 100644 index 0000000000000000000000000000000000000000..a19b0536b51d3d79ca260e3ad0094eec14e2d4b1 GIT binary patch literal 456 zcmeAS@N?(olHy`uVBq!ia0vp^!VC=T7dV)KEb-7OSwM;<-O<;Pf#KSXEB+BiK)z&& zYeY$Kep*R+Vo@rCV@iHfs)A>3VtQ&&YGO)d;mK4RprY^qpAgso|Nq~;bH~rmFEKH3 z;>3yJ;o&=W?D+TZ-_@&EKYnFn9F z0|El-Yis+uyJKQv4jnr5^XJcwjt&>y2OgKP#o4HM?^x_LSby;vetAWjEdJ sKX=^V`Tv9-!($T3G$Vd9S92LKaM|kJI?dDk1L!jbPgg&ebxsLQ0IFWt1^@s6 literal 0 HcmV?d00001 diff --git a/UI/WebServerResources/dialog-right.png b/UI/WebServerResources/dialog-right.png new file mode 100644 index 0000000000000000000000000000000000000000..dfea12bd5d6478843003479ede6bc17de8355f55 GIT binary patch literal 453 zcmeAS@N?(olHy`uVBq!ia0vp^!VC=T7dV)KEb-7OSwM;<-O<;Pf#KSXEB+BiK)z&& zYeY$Kep*R+Vo@rCV@iHfs)A>3VtQ&&YGO)d;mK4RprY^qpAgso|Nq~;bH~rmFEKH3 z;>3yJ;o&=W?D+TZ-_@&EKYnFn9F z0|El-Yis+uyJKQv4jnr5^XJcwjt&+@lQ+!i)jYk& zW21Fz_$$Xv+oaN-`)7XBjQe$b-|nm3GtA!JDCAqM=IwfK|JOEWpV*(3r>$;>-T(ep p?N9YFiR2zbnh_iAx6Wo@W(W<^yCqz05e)PegQu&X%Q~loCIHn>)|CJN literal 0 HcmV?d00001 diff --git a/UI/WebServerResources/generic.js b/UI/WebServerResources/generic.js index 936fa7e36..986216ffc 100644 --- a/UI/WebServerResources/generic.js +++ b/UI/WebServerResources/generic.js @@ -870,13 +870,16 @@ function setSearchCriteria(event) { var searchValue = $("searchValue"); var searchCriteria = $("searchCriteria"); + if (searchValue.ghostPhrase == searchValue.value) + searchValue.value = this.innerHTML; + searchValue.ghostPhrase = this.innerHTML; searchCriteria.value = this.getAttribute('id'); if (this.parentNode.chosenNode) this.parentNode.chosenNode.removeClassName("_chosen"); this.addClassName("_chosen"); - + if (this.parentNode.chosenNode != this) { searchValue.lastSearch = ""; this.parentNode.chosenNode = this; @@ -959,7 +962,7 @@ function onSearchKeyDown(event) { function onSearchFormSubmit(event) { var searchValue = $("searchValue"); var searchCriteria = $("searchCriteria"); - + if (searchValue.value != searchValue.ghostPhrase && (searchValue.value != searchValue.lastSearch || searchValue.value.strip().length > 0)) {