Skip to content

Commit b7e32b2

Browse files
GiteaBotwxiaoguang
andauthored
Avoid duplicate JS error messages on UI (#28873) (#28881)
Backport #28873 by wxiaoguang Gitea treat JS errors seriously, so sometimes the JS errors caused by 3rdparty code (eg: browser extensions) would also be reported on Gitea UI: TypeError: WeakMap key undefined (caused by extension DarkReader's bug) #28861 To avoid fill the user's screen with a lot of error messages, this PR merges the same error messages into one. Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
1 parent e3dfb51 commit b7e32b2

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

web_src/js/bootstrap.js

+15-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,21 @@ __webpack_public_path__ = `${window.config?.assetUrlPrefix ?? '/assets'}/`;
88
export function showGlobalErrorMessage(msg) {
99
const pageContent = document.querySelector('.page-content');
1010
if (!pageContent) return;
11-
const el = document.createElement('div');
12-
el.innerHTML = `<div class="ui container negative message center aligned js-global-error" style="white-space: pre-line;"></div>`;
13-
el.childNodes[0].textContent = msg;
14-
pageContent.prepend(el.childNodes[0]);
11+
12+
// compact the message to a data attribute to avoid too many duplicated messages
13+
const msgCompact = msg.replace(/\W/g, '').trim();
14+
let msgDiv = pageContent.querySelector(`.js-global-error[data-global-error-msg-compact="${msgCompact}"]`);
15+
if (!msgDiv) {
16+
const el = document.createElement('div');
17+
el.innerHTML = `<div class="ui container negative message center aligned js-global-error" style="white-space: pre-line;"></div>`;
18+
msgDiv = el.childNodes[0];
19+
}
20+
// merge duplicated messages into "the message (count)" format
21+
const msgCount = Number(msgDiv.getAttribute(`data-global-error-msg-count`)) + 1;
22+
msgDiv.setAttribute(`data-global-error-msg-compact`, msgCompact);
23+
msgDiv.setAttribute(`data-global-error-msg-count`, msgCount.toString());
24+
msgDiv.textContent = msg + (msgCount > 1 ? ` (${msgCount})` : '');
25+
pageContent.prepend(msgDiv);
1526
}
1627

1728
/**

web_src/js/bootstrap.test.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import {showGlobalErrorMessage} from './bootstrap.js';
2+
3+
test('showGlobalErrorMessage', () => {
4+
document.body.innerHTML = '<div class="page-content"></div>';
5+
showGlobalErrorMessage('test msg 1');
6+
showGlobalErrorMessage('test msg 2');
7+
showGlobalErrorMessage('test msg 1'); // duplicated
8+
9+
expect(document.body.innerHTML).toContain('>test msg 1 (2)<');
10+
expect(document.body.innerHTML).toContain('>test msg 2<');
11+
expect(document.querySelectorAll('.js-global-error').length).toEqual(2);
12+
});

web_src/js/test/setup.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
window.__webpack_public_path__ = '';
2+
13
window.config = {
24
csrfToken: 'test-csrf-token-123456',
35
pageData: {},

0 commit comments

Comments
 (0)