diff options
author | Dylan William Hardison <dylan@hardison.net> | 2018-07-08 06:59:55 +0200 |
---|---|---|
committer | Dylan William Hardison <dylan@hardison.net> | 2018-07-08 06:59:55 +0200 |
commit | be1f92450788dc89280c9e04a4bf983b5d7fac54 (patch) | |
tree | b5513fd846597fe5f152177dbbda88dca08fdf5f /extensions/BugModal | |
parent | 9bbd8d368598046c47964ee043620621b6c3634b (diff) | |
parent | 446a08b30b0dbaac9f2b88e0a5cad410f0446140 (diff) | |
download | bugzilla-be1f92450788dc89280c9e04a4bf983b5d7fac54.tar.gz bugzilla-be1f92450788dc89280c9e04a4bf983b5d7fac54.tar.xz |
Merge remote-tracking branch 'bmo/master'
Diffstat (limited to 'extensions/BugModal')
-rw-r--r-- | extensions/BugModal/template/en/default/bug_modal/header.html.tmpl | 8 | ||||
-rw-r--r-- | extensions/BugModal/template/en/default/bug_modal/user.html.tmpl | 2 | ||||
-rw-r--r-- | extensions/BugModal/web/bug_modal.css | 48 | ||||
-rw-r--r-- | extensions/BugModal/web/bug_modal.js | 152 | ||||
-rw-r--r-- | extensions/BugModal/web/comments.js | 2 | ||||
-rw-r--r-- | extensions/BugModal/web/common_bug_modal.js | 2 |
6 files changed, 206 insertions, 8 deletions
diff --git a/extensions/BugModal/template/en/default/bug_modal/header.html.tmpl b/extensions/BugModal/template/en/default/bug_modal/header.html.tmpl index 38b6b572f..b9a42caf3 100644 --- a/extensions/BugModal/template/en/default/bug_modal/header.html.tmpl +++ b/extensions/BugModal/template/en/default/bug_modal/header.html.tmpl @@ -83,12 +83,7 @@ [%# 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 %] @@ -100,6 +95,7 @@ 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" %], diff --git a/extensions/BugModal/template/en/default/bug_modal/user.html.tmpl b/extensions/BugModal/template/en/default/bug_modal/user.html.tmpl index cd05d053f..9eda7b936 100644 --- a/extensions/BugModal/template/en/default/bug_modal/user.html.tmpl +++ b/extensions/BugModal/template/en/default/bug_modal/user.html.tmpl @@ -46,7 +46,7 @@ END; href="mailto:[% u.email FILTER html %]" data-user-email="[% u.email FILTER html %]" data-user-id="[% u.id FILTER html %]" - data-show-edit="[% user.in_group('editusers') || user.bless_groups.size > 0 ? 1 : 0 %]" + data-show-edit="[% user.in_group('editusers') || user.in_group('disableusers') || user.bless_groups.size > 0 ? 1 : 0 %]" title="[% u.identity FILTER html %]" [% ELSE %] href="user_profile?user_id=[% u.id FILTER none %]" diff --git a/extensions/BugModal/web/bug_modal.css b/extensions/BugModal/web/bug_modal.css index 65aeec86d..a8c469ad6 100644 --- a/extensions/BugModal/web/bug_modal.css +++ b/extensions/BugModal/web/bug_modal.css @@ -153,6 +153,12 @@ a.activity-ref { font-weight: normal; padding-right: 5px; color: #666; + opacity: 1; + transition: all .2s; +} + +.module-spinner[aria-expanded="true"] ~ .module-subtitle { + opacity: 0; } .module .fields-lhs { @@ -532,6 +538,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); @@ -626,6 +669,11 @@ body.platform-Win32 .comment-text, body.platform-Win64 .comment-text { width: 99% !important; } +.comment-text.bz_private { + color: darkred; + border: 1px dashed darkred; +} + .comment-tags { padding: 0 8px 2px 8px !important; } diff --git a/extensions/BugModal/web/bug_modal.js b/extensions/BugModal/web/bug_modal.js index c6abb5d7a..4a770e66c 100644 --- a/extensions/BugModal/web/bug_modal.js +++ b/extensions/BugModal/web/bug_modal.js @@ -96,6 +96,54 @@ $(function() { $('#editing').val(''); } + function saveBugComment(text) { + if (text.length < 1) return clearSavedBugComment(); + if (text.length > 65535) return; + let key = `bug-modal-saved-comment-${BUGZILLA.bug_id}`; + let value = { + text: text, + savedAt: Date.now() + }; + localStorage.setItem(key, JSON.stringify(value)); + } + + function clearSavedBugComment() { + let key = `bug-modal-saved-comment-${BUGZILLA.bug_id}`; + localStorage.removeItem(key); + } + + function restoreSavedBugComment() { + expireSavedComments(); + let key = `bug-modal-saved-comment-${BUGZILLA.bug_id}`; + let value = JSON.parse(localStorage.getItem(key)); + if (value){ + let commentBox = document.querySelector("textarea#comment"); + commentBox.value = value['text']; + if (BUGZILLA.user.settings.autosize_comments) { + autosize.update(commentBox); + } + } + } + + function expireSavedComments() { + const AGE_THRESHOLD = 7 * 24 * 60 * 60 * 1000; // 7 days in milliseconds. + let expiredKeys = []; + for (let i = 0; i < localStorage.length; i++) { + let key = localStorage.key(i); + if (key.match(/^bug-modal-saved-comment-/)) { + let value = JSON.parse(localStorage.getItem(key)); + let savedAt = value['savedAt'] || 0; + let age = Date.now() - savedAt; + if (age < 0 || age > AGE_THRESHOLD) { + expiredKeys.push(key); + } + } + } + expiredKeys.forEach((key) => { + localStorage.removeItem(key); + }); + } + // expand/colapse module $('.module-latch') .click(function(event) { @@ -309,7 +357,9 @@ $(function() { // execCommand("copy") only works on selected text $('#clip-container').show(); $('#clip').val(clipboardSummary()).select(); - document.execCommand("copy"); + $('#floating-message-text') + .text(document.execCommand("copy") ? 'Bug summary copied!' : 'Couldn’t copy bug summary'); + $('#floating-message').fadeIn(250).delay(2500).fadeOut(); $('#clip-container').hide(); }); } @@ -509,6 +559,8 @@ $(function() { keywords = data.keywords; $('#keywords') .devbridgeAutocomplete({ + appendTo: $('#main-inner'), + forceFixPosition: true, lookup: function(query, done) { query = query.toLowerCase(); var matchStart = @@ -586,6 +638,8 @@ $(function() { .toArray() .join(' ') ); + + clearSavedBugComment(); }) .attr('disabled', false); @@ -1272,9 +1326,18 @@ $(function() { } }); + // Save comments in progress + $('#comment') + .on('input', function(event) { + saveBugComment(event.target.value); + }); + // finally switch to edit mode if we navigate back to a page that was editing $(window).on('pageshow', restoreEditMode); + $(window).on('pageshow', restoreSavedBugComment); + $(window).on('focus', restoreSavedBugComment); restoreEditMode(); + restoreSavedBugComment(); }); function confirmUnsafeURL(url) { @@ -1283,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: document.querySelector('#bugzilla-body') }); + + 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) { var href = document.location.href; diff --git a/extensions/BugModal/web/comments.js b/extensions/BugModal/web/comments.js index 04894506e..85c5a2368 100644 --- a/extensions/BugModal/web/comments.js +++ b/extensions/BugModal/web/comments.js @@ -355,6 +355,8 @@ $(function() { $('#ctag-add') .devbridgeAutocomplete({ + appendTo: $('#main-inner'), + forceFixPosition: true, serviceUrl: function(query) { return 'rest/bug/comment/tags/' + encodeURIComponent(query); }, diff --git a/extensions/BugModal/web/common_bug_modal.js b/extensions/BugModal/web/common_bug_modal.js index dc91824f6..6cd658045 100644 --- a/extensions/BugModal/web/common_bug_modal.js +++ b/extensions/BugModal/web/common_bug_modal.js @@ -509,6 +509,8 @@ $(function() { keywords = data.keywords; $('#keywords') .devbridgeAutocomplete({ + appendTo: $('#main-inner'), + forceFixPosition: true, lookup: function(query, done) { query = query.toLowerCase(); var matchStart = |