Avoid duplicate JS error messages on UI (#28873)
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> ```
This commit is contained in:
		
					parent
					
						
							
								0e6fd0d1c1
							
						
					
				
			
			
				commit
				
					
						5d09023f13
					
				
			
		
					 3 changed files with 29 additions and 4 deletions
				
			
		
							
								
								
									
										19
									
								
								web_src/js/bootstrap.js
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								web_src/js/bootstrap.js
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								web_src/js/bootstrap.test.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								web_src/js/bootstrap.test.js
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
window.__webpack_public_path__ = '';
 | 
			
		||||
 | 
			
		||||
window.config = {
 | 
			
		||||
  csrfToken: 'test-csrf-token-123456',
 | 
			
		||||
  pageData: {},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue