]> source.dussan.org Git - gitea.git/commitdiff
Fix and clean up `ConfirmModal` (#31283) (#31291)
authorGiteabot <teabot@gitea.io>
Fri, 7 Jun 2024 13:51:54 +0000 (21:51 +0800)
committerGitHub <noreply@github.com>
Fri, 7 Jun 2024 13:51:54 +0000 (15:51 +0200)
Backport #31283 by @silverwind

Bug: orange button color was removed in
https://github.com/go-gitea/gitea/pull/30475, replaced with red
Bug: translation text was not html-escaped
Refactor: Replaced as much jQuery as possible, added useful
`createElementFromHTML`
Refactor: Remove colors checks that don't exist on `.link-action`

<img width="381" alt="image"
src="https://github.com/go-gitea/gitea/assets/115237/5900bf6a-8a86-4a86-b368-0559cbfea66e">

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: delvh <dev.lh@web.de>
web_src/js/features/common-global.js
web_src/js/features/comp/ConfirmModal.js
web_src/js/features/repo-issue-list.js
web_src/js/utils/dom.js
web_src/js/utils/dom.test.js [new file with mode: 0644]

index 3b021d44851a2b6628d2c1c5ccaf363dc34b13b0..65eb237ddeee3a3af5c3d522c654b2949f057a5c 100644 (file)
@@ -295,8 +295,8 @@ async function linkAction(e) {
     return;
   }
 
-  const isRisky = el.classList.contains('red') || el.classList.contains('yellow') || el.classList.contains('orange') || el.classList.contains('negative');
-  if (await confirmModal({content: modalConfirmContent, buttonColor: isRisky ? 'orange' : 'primary'})) {
+  const isRisky = el.classList.contains('red') || el.classList.contains('negative');
+  if (await confirmModal(modalConfirmContent, {confirmButtonColor: isRisky ? 'red' : 'primary'})) {
     await doRequest();
   }
 }
index e64996a3529a796ec630859ce1760c498206df68..f9ad5c39cca52abc5ea062999a9443100702c4c6 100644 (file)
@@ -1,22 +1,23 @@
 import $ from 'jquery';
 import {svg} from '../../svg.js';
 import {htmlEscape} from 'escape-goat';
+import {createElementFromHTML} from '../../utils/dom.js';
 
 const {i18n} = window.config;
 
-export async function confirmModal(opts = {content: '', buttonColor: 'primary'}) {
+export function confirmModal(content, {confirmButtonColor = 'primary'} = {}) {
   return new Promise((resolve) => {
-    const $modal = $(`
-<div class="ui g-modal-confirm modal">
-  <div class="content">${htmlEscape(opts.content)}</div>
-  <div class="actions">
-    <button class="ui cancel button">${svg('octicon-x')} ${i18n.modal_cancel}</button>
-    <button class="ui ${opts.buttonColor || 'primary'} ok button">${svg('octicon-check')} ${i18n.modal_confirm}</button>
-  </div>
-</div>
-`);
-
-    $modal.appendTo(document.body);
+    const modal = createElementFromHTML(`
+      <div class="ui g-modal-confirm modal">
+        <div class="content">${htmlEscape(content)}</div>
+        <div class="actions">
+          <button class="ui cancel button">${svg('octicon-x')} ${htmlEscape(i18n.modal_cancel)}</button>
+          <button class="ui ${confirmButtonColor} ok button">${svg('octicon-check')} ${htmlEscape(i18n.modal_confirm)}</button>
+        </div>
+      </div>
+    `);
+    document.body.append(modal);
+    const $modal = $(modal);
     $modal.modal({
       onApprove() {
         resolve(true);
index 92f058c4d20e1842e729ad2bf90cddc7f86de451..5d18a7ff8d330e325e469753b2bb60bc87c23991 100644 (file)
@@ -76,7 +76,7 @@ function initRepoIssueListCheckboxes() {
     // for delete
     if (action === 'delete') {
       const confirmText = e.target.getAttribute('data-action-delete-confirm');
-      if (!await confirmModal({content: confirmText, buttonColor: 'orange'})) {
+      if (!await confirmModal(confirmText, {confirmButtonColor: 'red'})) {
         return;
       }
     }
index a48510b191d11d336a9b3839e4987a04c54fe6f0..7289f19cbfef06a560c49fedb4bdb3ff969bd062 100644 (file)
@@ -297,3 +297,10 @@ export function replaceTextareaSelection(textarea, text) {
     textarea.dispatchEvent(new CustomEvent('change', {bubbles: true, cancelable: true}));
   }
 }
+
+// Warning: Do not enter any unsanitized variables here
+export function createElementFromHTML(htmlString) {
+  const div = document.createElement('div');
+  div.innerHTML = htmlString.trim();
+  return div.firstChild;
+}
diff --git a/web_src/js/utils/dom.test.js b/web_src/js/utils/dom.test.js
new file mode 100644 (file)
index 0000000..fd7d97c
--- /dev/null
@@ -0,0 +1,5 @@
+import {createElementFromHTML} from './dom.js';
+
+test('createElementFromHTML', () => {
+  expect(createElementFromHTML('<a>foo<span>bar</span></a>').outerHTML).toEqual('<a>foo<span>bar</span></a>');
+});