Fix and clean up `ConfirmModal` (#31283) (#31291)

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>
This commit is contained in:
Giteabot 2024-06-07 21:51:54 +08:00 committed by GitHub
parent 75e0bdcec5
commit 5ca4c6d066
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 28 additions and 15 deletions

View File

@ -295,8 +295,8 @@ async function linkAction(e) {
return; return;
} }
const isRisky = el.classList.contains('red') || el.classList.contains('yellow') || el.classList.contains('orange') || el.classList.contains('negative'); const isRisky = el.classList.contains('red') || el.classList.contains('negative');
if (await confirmModal({content: modalConfirmContent, buttonColor: isRisky ? 'orange' : 'primary'})) { if (await confirmModal(modalConfirmContent, {confirmButtonColor: isRisky ? 'red' : 'primary'})) {
await doRequest(); await doRequest();
} }
} }

View File

@ -1,22 +1,23 @@
import $ from 'jquery'; import $ from 'jquery';
import {svg} from '../../svg.js'; import {svg} from '../../svg.js';
import {htmlEscape} from 'escape-goat'; import {htmlEscape} from 'escape-goat';
import {createElementFromHTML} from '../../utils/dom.js';
const {i18n} = window.config; const {i18n} = window.config;
export async function confirmModal(opts = {content: '', buttonColor: 'primary'}) { export function confirmModal(content, {confirmButtonColor = 'primary'} = {}) {
return new Promise((resolve) => { return new Promise((resolve) => {
const $modal = $(` const modal = createElementFromHTML(`
<div class="ui g-modal-confirm modal"> <div class="ui g-modal-confirm modal">
<div class="content">${htmlEscape(opts.content)}</div> <div class="content">${htmlEscape(content)}</div>
<div class="actions"> <div class="actions">
<button class="ui cancel button">${svg('octicon-x')} ${i18n.modal_cancel}</button> <button class="ui cancel button">${svg('octicon-x')} ${htmlEscape(i18n.modal_cancel)}</button>
<button class="ui ${opts.buttonColor || 'primary'} ok button">${svg('octicon-check')} ${i18n.modal_confirm}</button> <button class="ui ${confirmButtonColor} ok button">${svg('octicon-check')} ${htmlEscape(i18n.modal_confirm)}</button>
</div> </div>
</div> </div>
`); `);
document.body.append(modal);
$modal.appendTo(document.body); const $modal = $(modal);
$modal.modal({ $modal.modal({
onApprove() { onApprove() {
resolve(true); resolve(true);

View File

@ -76,7 +76,7 @@ function initRepoIssueListCheckboxes() {
// for delete // for delete
if (action === 'delete') { if (action === 'delete') {
const confirmText = e.target.getAttribute('data-action-delete-confirm'); const confirmText = e.target.getAttribute('data-action-delete-confirm');
if (!await confirmModal({content: confirmText, buttonColor: 'orange'})) { if (!await confirmModal(confirmText, {confirmButtonColor: 'red'})) {
return; return;
} }
} }

View File

@ -297,3 +297,10 @@ export function replaceTextareaSelection(textarea, text) {
textarea.dispatchEvent(new CustomEvent('change', {bubbles: true, cancelable: true})); 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;
}

View File

@ -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>');
});