]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 1469023 - Show "new changes since (datetime)" indicator that links to unread...
authorKohei Yoshino <kohei.yoshino@gmail.com>
Tue, 26 Jun 2018 20:50:45 +0000 (16:50 -0400)
committerDylan William Hardison <dylan@hardison.net>
Tue, 26 Jun 2018 20:50:45 +0000 (16:50 -0400)
extensions/BugModal/template/en/default/bug_modal/header.html.tmpl
extensions/BugModal/web/bug_modal.css
extensions/BugModal/web/bug_modal.js

index a21e9c26853dbd747c0d83959558717c21738bdb..c5ae78af3644c200e986da8702e000ac9ae39912 100644 (file)
 
   [%# update last-visited %]
   [% IF user.id && user.is_involved_in_bug(bug) %]
-    $(function() {
-      bugzilla_ajax({
-          url: 'rest/bug_user_last_visit/[% bug.id FILTER none %]',
-          type: 'POST'
-      });
-    });
+    document.addEventListener('DOMContentLoaded', () => show_new_changes_indicator(), { once: true });
   [% END %]
 
   [%# expose useful data to js %]
     is_insider: [% user.is_insider ? "true" : "false" %],
     is_timetracker: [% user.is_timetracker ? "true" : "false" %],
     can_tag: [% user.can_tag_comments ? "true" : "false" %],
+    timezone: '[% user.timezone.name FILTER js %]',
     settings: {
       quote_replies: '[% user.settings.quote_replies.value FILTER js %]',
       zoom_textareas: [% user.settings.zoom_textareas.value == "on" ? "true" : "false" %],
index eeba78d74e86a958d290a6b68e872fd8d86c045e..9a3978b14c8183878dc582f43b937b35a4c9233d 100644 (file)
@@ -532,6 +532,43 @@ td.flag-requestee {
     text-align: right;
 }
 
+.new-changes-link {
+    margin: 8px 0;
+    border-radius: 4px;
+    padding: 4px;
+    font-size: 12px;
+    text-align: center;
+    color: #FFF;
+    background: #277AC1;
+    cursor: pointer;
+}
+
+.new-changes-separator {
+    position: relative;
+    margin: 16px -8px;
+    height: 0;
+    border-top: 1px solid #C00;
+    -moz-user-select: none;
+    -webkit-user-select: none;
+    user-select: none;
+}
+
+.new-changes-separator span {
+    display: inline-block;
+    position: absolute;
+    top: -10px;
+    right: 16px;
+    border: 1px solid #CCC;
+    border-radius: 4px;
+    padding: 0 4px;
+    height: 16px;
+    font-size: 10px;
+    line-height: 16px;
+    text-transform: uppercase;
+    color: #C00;
+    background-color: #FFF;
+}
+
 .change-set {
     clear: both;
     -webkit-box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
index 300ebd3ae3d1a264df73b9248feff018e9c64dc6..ef015d3f9f0e5a6c9b2345d63d4de7348b6d2052 100644 (file)
@@ -1346,6 +1346,93 @@ function confirmUnsafeURL(url) {
         'The full URL is:\n\n' + url + '\n\nContinue?');
 }
 
+function show_new_changes_indicator() {
+    const url = `rest/bug_user_last_visit/${BUGZILLA.bug_id}`;
+
+    // Get the last visited timestamp
+    bugzilla_ajax({ url }, data => {
+        // Save the current timestamp
+        bugzilla_ajax({ url, type: 'POST' });
+
+        if (!data[0] || !data[0].last_visit_ts) {
+            return;
+        }
+
+        const last_visit_ts = new Date(data[0].last_visit_ts);
+        const new_changes = [...document.querySelectorAll('main .change-set')].filter($change => {
+            // Exclude hidden CC changes
+            return $change.clientHeight > 0 &&
+                new Date($change.querySelector('[data-time]').getAttribute('data-time') * 1000) > last_visit_ts;
+        });
+
+        if (new_changes.length === 0) {
+            return;
+        }
+
+        const now = new Date();
+        const date_locale = document.querySelector('html').lang;
+        const date_options = {
+            year: 'numeric',
+            month: 'long',
+            day: 'numeric',
+            hour: 'numeric',
+            minute: 'numeric',
+            hour12: false,
+            timeZone: BUGZILLA.user.timezone,
+            timeZoneName: 'short',
+        };
+
+        if (last_visit_ts.getFullYear() === now.getFullYear()) {
+            delete date_options.year;
+
+            if (last_visit_ts.getMonth() === now.getMonth() && last_visit_ts.getDate() === now.getDate()) {
+                delete date_options.month;
+                delete date_options.day;
+            }
+        }
+
+        const $link = document.createElement('div');
+        const $separator = document.createElement('div');
+        const comments_count = new_changes.filter($change => !!$change.querySelector('.comment')).length;
+        const changes_count = new_changes.length - comments_count;
+        const date_attr = last_visit_ts.toISOString();
+        const date_label = last_visit_ts.toLocaleString(date_locale, date_options);
+
+        // Insert a link
+        $link.className = 'new-changes-link';
+        $link.innerHTML =
+            (c => c === 0 ? '' : (c === 1 ? `${c} new comment` : `${c} new comments`))(comments_count) +
+            (comments_count > 0 && changes_count > 0 ? ', ' : '') +
+            (c => c === 0 ? '' : (c === 1 ? `${c} new change` : `${c} new changes`))(changes_count) +
+            ` since <time datetime="${date_attr}">${date_label}</time>`;
+        $link.addEventListener('click', () => {
+            $link.remove();
+            scroll_element_into_view($separator);
+        }, { once: true });
+        document.querySelector('#changeform').insertAdjacentElement('beforebegin', $link);
+
+        // Insert a separator
+        $separator.className = 'new-changes-separator';
+        $separator.innerHTML = '<span>New</span>';
+        new_changes[0].insertAdjacentElement('beforebegin', $separator);
+
+        // Remove the link once the separator goes into the viewport
+        if ('IntersectionObserver' in window) {
+            const observer = new IntersectionObserver(entries => entries.forEach(entry => {
+                if (entry.intersectionRatio > 0) {
+                    observer.unobserve($separator);
+                    $link.remove();
+                }
+            }), { root: $separator.offsetParent });
+
+            observer.observe($separator);
+        }
+
+        // TODO: Enable auto-scroll once the modal page layout is optimized
+        // scroll_element_into_view($separator);
+    });
+}
+
 // fix url after bug creation/update
 if (history && history.replaceState) {
     let bug_id    = BUGZILLA.bug_id;