1
0
Fork 0
forked from forgejo/forgejo

Batch delete issue and improve tippy opts (#25253)

1. Add "batch delete" button for selected issues, close #22273
2. Address the review in
https://github.com/go-gitea/gitea/pull/25219#discussion_r1229266083
This commit is contained in:
wxiaoguang 2023-06-19 15:46:50 +08:00 committed by GitHub
parent 51c2aebe1f
commit a1c5057fe8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 104 additions and 47 deletions

View file

@ -8,6 +8,7 @@ import {svg} from '../svg.js';
import {hideElem, showElem, toggleElem} from '../utils/dom.js';
import {htmlEscape} from 'escape-goat';
import {createTippy} from '../modules/tippy.js';
import {confirmModal} from './comp/ConfirmModal.js';
const {appUrl, appSubUrl, csrfToken, i18n} = window.config;
@ -264,7 +265,7 @@ export function initGlobalDropzone() {
}
}
function linkAction(e) {
async function linkAction(e) {
e.preventDefault();
// A "link-action" can post AJAX request to its "data-url"
@ -291,33 +292,16 @@ function linkAction(e) {
});
};
const modalConfirmHtml = htmlEscape($this.attr('data-modal-confirm') || '');
if (!modalConfirmHtml) {
const modalConfirmContent = htmlEscape($this.attr('data-modal-confirm') || '');
if (!modalConfirmContent) {
doRequest();
return;
}
const okButtonColor = $this.hasClass('red') || $this.hasClass('yellow') || $this.hasClass('orange') || $this.hasClass('negative') ? 'orange' : 'green';
const $modal = $(`
<div class="ui g-modal-confirm modal">
<div class="content">${modalConfirmHtml}</div>
<div class="actions">
<button class="ui basic cancel button">${svg('octicon-x')} ${i18n.modal_cancel}</button>
<button class="ui ${okButtonColor} ok button">${svg('octicon-check')} ${i18n.modal_confirm}</button>
</div>
</div>
`);
$modal.appendTo(document.body);
$modal.modal({
onApprove() {
doRequest();
},
onHidden() {
$modal.remove();
},
}).modal('show');
const isRisky = $this.hasClass('red') || $this.hasClass('yellow') || $this.hasClass('orange') || $this.hasClass('negative');
if (await confirmModal({content: modalConfirmContent, buttonColor: isRisky ? 'orange' : 'green'})) {
doRequest();
}
}
export function initGlobalLinkActions() {

View file

@ -0,0 +1,30 @@
import $ from 'jquery';
import {svg} from '../../svg.js';
import {htmlEscape} from 'escape-goat';
const {i18n} = window.config;
export async function confirmModal(opts = {content: '', buttonColor: 'green'}) {
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 basic cancel button">${svg('octicon-x')} ${i18n.modal_cancel}</button>
<button class="ui ${opts.buttonColor || 'green'} ok button">${svg('octicon-check')} ${i18n.modal_confirm}</button>
</div>
</div>
`);
$modal.appendTo(document.body);
$modal.modal({
onApprove() {
resolve(true);
},
onHidden() {
$modal.remove();
resolve(false);
},
}).modal('show');
});
}

View file

@ -3,6 +3,7 @@ import {updateIssuesMeta} from './repo-issue.js';
import {toggleElem} from '../utils/dom.js';
import {htmlEscape} from 'escape-goat';
import {Sortable} from 'sortablejs';
import {confirmModal} from './comp/ConfirmModal.js';
function initRepoIssueListCheckboxes() {
const $issueSelectAll = $('.issue-checkbox-all');
@ -36,19 +37,36 @@ function initRepoIssueListCheckboxes() {
$('.issue-action').on('click', async function (e) {
e.preventDefault();
const url = this.getAttribute('data-url');
let action = this.getAttribute('data-action');
let elementId = this.getAttribute('data-element-id');
const url = this.getAttribute('data-url');
const issueIDs = $('.issue-checkbox:checked').map((_, el) => {
return el.getAttribute('data-issue-id');
}).get().join(',');
if (elementId === '0' && url.slice(-9) === '/assignee') {
let issueIDs = [];
for (const el of document.querySelectorAll('.issue-checkbox:checked')) {
issueIDs.push(el.getAttribute('data-issue-id'));
}
issueIDs = issueIDs.join(',');
if (!issueIDs) return;
// for assignee
if (elementId === '0' && url.endsWith('/assignee')) {
elementId = '';
action = 'clear';
}
// for toggle
if (action === 'toggle' && e.altKey) {
action = 'toggle-alt';
}
// for delete
if (action === 'delete') {
const confirmText = e.target.getAttribute('data-action-delete-confirm');
if (!await confirmModal({content: confirmText, buttonColor: 'orange'})) {
return;
}
}
updateIssuesMeta(
url,
action,