Fix bug 404900 - Add Accept/Decline to Calendar item's context menu. r=nomisvai

--HG--
extra : rebase_source : 3cac4e9ff5faccf93fa76b2191d7d78edd909882
This commit is contained in:
Philipp Kewisch 2011-02-13 11:45:00 +01:00
Родитель fe079f7571
Коммит 34118039b9
7 изменённых файлов: 188 добавлений и 4 удалений

Просмотреть файл

@ -99,6 +99,8 @@ var calendarController = {
"calendar_general-progress_command": true, "calendar_general-progress_command": true,
"calendar_task_category_command": true, "calendar_task_category_command": true,
"calendar_attendance_command": true,
// Pseudo commands // Pseudo commands
"calendar_in_foreground": true, "calendar_in_foreground": true,
"calendar_in_background": true, "calendar_in_background": true,
@ -185,6 +187,13 @@ var calendarController = {
case "calendar_reload_remote_calendar": case "calendar_reload_remote_calendar":
return !this.no_network_calendars && !this.offline; return !this.no_network_calendars && !this.offline;
case "calendar_attendance_command":
// Small hack, we want to hide instead of disable.
let attendSel = this.item_selected && this.selected_events_invitation;
setBooleanAttribute("calendar_attendance_command", "hidden", !attendSel);
return attendSel;
break;
// The following commands all just need the calendar in foreground, // The following commands all just need the calendar in foreground,
// make sure you take care when changing things here. // make sure you take care when changing things here.
case "calendar_view_next_command": case "calendar_view_next_command":
@ -387,6 +396,9 @@ var calendarController = {
case "calendar_month-view_command": case "calendar_month-view_command":
switchCalendarView("month", true); switchCalendarView("month", true);
break; break;
case "calendar_attendance_command":
// This command is actually handled inline, since it takes a value
break;
default: default:
if (this.defaultController && !this.isCalendarInForeground()) { if (this.defaultController && !this.isCalendarInForeground()) {
@ -425,9 +437,11 @@ var calendarController = {
var selectedItems = aEvent.detail; var selectedItems = aEvent.detail;
calendarController.item_selected = selectedItems && (selectedItems.length > 0); calendarController.item_selected = selectedItems && (selectedItems.length > 0);
var selLength = (selectedItems === undefined ? 0 : selectedItems.length); let selLength = (selectedItems === undefined ? 0 : selectedItems.length);
var selected_events_readonly = 0; let selected_events_readonly = 0;
var selected_events_requires_network = 0; let selected_events_requires_network = 0;
let selected_events_invitation = 0;
if (selLength > 0) { if (selLength > 0) {
for each (var item in selectedItems) { for each (var item in selectedItems) {
if (item.calendar.readOnly) { if (item.calendar.readOnly) {
@ -436,6 +450,17 @@ var calendarController = {
if (item.calendar.getProperty("requiresNetwork")) { if (item.calendar.getProperty("requiresNetwork")) {
selected_events_requires_network++; selected_events_requires_network++;
} }
if (cal.isInvitation(item)) {
selected_events_invitation++;
} else if (item.organizer) {
// If we are the organizer and there are attendees, then
// this is likely also an invitation.
let calOrgId = item.calendar.getProperty("organizerId");
if (item.organizer.id == calOrgId && item.getAttendees({}).length) {
selected_events_invitation++;
}
}
} }
} }
@ -444,6 +469,9 @@ var calendarController = {
calendarController.selected_events_requires_network = calendarController.selected_events_requires_network =
(selected_events_requires_network == selLength); (selected_events_requires_network == selLength);
calendarController.selected_events_invitation =
(selected_events_invitation == selLength);
calendarController.updateCommands(); calendarController.updateCommands();
calendarController2.updateCommands(); calendarController2.updateCommands();
if(!isSunbird()) { if(!isSunbird()) {
@ -459,6 +487,7 @@ var calendarController = {
item_selected: false, item_selected: false,
selected_events_readonly: false, selected_events_readonly: false,
selected_events_requires_network: false, selected_events_requires_network: false,
selected_events_invitation: false,
/** /**
* Returns a boolean indicating if its possible to write items to any * Returns a boolean indicating if its possible to write items to any
@ -782,6 +811,40 @@ function setupContextItemType(event, items) {
event.target.removeAttribute("type"); event.target.removeAttribute("type");
adaptModificationMenuItem("calendar-item-context-menu-delete-menuitem", "Item"); adaptModificationMenuItem("calendar-item-context-menu-delete-menuitem", "Item");
} }
let menu = document.getElementById("calendar-item-context-menu-attendance-menu");
let allSingle = items.every(function(x) !x.recurrenceId);
setElementValue(menu, allSingle ? "single" : "recurring", "itemType");
// Set up the attendance menu
function getInvStat(item) {
let attendee = null;
if (cal.isInvitation(item)) {
attendee = cal.getInvitedAttendee(item);
} else if (item.organizer) {
let calOrgId = item.calendar.getProperty("organizerId");
if (calOrgId == item.organizer.id && item.getAttendees({}).length) {
attendee = item.organizer;
}
}
return attendee && attendee.participationStatus;
}
let firstStatusOccurrences = items.length && getInvStat(items[0]);
let firstStatusParents = items.length && getInvStat(items[0].parentItem);
let sameStatusOccurrences = items.every(function (x) getInvStat(x) == firstStatusOccurrences);
let sameStatusParents = items.every(function (x) getInvStat(x.parentItem) == firstStatusParents)
let occurrenceChildren = menu.getElementsByAttribute("value", firstStatusOccurrences);
let parentsChildren = menu.getElementsByAttribute("value", firstStatusParents);
if (sameStatusOccurrences && occurrenceChildren[0]) {
occurrenceChildren[0].setAttribute("checked", "true");
}
if (sameStatusParents && parentsChildren[1]) {
parentsChildren[1].setAttribute("checked", "true");
}
return true; return true;
} }

Просмотреть файл

@ -128,6 +128,8 @@
<!-- These commands are enabled when in calendar or task mode, respectively --> <!-- These commands are enabled when in calendar or task mode, respectively -->
<command id="calendar_mode_calendar"/> <command id="calendar_mode_calendar"/>
<command id="calendar_mode_task"/> <command id="calendar_mode_task"/>
<command id="calendar_attendance_command"/>
</commandset> </commandset>
<keyset id="calendar-keys"> <keyset id="calendar-keys">
@ -240,6 +242,62 @@
<menuitem id="calendar-item-context-menu-delete-menuitem" <menuitem id="calendar-item-context-menu-delete-menuitem"
key="calendar-delete-item-key" key="calendar-delete-item-key"
observes="calendar_delete_event_command"/> observes="calendar_delete_event_command"/>
<menu id="calendar-item-context-menu-attendance-menu"
label="&calendar.context.attendance.menu.label;"
accesskey="&calendar.context.attendance.menu.accesskey;"
oncommand="setContextPartstat(event.target.value, event.target.getAttribute('scope'), currentView().getSelectedItems({}))"
observes="calendar_attendance_command">
<menupopup id="calendar-item-context-menu-attendance-menupopup">
<label id="calendar-item-context-attendance-thisoccurrence-label"
class="calendar-context-heading-label"
scope="all-occurrences"
value="&calendar.context.attendance.occurrence.label;"/>
<menuitem id="calendar-item-context-menu-attend-accept-menuitem"
type="radio"
scope="this-occurrence"
name="calendar-item-context-attendance"
label="&read.only.accept.label;" value="ACCEPTED"/>
<menuitem id="calendar-item-context-menu-attend-tentative-menuitem"
type="radio"
scope="this-occurrence"
name="calendar-item-context-attendance"
label="&read.only.tentative.label;" value="TENTATIVE"/>
<menuitem id="calendar-item-context-menu-attend-declined-menuitem"
type="radio"
scope="this-occurrence"
name="calendar-item-context-attendance"
label="&read.only.decline.label;" value="DECLINED"/>
<menuitem id="calendar-item-context-menu-attend-needsaction-menuitem"
type="radio"
scope="this-occurrence"
name="calendar-item-context-attendance"
label="&read.only.needs.action.label;" value="NEEDS-ACTION"/>
<label id="calendar-item-context-attendance-alloccurrence-label"
class="calendar-context-heading-label"
scope="all-occurrences"
value="&calendar.context.attendance.all.label;"/>
<menuitem id="calendar-item-context-menu-attend-accept-all-menuitem"
type="radio"
scope="all-occurrences"
name="calendar-item-context-attendance-all"
label="&read.only.accept.label;" value="ACCEPTED"/>
<menuitem id="calendar-item-context-menu-attend-tentative-all-menuitem"
type="radio"
scope="all-occurrences"
name="calendar-item-context-attendance-all"
label="&read.only.tentative.label;" value="TENTATIVE"/>
<menuitem id="calendar-item-context-menu-attend-declined-all-menuitem"
type="radio"
scope="all-occurrences"
name="calendar-item-context-attendance-all"
label="&read.only.decline.label;" value="DECLINED"/>
<menuitem id="calendar-item-context-menu-attend-needsaction-all-menuitem"
type="radio"
scope="all-occurrences"
name="calendar-item-context-attendance-all"
label="&read.only.needs.action.label;" value="NEEDS-ACTION"/>
</menupopup>
</menu>
</menupopup> </menupopup>
<!-- CALENDAR VIEW CONTEXT MENU --> <!-- CALENDAR VIEW CONTEXT MENU -->

Просмотреть файл

@ -491,3 +491,44 @@ function updateUndoRedoMenu() {
goUpdateCommand("cmd_undo"); goUpdateCommand("cmd_undo");
goUpdateCommand("cmd_redo"); goUpdateCommand("cmd_redo");
} }
function setContextPartstat(value, scope, items) {
startBatchTransaction();
try {
for each (let oldItem in items) {
if (scope == "all-occurrences") {
oldItem = oldItem.parentItem;
}
let attendee = null;
if (cal.isInvitation(oldItem)) {
// Check for the invited attendee first, this is more important
attendee = cal.getInvitedAttendee(oldItem);
} else if (oldItem.organizer && oldItem.getAttendees({}).length) {
// Now check the organizer. This should be done last.
let calOrgId = oldItem.calendar.getProperty("organizerId");
if (calOrgId == oldItem.organizer.id) {
attendee = oldItem.organizer;
}
}
if (attendee) {
let newItem = oldItem.clone();
let newAttendee = attendee.clone();
newAttendee.participationStatus = value;
if (newAttendee.isOrganizer) {
newItem.organizer = newAttendee;
} else {
newItem.removeAttendee(attendee);
newItem.addAttendee(newAttendee);
}
doTransaction('modify', newItem, newItem.calendar, oldItem, null);
}
}
} catch (e) {
cal.ERROR("Error settinge partstat: " + e);
} finally {
endBatchTransaction();
}
}

Просмотреть файл

@ -1142,7 +1142,9 @@
<handlers> <handlers>
<handler event="select"><![CDATA[ <handler event="select"><![CDATA[
this.mTreeView.onSelect(event); this.mTreeView.onSelect(event);
if (calendarController.todo_tasktree_focused) {
calendarController.onSelectionChanged({detail:this.selectedTasks}); calendarController.onSelectionChanged({detail:this.selectedTasks});
}
]]></handler> ]]></handler>
<handler event="dblclick" button="0"><![CDATA[ <handler event="dblclick" button="0"><![CDATA[
this.mTreeView.onDoubleClick(event); this.mTreeView.onDoubleClick(event);

Просмотреть файл

@ -650,6 +650,14 @@ description.tooltipBody {
display: none; display: none;
} }
#calendar-item-context-menu-attendance-menu[itemType="single"] > menupopup > *[scope="all-occurrences"] {
display: none;
}
.calendar-context-heading-label {
font-weight: bold;
}
calendar-event-box, calendar-event-box,
calendar-editable-item, calendar-editable-item,
calendar-month-day-box-item { calendar-month-day-box-item {

Просмотреть файл

@ -650,6 +650,14 @@ description.tooltipBody {
display: none; display: none;
} }
#calendar-item-context-menu-attendance-menu[itemType="single"] > menupopup > *[scope="all-occurrences"] {
display: none;
}
.calendar-context-heading-label {
font-weight: bold;
}
calendar-event-box, calendar-event-box,
calendar-editable-item, calendar-editable-item,
calendar-month-day-box-item { calendar-month-day-box-item {

Просмотреть файл

@ -203,6 +203,10 @@
<!ENTITY calendar.context.pasteevent.accesskey "P"> <!ENTITY calendar.context.pasteevent.accesskey "P">
<!ENTITY calendar.context.button.label "Today Pane" > <!ENTITY calendar.context.button.label "Today Pane" >
<!ENTITY calendar.context.button.accesskey "T" > <!ENTITY calendar.context.button.accesskey "T" >
<!ENTITY calendar.context.attendance.menu.label "Attendance" >
<!ENTITY calendar.context.attendance.menu.accesskey "d" >
<!ENTITY calendar.context.attendance.occurrence.label "This Occurrence" >
<!ENTITY calendar.context.attendance.all.label "All Occurrences" >
<!-- Task Context Menu --> <!-- Task Context Menu -->
<!ENTITY calendar.context.progress.label "Progress"> <!ENTITY calendar.context.progress.label "Progress">