MediaWiki:Gadget-QuickBlock.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 {
CdxCheckbox,
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 blockDialogOpen = ref(false);
const unblockDialogOpen = ref(false);
const dialogTargetUser = ref('');
const blockReasonSelection = ref(null);
const blockReasonCustom = ref('');
const blockDuration = ref('2 weeks');
const blockDurationCustom = ref('');
const unblockReason = ref('');
const actionMessage = ref('');
const actionMessageType = ref('');
const nocreate = ref(true);
const allowusertalk = ref(true);
const autoblock = ref(true);
const primaryActionBlock = {
label: 'Block',
actionType: 'progressive'
};
const primaryActionUnblock = {
label: 'Unblock',
actionType: 'progressive'
};
const defaultAction = {
label: 'Cancel'
};
function openBlockDialog(target) {
dialogTargetUser.value = target;
blockReasonSelection.value = null;
blockReasonCustom.value = '';
blockDuration.value = '2 weeks';
blockDurationCustom.value = '';
actionMessage.value = '';
blockDialogOpen.value = true;
setTimeout(() => document.querySelector('#quick-block-reason .cdx-select-vue__handle').focus(), 0);
}
function openUnblockDialog(target) {
dialogTargetUser.value = target;
unblockReason.value = '';
actionMessage.value = '';
unblockDialogOpen.value = true;
setTimeout(() => document.querySelector('#quick-unblock-reason input').focus(), 0);
}
function onSubmit(action) {
const reason = action === 'block'
? [blockReasonSelection.value, blockReasonCustom.value].filter(Boolean).join(': ')
: unblockReason.value;
const params = {
action,
user: dialogTargetUser.value,
reason,
tags: ['quickblock'],
bot: true
};
if (action === 'block') {
params.expiry = blockDuration.value === 'custom' ?
blockDurationCustom.value :
blockDuration.value;
params.reblock = true;
params.nocreate = nocreate.value;
params.allowusertalk = allowusertalk.value;
params.autoblock = autoblock.value;
}
api.postWithToken('csrf', params).done(() => {
actionMessageType.value = 'success';
actionMessage.value = 'Success!';
}).fail(code => {
actionMessageType.value = 'error';
actionMessage.value = `Failed to ${action} ${dialogTargetUser.value}: ${code}`;
});
}
function keydownHandler(event, action) {
if (event.key === 'Enter') {
onSubmit(action);
}
}
// <nowiki>
const blockDialog = createMwApp({
name: 'quick-block',
components: {CdxCheckbox, CdxDialog, CdxField, CdxMessage, CdxSelect, CdxTextInput},
template: `
<cdx-dialog
v-model:open="blockDialogOpen"
:title="'Blocking ' + dialogTargetUser"
:primary-action="primaryActionBlock"
:default-action="defaultAction"
@primary="onSubmit('block')"
@default="blockDialogOpen = false"
:use-close-button="true"
>
<cdx-field id="quick-block-reason">
<cdx-select
v-model:selected="blockReasonSelection"
:menu-items="blockReasons"
default-label="Select a reason..."
/>
<template #label>Block reason</template>
</cdx-field>
<cdx-field>
<cdx-text-input v-model="blockReasonCustom" @keydown="keydownHandler($event, 'block')" />
<template #label>Custom reason</template>
</cdx-field>
<cdx-field>
<cdx-select
v-model:selected="blockDuration"
:menu-items="blockDurations"
default-label="Select a duration..."
/>
<cdx-text-input
v-model="blockDurationCustom"
v-if="blockDuration == 'custom'"
@keydown="keydownHandler($event, 'block')"
/>
<template #label>Block duration</template>
</cdx-field>
<cdx-field>
<cdx-checkbox v-model="nocreate">Prevent account creation</cdx-checkbox>
<cdx-checkbox v-model="allowusertalk">Allow editing their own talk page</cdx-checkbox>
<cdx-checkbox v-model="autoblock">Automatically block user's IP addresses for 1 day</cdx-checkbox>
<template #label>Block details</template>
</cdx-field>
<cdx-message
v-if="actionMessage"
:type="actionMessageType"
:fade-in="true"
:auto-dismiss="true"
:display-time="5000"
@auto-dismissed="blockDialogOpen = false"
>{{ actionMessage }}</cdx-message>
</cdx-dialog>
`,
setup() {
return {
actionMessage,
actionMessageType,
blockDialogOpen,
dialogTargetUser,
blockReasonSelection,
blockReasonCustom,
blockDuration,
blockDurationCustom,
blockDurations: computed(() => [
...mw.msg('ipboptions')
.split(',')
.map(option => option.split(':'))
.map(([label, value]) => ({label, value})),
{
label: 'Custom duration',
value: 'custom'
}
]
),
blockReasons: parseReasonDropdown('ipbreason-dropdown'),
primaryActionBlock,
defaultAction,
nocreate,
allowusertalk,
autoblock,
onSubmit,
keydownHandler
};
}
});
const unblockDialog = createMwApp({
name: 'quick-unblock',
components: {CdxDialog, CdxField, CdxMessage, CdxTextInput},
template: `
<cdx-dialog
v-model:open="unblockDialogOpen"
:title="'Unblocking ' + dialogTargetUser"
:primary-action="primaryActionUnblock"
:default-action="defaultAction"
@primary="onSubmit('unblock')"
@default="unblockDialogOpen = false"
:use-close-button="true"
>
<cdx-field id="quick-unblock-reason">
<cdx-text-input v-model="unblockReason" @keydown="keydownHandler($event, 'unblock')" />
<template #label>Reason</template>
</cdx-field>
<cdx-message
v-if="actionMessage"
:type="actionMessageType"
:fade-in="true"
:auto-dismiss="true"
:display-time="5000"
@auto-dismissed="unblockDialogOpen = false"
>{{ actionMessage }}</cdx-message>
</cdx-dialog>
`,
setup() {
return {
actionMessage,
actionMessageType,
unblockDialogOpen,
dialogTargetUser,
unblockReason,
primaryActionUnblock,
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;
}
// TODO: Fetch localized special page aliases.
const blockTarget = getSpecialPageTarget(url, pageTitle, ['block']);
if (blockTarget) {
event.preventDefault();
openBlockDialog(blockTarget);
return;
}
const unblockTarget = getSpecialPageTarget(url, pageTitle, ['unblock']);
if (unblockTarget) {
event.preventDefault();
openUnblockDialog(unblockTarget);
}
});
const blockRoot = document.createElement('div');
document.body.appendChild(blockRoot);
blockDialog.mount(blockRoot);
const unblockRoot = document.createElement('div');
document.body.appendChild(unblockRoot);
unblockDialog.mount(unblockRoot);