Bug 1496086 - UX improvements in event dialog and tab for attendee/attachment handling. r=philipp
authorMakeMyDay <makemyday@gmx-topmail.de>
Wed, 03 Oct 2018 16:20:09 +0200
changeset 33411 b2ec0ac175e5b9ba9d8378aa95514fea3f76bf02
parent 33410 1be95c892c357bbb9fb2db9f569ffd7755623659
child 33412 84694c6debe3ef1ecf3f7660326244acc960e762
push id387
push userclokep@gmail.com
push dateMon, 10 Dec 2018 21:30:47 +0000
reviewersphilipp
bugs1496086
Bug 1496086 - UX improvements in event dialog and tab for attendee/attachment handling. r=philipp
calendar/base/themes/common/dialogs/calendar-event-dialog.css
calendar/lightning/content/lightning-item-iframe.js
calendar/lightning/content/lightning-item-iframe.xul
--- a/calendar/base/themes/common/dialogs/calendar-event-dialog.css
+++ b/calendar/base/themes/common/dialogs/calendar-event-dialog.css
@@ -156,16 +156,20 @@ label.label {
 /*--------------------------------------------------------------------
  *   Event dialog tabbox section
  *-------------------------------------------------------------------*/
 
 #event-grid-tabbox {
     margin: 5px 0;
 }
 
+#event-grid-tabbox #notify-options {
+    padding: 0px 9px;
+}
+
 /*--------------------------------------------------------------------
  *   Event dialog keep duration button
  *-------------------------------------------------------------------*/
 
 #keepduration-button {
     list-style-image: url(chrome://calendar-common/skin/chain-unlock.svg);
     padding-top: 3px;
     padding-bottom: 3px;
--- a/calendar/lightning/content/lightning-item-iframe.js
+++ b/calendar/lightning/content/lightning-item-iframe.js
@@ -324,16 +324,18 @@ function onLoad() {
     // we store the item in the window to be able
     // to access this from any location. please note
     // that the item is either an occurrence [proxy]
     // or the stand-alone item [single occurrence item].
     window.calendarItem = item;
     // store the initial date value for datepickers in New Task dialog
     window.initialStartDateValue = args.initialStartDateValue;
 
+    window.attendeeTabLabel = document.getElementById("event-grid-tab-attendees").label;
+    window.attachmentTabLabel = document.getElementById("event-grid-tab-attachments").label;
     // we store the array of attendees in the window.
     // clone each existing attendee since we still suffer
     // from the 'lost x-properties'-bug.
     window.attendees = [];
     let attendees = item.getAttendees({});
     if (attendees && attendees.length) {
         for (let attendee of attendees) {
             window.attendees.push(attendee.clone());
@@ -1907,16 +1909,23 @@ function editAttendees() {
                     organizer.participationStatus = null;
                 }
                 if (!savedWindow.organizer.commonName) {
                     organizer.commonName = null;
                 }
             }
             savedWindow.organizer = organizer;
         }
+
+        // if a participant was added or removed we switch to the attendee
+        // tab, so the user can see the change directly
+        let tabs = document.getElementById("event-grid-tabs");
+        let attendeeTab = document.getElementById("event-grid-tab-attendees");
+        tabs.selectedItem = attendeeTab;
+
         let duration = endTime.subtractDate(startTime);
         startTime = startTime.clone();
         endTime = endTime.clone();
         let kDefaultTimezone = cal.dtz.defaultTimezone;
         gStartTimezone = startTime.timezone;
         gEndTimezone = endTime.timezone;
         gStartTime = startTime.getInTimezone(kDefaultTimezone);
         gEndTime = endTime.getInTimezone(kDefaultTimezone);
@@ -2078,16 +2087,21 @@ function attachURL() {
         );
 
         if (confirm) {
             try {
                 // If something bogus was entered, Services.io.newURI may fail.
                 let attachment = cal.createAttachment();
                 attachment.uri = Services.io.newURI(result.value);
                 addAttachment(attachment);
+                // we switch to the attachment tab if it is not already displayed
+                // to allow the user to see the attachment was added
+                let tabs = document.getElementById("event-grid-tabs");
+                let attachTab = document.getElementById("event-grid-tab-attachments");
+                tabs.selectedItem = attachTab;
             } catch (e) {
                 // TODO We might want to show a warning instead of just not
                 // adding the file
             }
         }
     }
 }
 
@@ -3593,16 +3607,33 @@ function updateTimezone() {
 /**
  * Updates dialog controls related to item attachments
  */
 function updateAttachment() {
     let hasAttachments = capSupported("attachments");
     if (!gNewItemUI) {
         setElementValue("cmd_attach_url", !hasAttachments && "true", "disabled");
     }
+
+    // update the attachment tab label to make the number of (uri) attachments visible
+    // even if another tab is displayed
+    let attachments = Object.values(gAttachMap).filter(aAtt => aAtt.uri);
+    let attachmentTab = document.getElementById("event-grid-tab-attachments");
+    if (attachments.length) {
+        let trailingColon = "";
+        let newLabel = window.attachmentTabLabel;
+        if (newLabel.endsWith(":")) {
+            trailingColon = ":";
+            newLabel = newLabel.substring(0, newLabel.length - 1);
+        }
+        attachmentTab.label = newLabel + " (" + attachments.length + ")" + trailingColon;
+    } else {
+        attachmentTab.label = window.attachmentTabLabel;
+    }
+
     sendMessage({
         command: "updateConfigState",
         argument: { attachUrlCommand: hasAttachments }
     });
 }
 
 /**
  * Returns whether to show or hide the related link on the dialog
@@ -3664,19 +3695,21 @@ function updateItemURL(aShow, aUrl) {
 
 /**
  * This function updates dialog controls related to attendees.
  */
 function updateAttendees() {
     // sending email invitations currently only supported for events
     let attendeeTab = document.getElementById("event-grid-tab-attendees");
     let attendeePanel = document.getElementById("event-grid-tabpanel-attendees");
+    let notifyOptions = document.getElementById("notify-options");
     if (cal.item.isEvent(window.calendarItem)) {
         attendeeTab.removeAttribute("collapsed");
         attendeePanel.removeAttribute("collapsed");
+        notifyOptions.removeAttribute("collapsed");
 
         if (window.organizer && window.organizer.id) {
             document.getElementById("item-organizer-row").removeAttribute("collapsed");
             let cell = document.querySelector(".item-organizer-cell");
             let icon = cell.querySelector("img:nth-of-type(1)");
             let text = cell.querySelector("label:nth-of-type(1)");
 
             let role = organizer.role || "REQ-PARTICIPANT";
@@ -3706,16 +3739,30 @@ function updateAttendees() {
             cell.setAttribute("tooltiptext", tooltip);
             icon.setAttribute("partstat", partStat);
             icon.setAttribute("usertype", userType);
             icon.setAttribute("role", role);
         } else {
             setBooleanAttribute("item-organizer-row", "collapsed", true);
         }
         setupAttendees();
+
+        // update the attendee tab label to make the number of attendees
+        // visible even if another tab is displayed
+        if (window.attendees.length) {
+            let trailingColon = "";
+            let newLabel = window.attendeeTabLabel;
+            if (newLabel.endsWith(":")) {
+                trailingColon = ":";
+                newLabel = newLabel.substring(0, newLabel.length - 1);
+            }
+            attendeeTab.label = newLabel + " (" + window.attendees.length + ")" + trailingColon;
+        } else {
+            attendeeTab.label = window.attendeeTabLabel;
+        }
     } else {
         attendeeTab.setAttribute("collapsed", "true");
         attendeePanel.setAttribute("collapsed", "true");
     }
     updateParentSaveControls();
 }
 
 /**
--- a/calendar/lightning/content/lightning-item-iframe.xul
+++ b/calendar/lightning/content/lightning-item-iframe.xul
@@ -615,36 +615,40 @@
               <hbox flex="1">
                 <vbox id="item-attendees-box"
                       dialog-type="event"
                       flex="1"
                       context="attendee-popup"
                       onclick="attendeeClick(event)"
                       disable-on-readonly="true"/>
               </hbox>
-              <hbox id="notify-options" align="center">
-                <checkbox id="notify-attendees-checkbox"
-                          label="&event.attendees.notify.label;"
-                          accesskey="&event.attendees.notify.accesskey;"
-                          oncommand="changeUndiscloseCheckboxStatus();"
-                          pack="start"/>
-                <checkbox id="undisclose-attendees-checkbox"
-                          label="&event.attendees.notifyundisclosed.label;"
-                          accesskey="&event.attendees.notifyundisclosed.accesskey;"
-                          tooltiptext="&event.attendees.notifyundisclosed.tooltip;"
-                          pack="start"/>
-                <checkbox id="disallow-counter-checkbox"
-                          label="&event.attendees.disallowcounter.label;"
-                          accesskey="&event.attendees.disallowcounter.accesskey;"
-                          tooltiptext="&event.attendees.disallowcounter.tooltip;"
-                          pack="start"/>
-              </hbox>
             </vbox>
           </tabpanel>
         </tabpanels>
+        <hbox id="notify-options"
+              dialog-type="event"
+              align="center"
+              collapsed="true"
+              disable-on-readonly="true">
+          <checkbox id="notify-attendees-checkbox"
+                    label="&event.attendees.notify.label;"
+                    accesskey="&event.attendees.notify.accesskey;"
+                    oncommand="changeUndiscloseCheckboxStatus();"
+                    pack="start"/>
+          <checkbox id="undisclose-attendees-checkbox"
+                    label="&event.attendees.notifyundisclosed.label;"
+                    accesskey="&event.attendees.notifyundisclosed.accesskey;"
+                    tooltiptext="&event.attendees.notifyundisclosed.tooltip;"
+                    pack="start"/>
+          <checkbox id="disallow-counter-checkbox"
+                    label="&event.attendees.disallowcounter.label;"
+                    accesskey="&event.attendees.disallowcounter.accesskey;"
+                    tooltiptext="&event.attendees.disallowcounter.tooltip;"
+                    pack="start"/>
+         </hbox>
       </tabbox>
 
       <separator id="event-grid-link-separator"
                  class="groove"
                  hidden="true"/>
       <row id="event-grid-link-row"
            align="center"
            hidden="true">