summaryrefslogtreecommitdiffstats
path: root/extensions/BugModal
diff options
context:
space:
mode:
authorDylan William Hardison <dylan@hardison.net>2018-07-08 06:59:55 +0200
committerDylan William Hardison <dylan@hardison.net>2018-07-08 06:59:55 +0200
commitbe1f92450788dc89280c9e04a4bf983b5d7fac54 (patch)
treeb5513fd846597fe5f152177dbbda88dca08fdf5f /extensions/BugModal
parent9bbd8d368598046c47964ee043620621b6c3634b (diff)
parent446a08b30b0dbaac9f2b88e0a5cad410f0446140 (diff)
downloadbugzilla-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.tmpl8
-rw-r--r--extensions/BugModal/template/en/default/bug_modal/user.html.tmpl2
-rw-r--r--extensions/BugModal/web/bug_modal.css48
-rw-r--r--extensions/BugModal/web/bug_modal.js152
-rw-r--r--extensions/BugModal/web/comments.js2
-rw-r--r--extensions/BugModal/web/common_bug_modal.js2
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 =