Fix bug 404900 - Add Accept/Decline to Calendar item's context menu. r=nomisvai
--HG-- extra : rebase_source : 3cac4e9ff5faccf93fa76b2191d7d78edd909882
This commit is contained in:
Родитель
fe079f7571
Коммит
34118039b9
|
@ -99,6 +99,8 @@ var calendarController = {
|
|||
"calendar_general-progress_command": true,
|
||||
"calendar_task_category_command": true,
|
||||
|
||||
"calendar_attendance_command": true,
|
||||
|
||||
// Pseudo commands
|
||||
"calendar_in_foreground": true,
|
||||
"calendar_in_background": true,
|
||||
|
@ -185,6 +187,13 @@ var calendarController = {
|
|||
case "calendar_reload_remote_calendar":
|
||||
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,
|
||||
// make sure you take care when changing things here.
|
||||
case "calendar_view_next_command":
|
||||
|
@ -387,6 +396,9 @@ var calendarController = {
|
|||
case "calendar_month-view_command":
|
||||
switchCalendarView("month", true);
|
||||
break;
|
||||
case "calendar_attendance_command":
|
||||
// This command is actually handled inline, since it takes a value
|
||||
break;
|
||||
|
||||
default:
|
||||
if (this.defaultController && !this.isCalendarInForeground()) {
|
||||
|
@ -425,9 +437,11 @@ var calendarController = {
|
|||
var selectedItems = aEvent.detail;
|
||||
calendarController.item_selected = selectedItems && (selectedItems.length > 0);
|
||||
|
||||
var selLength = (selectedItems === undefined ? 0 : selectedItems.length);
|
||||
var selected_events_readonly = 0;
|
||||
var selected_events_requires_network = 0;
|
||||
let selLength = (selectedItems === undefined ? 0 : selectedItems.length);
|
||||
let selected_events_readonly = 0;
|
||||
let selected_events_requires_network = 0;
|
||||
let selected_events_invitation = 0;
|
||||
|
||||
if (selLength > 0) {
|
||||
for each (var item in selectedItems) {
|
||||
if (item.calendar.readOnly) {
|
||||
|
@ -436,6 +450,17 @@ var calendarController = {
|
|||
if (item.calendar.getProperty("requiresNetwork")) {
|
||||
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 =
|
||||
(selected_events_requires_network == selLength);
|
||||
calendarController.selected_events_invitation =
|
||||
(selected_events_invitation == selLength);
|
||||
|
||||
calendarController.updateCommands();
|
||||
calendarController2.updateCommands();
|
||||
if(!isSunbird()) {
|
||||
|
@ -459,6 +487,7 @@ var calendarController = {
|
|||
item_selected: false,
|
||||
selected_events_readonly: false,
|
||||
selected_events_requires_network: false,
|
||||
selected_events_invitation: false,
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating if its possible to write items to any
|
||||
|
@ -782,6 +811,40 @@ function setupContextItemType(event, items) {
|
|||
event.target.removeAttribute("type");
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,8 @@
|
|||
<!-- These commands are enabled when in calendar or task mode, respectively -->
|
||||
<command id="calendar_mode_calendar"/>
|
||||
<command id="calendar_mode_task"/>
|
||||
|
||||
<command id="calendar_attendance_command"/>
|
||||
</commandset>
|
||||
|
||||
<keyset id="calendar-keys">
|
||||
|
@ -240,6 +242,62 @@
|
|||
<menuitem id="calendar-item-context-menu-delete-menuitem"
|
||||
key="calendar-delete-item-key"
|
||||
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>
|
||||
|
||||
<!-- CALENDAR VIEW CONTEXT MENU -->
|
||||
|
|
|
@ -491,3 +491,44 @@ function updateUndoRedoMenu() {
|
|||
goUpdateCommand("cmd_undo");
|
||||
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>
|
||||
<handler event="select"><![CDATA[
|
||||
this.mTreeView.onSelect(event);
|
||||
calendarController.onSelectionChanged({detail:this.selectedTasks});
|
||||
if (calendarController.todo_tasktree_focused) {
|
||||
calendarController.onSelectionChanged({detail:this.selectedTasks});
|
||||
}
|
||||
]]></handler>
|
||||
<handler event="dblclick" button="0"><![CDATA[
|
||||
this.mTreeView.onDoubleClick(event);
|
||||
|
|
|
@ -650,6 +650,14 @@ description.tooltipBody {
|
|||
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-editable-item,
|
||||
calendar-month-day-box-item {
|
||||
|
|
|
@ -650,6 +650,14 @@ description.tooltipBody {
|
|||
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-editable-item,
|
||||
calendar-month-day-box-item {
|
||||
|
|
|
@ -203,6 +203,10 @@
|
|||
<!ENTITY calendar.context.pasteevent.accesskey "P">
|
||||
<!ENTITY calendar.context.button.label "Today Pane" >
|
||||
<!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 -->
|
||||
<!ENTITY calendar.context.progress.label "Progress">
|
||||
|
|
Загрузка…
Ссылка в новой задаче