MediaWiki:Gadget-QuickDelete.js
Note : après avoir publié vos modifications, il se peut que vous deviez forcer le rechargement complet du cache de votre navigateur pour voir les changements.
- Firefox / Safari : maintenez la touche Maj (Shift) en cliquant sur le bouton Actualiser ou appuyez sur Ctrl + F5 ou Ctrl + R (⌘ + R sur un Mac).
- Google Chrome : appuyez sur Ctrl + Maj + R (⌘ + Shift + R sur un Mac).
- Edge : maintenez la touche Ctrl en cliquant sur le bouton Actualiser ou pressez Ctrl + F5.
/* TODO: MediaWiki 1.45 allows loading .vue files in Gadgets (T340460) */
const {computed, createMwApp, ref} = mw.loader.require('vue');
const {
CdxDialog,
CdxField,
CdxMessage,
CdxSelect,
CdxTextInput
} = mw.loader.require('@wikimedia/codex');
const {
parseReasonDropdown,
getTitleFromUrl,
getSpecialPageTarget
} = mw.loader.require('ext.gadget.Util');
const api = new mw.Api();
const deleteDialogOpen = ref(false);
const undeleteDialogOpen = ref(false);
const dialogPageTitle = ref('');
const dialogIsFile = ref(false);
const dialogPageRev = ref(null);
const deleteReasonSelection = ref(null);
const deleteReasonCustom = ref('');
const undeleteReason = ref('');
const actionMessage = ref('');
const actionMessageType = ref('');
const primaryActionDelete = {
label: 'Delete',
actionType: 'progressive'
};
const primaryActionUndelete = {
label: 'Delete',
actionType: 'progressive'
};
const defaultAction = {
label: 'Cancel'
};
function isDelete(url) {
return url.searchParams.get('action') === 'delete';
}
function openDeleteDialog(title) {
deleteReasonCustom.value = '';
actionMessage.value = '';
dialogPageTitle.value = title.getPrefixedText();
dialogIsFile.value = title.namespace === 6;
deleteDialogOpen.value = true;
setTimeout(() => document.querySelector('#quick-delete-reason .cdx-select-vue__handle').focus(), 0);
}
function openUndeleteDialog(title) {
undeleteReason.value = '';
actionMessage.value = '';
dialogPageTitle.value = title;
undeleteDialogOpen.value = true;
setTimeout(() => document.querySelector('#quick-undelete-reason input').focus(), 0);
}
function onSubmit(action) {
const reason = (action === 'delete') ?
[deleteReasonSelection.value, deleteReasonCustom.value].filter(Boolean).join(': ') :
undeleteReason.value;
api.postWithToken('csrf', {
action,
title: dialogPageTitle.value,
reason,
oldimage: dialogPageRev.value,
tags: ['quickdelete'],
bot: true
}).done(() => {
actionMessageType.value = 'success';
actionMessage.value = 'Success!';
}).fail(code => {
actionMessageType.value = 'error';
actionMessage.value = 'Failed to ' + action + ' ' + dialogPageTitle.value + ': ' + code;
});
}
function keydownHandler(event, action) {
if (event.which === 13 || event.which === 11) {
onSubmit(action);
}
}
// <nowiki>
const deleteDialog = createMwApp({
name: 'quick-delete',
components: {
CdxDialog,
CdxField,
CdxMessage,
CdxSelect,
CdxTextInput
},
template: `
<cdx-dialog
v-model:open="deleteDialogOpen"
:title="'Deleting ' + (dialogPageRev ? ('revision of ' + dialogPageRev + ' on ') : '') + dialogPageTitle"
:primary-action="primaryActionDelete"
:default-action="defaultAction"
@primary="onSubmit('delete')"
@default="deleteDialogOpen = false"
:use-close-button="true"
>
<cdx-field id="quick-delete-reason">
<cdx-select
v-model:selected="deleteReasonSelection"
:menu-items="deletionReasons"
default-label="Select a reason..."
/>
<template #label>Deletion reason</template>
</cdx-field>
<cdx-field>
<cdx-text-input v-model="deleteReasonCustom" @keydown="keydownHandler($event, 'delete')" />
<template #label>Custom reason</template>
<template #description>Add a reason instead, or in addition to, the reason selected above.</template>
</cdx-field>
<cdx-message
v-if="actionMessage"
:type="actionMessageType"
:fade-in="true"
:auto-dismiss="true"
:display-time="5000"
@auto-dismissed="deleteDialogOpen = false"
>{{ actionMessage }}</cdx-message>
</cdx-dialog>
`,
setup() {
return {
actionMessage,
actionMessageType,
deleteDialogOpen,
dialogPageTitle,
dialogPageRev,
deleteReasonSelection,
deletionReasons: computed(() => parseReasonDropdown(
dialogIsFile.value === 6 ?
'filedelete-reason-dropdown' :
'deletereason-dropdown'
)),
deleteReasonCustom,
primaryActionDelete,
defaultAction,
onSubmit,
keydownHandler
};
}
});
const undeleteDialog = createMwApp({
name: 'quick-undelete',
components: {
CdxDialog,
CdxField,
CdxMessage,
CdxTextInput
},
template: `
<cdx-dialog
v-model:open="undeleteDialogOpen"
:title="'Undeleting ' + dialogPageTitle"
:primary-action="primaryActionUndelete"
:default-action="defaultAction"
@primary="onSubmit('undelete')"
@default="undeleteDialogOpen = false"
:use-close-button="true"
>
<p>To undelete specific revisions, visit <a :href="undeletePageLink">the undeletion page</a>.</p>
<cdx-field id="quick-undelete-reason">
<cdx-text-input v-model="undeleteReason" @keydown="keydownHandler($event, 'undelete')" />
<template #label>Custom reason</template>
<template #description>Add a reason instead, or in addition to, the reason selected above.</template>
</cdx-field>
<cdx-message
v-if="actionMessage"
:type="actionMessageType"
:fade-in="true"
:auto-dismiss="true"
:display-time="5000"
@auto-dismissed="undeleteDialogOpen = false"
>{{ actionMessage }}</cdx-message>
</cdx-dialog>
`,
setup() {
return {
actionMessage,
actionMessageType,
undeleteDialogOpen,
undeletePageLink: computed(() => mw.util.getUrl('Special:Undelete/' + dialogPageTitle.value)),
dialogPageTitle,
undeleteReason,
primaryActionUndelete,
defaultAction,
onSubmit,
keydownHandler
};
}
});
// </nowiki>
document.addEventListener('click', event => {
const target = event.target.closest('a[href]');
if (
!target ||
event.ctrlKey ||
event.shiftKey ||
event.metaKey ||
event.altKey
) {
return;
}
let url;
try {
url = new URL(target.href);
} catch (error) {
return;
}
const pageTitle = getTitleFromUrl(url);
if (!pageTitle) {
return;
}
dialogPageRev.value = null;
if (isDelete(url)) {
event.preventDefault();
dialogPageRev.value = url.searchParams.get('oldimage');
openDeleteDialog(pageTitle);
} else {
// TODO: Fetch international aliases for Special:Undelete.
const undeleteTarget = getSpecialPageTarget(url, pageTitle, ['undelete']);
if (undeleteTarget) {
event.preventDefault();
openUndeleteDialog(undeleteTarget);
}
}
});
const deleteRoot = document.createElement('div');
document.body.appendChild(deleteRoot);
deleteDialog.mount(deleteRoot);
const undeleteRoot = document.createElement('div');
document.body.appendChild(undeleteRoot);
undeleteDialog.mount(undeleteRoot);