summaryrefslogtreecommitdiffstats
path: root/extensions/BugModal/web
diff options
context:
space:
mode:
authorKohei Yoshino <kohei.yoshino@gmail.com>2018-06-26 22:50:45 +0200
committerDylan William Hardison <dylan@hardison.net>2018-06-26 22:50:45 +0200
commita685e15218fbe7d26015a579c96caf7de783732d (patch)
treeac5f9157392181648ef995c182efbee3c0d2fe28 /extensions/BugModal/web
parent02e46829b2ddd0f6109c7d81cf40c1865b01a122 (diff)
downloadbugzilla-a685e15218fbe7d26015a579c96caf7de783732d.tar.gz
bugzilla-a685e15218fbe7d26015a579c96caf7de783732d.tar.xz
Bug 1469023 - Show "new changes since (datetime)" indicator that links to unread changes/comments
Diffstat (limited to 'extensions/BugModal/web')
-rw-r--r--extensions/BugModal/web/bug_modal.css37
-rw-r--r--extensions/BugModal/web/bug_modal.js87
2 files changed, 124 insertions, 0 deletions
diff --git a/extensions/BugModal/web/bug_modal.css b/extensions/BugModal/web/bug_modal.css
index eeba78d74..9a3978b14 100644
--- a/extensions/BugModal/web/bug_modal.css
+++ b/extensions/BugModal/web/bug_modal.css
@@ -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);
diff --git a/extensions/BugModal/web/bug_modal.js b/extensions/BugModal/web/bug_modal.js
index 300ebd3ae..ef015d3f9 100644
--- a/extensions/BugModal/web/bug_modal.js
+++ b/extensions/BugModal/web/bug_modal.js
@@ -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;