]> source.dussan.org Git - gitea.git/commitdiff
Avoid duplicate JS error messages on UI (#28873)
authorwxiaoguang <wxiaoguang@gmail.com>
Sun, 21 Jan 2024 14:23:08 +0000 (22:23 +0800)
committerGitHub <noreply@github.com>
Sun, 21 Jan 2024 14:23:08 +0000 (14:23 +0000)
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, like this:

```js
<div class="page-content">
  <div class="... js-global-error" data-global-error-msg-compact="testmsg1" data-global-error-msg-count="2">test msg 1 (2)</div>
  <div class="... js-global-error" data-global-error-msg-compact="testmsg2" data-global-error-msg-count="1">test msg 2</div>
</div>
```

web_src/js/bootstrap.js
web_src/js/bootstrap.test.js [new file with mode: 0644]
web_src/js/test/setup.js

index 15e5b21204de06c72481a2d7999d945dff93ee4f..f8d0c0cac0c33fdc10754ff32a4716f4b0db52d7 100644 (file)
@@ -8,10 +8,21 @@ __webpack_public_path__ = `${window.config?.assetUrlPrefix ?? '/assets'}/`;
 export function showGlobalErrorMessage(msg) {
   const pageContent = document.querySelector('.page-content');
   if (!pageContent) return;
-  const el = document.createElement('div');
-  el.innerHTML = `<div class="ui container negative message center aligned js-global-error" style="white-space: pre-line;"></div>`;
-  el.childNodes[0].textContent = msg;
-  pageContent.prepend(el.childNodes[0]);
+
+  // compact the message to a data attribute to avoid too many duplicated messages
+  const msgCompact = msg.replace(/\W/g, '').trim();
+  let msgDiv = pageContent.querySelector(`.js-global-error[data-global-error-msg-compact="${msgCompact}"]`);
+  if (!msgDiv) {
+    const el = document.createElement('div');
+    el.innerHTML = `<div class="ui container negative message center aligned js-global-error" style="white-space: pre-line;"></div>`;
+    msgDiv = el.childNodes[0];
+  }
+  // merge duplicated messages into "the message (count)" format
+  const msgCount = Number(msgDiv.getAttribute(`data-global-error-msg-count`)) + 1;
+  msgDiv.setAttribute(`data-global-error-msg-compact`, msgCompact);
+  msgDiv.setAttribute(`data-global-error-msg-count`, msgCount.toString());
+  msgDiv.textContent = msg + (msgCount > 1 ? ` (${msgCount})` : '');
+  pageContent.prepend(msgDiv);
 }
 
 /**
diff --git a/web_src/js/bootstrap.test.js b/web_src/js/bootstrap.test.js
new file mode 100644 (file)
index 0000000..a6b901b
--- /dev/null
@@ -0,0 +1,12 @@
+import {showGlobalErrorMessage} from './bootstrap.js';
+
+test('showGlobalErrorMessage', () => {
+  document.body.innerHTML = '<div class="page-content"></div>';
+  showGlobalErrorMessage('test msg 1');
+  showGlobalErrorMessage('test msg 2');
+  showGlobalErrorMessage('test msg 1'); // duplicated
+
+  expect(document.body.innerHTML).toContain('>test msg 1 (2)<');
+  expect(document.body.innerHTML).toContain('>test msg 2<');
+  expect(document.querySelectorAll('.js-global-error').length).toEqual(2);
+});
index 52355c7adcbcdbccf99282d2d1e4aa83a577234c..6fb0f5dc8f8bf2410430ec4d8d72a8f5c789e2ee 100644 (file)
@@ -1,3 +1,5 @@
+window.__webpack_public_path__ = '';
+
 window.config = {
   csrfToken: 'test-csrf-token-123456',
   pageData: {},