aboutsummaryrefslogtreecommitdiffstats
path: root/web_src/js
diff options
context:
space:
mode:
authorsilverwind <me@silverwind.io>2024-06-07 15:42:31 +0200
committerGitHub <noreply@github.com>2024-06-07 13:42:31 +0000
commit291a00dc570a143092e5ad19cdad12939d3d70dc (patch)
treea58aff279e223d3897e7b3e757486f04c942f8d9 /web_src/js
parent15debbbe4eb94c1855a0178e379b7e3d19bd07ad (diff)
downloadgitea-291a00dc570a143092e5ad19cdad12939d3d70dc.tar.gz
gitea-291a00dc570a143092e5ad19cdad12939d3d70dc.zip
Fix and clean up `ConfirmModal` (#31283)
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: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: delvh <dev.lh@web.de>
Diffstat (limited to 'web_src/js')
-rw-r--r--web_src/js/features/common-global.js4
-rw-r--r--web_src/js/features/comp/ConfirmModal.js25
-rw-r--r--web_src/js/features/repo-issue-list.js2
-rw-r--r--web_src/js/utils/dom.js7
-rw-r--r--web_src/js/utils/dom.test.js5
5 files changed, 28 insertions, 15 deletions
diff --git a/web_src/js/features/common-global.js b/web_src/js/features/common-global.js
index 3b021d4485..65eb237dde 100644
--- a/web_src/js/features/common-global.js
+++ b/web_src/js/features/common-global.js
@@ -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();
}
}
diff --git a/web_src/js/features/comp/ConfirmModal.js b/web_src/js/features/comp/ConfirmModal.js
index e64996a352..f9ad5c39cc 100644
--- a/web_src/js/features/comp/ConfirmModal.js
+++ b/web_src/js/features/comp/ConfirmModal.js
@@ -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);
diff --git a/web_src/js/features/repo-issue-list.js b/web_src/js/features/repo-issue-list.js
index 92f058c4d2..5d18a7ff8d 100644
--- a/web_src/js/features/repo-issue-list.js
+++ b/web_src/js/features/repo-issue-list.js
@@ -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;
}
}
diff --git a/web_src/js/utils/dom.js b/web_src/js/utils/dom.js
index a48510b191..7289f19cbf 100644
--- a/web_src/js/utils/dom.js
+++ b/web_src/js/utils/dom.js
@@ -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
index 0000000000..fd7d97cad5
--- /dev/null
+++ b/web_src/js/utils/dom.test.js
@@ -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>');
+});