Aller au contenu

MediaWiki:Gadget-QuickDelete.js

De Wiki Undertale FR

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);