Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5.
// <nowiki>

if (typeof createCategories === 'undefined') {
    var createCategories = {};
}
createCategories.api = new mw.Api();

mw.loader.using('@wikimedia/codex').then(function(require) {
    const Vue = require('vue');
    const Codex = require('@wikimedia/codex');

    const mountPoint = document.body.appendChild(document.createElement('div'));
    
    Vue.createMwApp({
        data: function() {
            return {
                year: '',
                categoryType: 'date',
                previewContent: '',
                selectedCategories: [],
                showMessage: false,
                messageType: '',
                messageContent: '',
                showProgress: false,
                showConfirmDialog: false,
                showSuccessDialog: false,
                monthOptions: [
                    { value: 1, label: 'জানুয়ারি' },
                    { value: 2, label: 'ফেব্রুয়ারি' },
                    { value: 3, label: 'মার্চ' },
                    { value: 4, label: 'এপ্রিল' },
                    { value: 5, label: 'মে' },
                    { value: 6, label: 'জুন' },
                    { value: 7, label: 'জুলাই' },
                    { value: 8, label: 'আগস্ট' },
                    { value: 9, label: 'সেপ্টেম্বর' },
                    { value: 10, label: 'অক্টোবর' },
                    { value: 11, label: 'নভেম্বর' },
                    { value: 12, label: 'ডিসেম্বর' }
                ],
                categoryTypeOptions: [
                    { label: 'তারিখ বিষয়শ্রেণী', value: 'date' },
                    { label: 'মাস বিষয়শ্রেণী', value: 'month' }
                ],
                expanded: false,
                chips: [],
                selectedValue: [],
                createdPages: 0,
                updatedPages: 0,
                totalTime: 0
            };
        },
        computed: {
            isFormValid: function() {
                return this.year && this.selectedValue.length > 0;
            },
            activeDescendant: function() {
                const highlightedItem = this.$refs.menu && this.$refs.menu.getHighlightedMenuItem();
                return highlightedItem ? highlightedItem.id : undefined;
            },
            menuId: function() {
                return 'month-menu';
            }
        },
        methods: {
            showConfirmationDialog: function() {
                if (this.isFormValid) {
                    this.showConfirmDialog = true;
                } else {
                    this.showWarningMessage('অনুগ্রহ করে বছর এবং অন্তত একটি মাস নির্বাচন করুন।');
                }
            },
            generatePreview: function() {
                this.resetMessageState();
                if (this.isFormValid) {
                    this.showProgress = true;
                    let previewPromises;
                    if (this.categoryType === 'date') {
                        this.previewContent = '{{Wn/bn/তারিখশ্রেণী}}';
                        previewPromises = this.getPreviewDateCategories(this.year, this.selectedValue);
                    } else {
                        this.previewContent = '{{Wn/bn/মাসশ্রেণী}}';
                        previewPromises = this.getPreviewMonthCategories(this.year, this.selectedValue);
                    }
                    Promise.all(previewPromises)
                        .then((previewItems) => {
                            this.selectedCategories = previewItems.flat().map(item => ({
                                ...item,
                                selected: true
                            }));
                            this.showProgress = false;
                        })
                        .catch((error) => {
                            console.error('Error generating preview:', error);
                            this.showProgress = false;
                            this.showErrorMessage('প্রাকদর্শন তৈরি করার সময় একটি ত্রুটি ঘটেছে৷');
                        });
                } else {
                    this.showWarningMessage('অনুগ্রহ করে বছর এবং অন্তত একটি মাস নির্বাচন করুন।');
                }
            },
            createCategories: function() {
                this.resetMessageState();
                this.showConfirmDialog = false;
                this.showProgress = true;

                const selectedCategories = this.selectedCategories.filter(category => category.selected);
                
                if (selectedCategories.length === 0) {
                    this.showWarningMessage('অনুগ্রহ করে অন্তত একটি বিষয়শ্রেণী নির্বাচন করুন।');
                    this.showProgress = false;
                    return;
                }

                this.createdPages = 0;
                this.updatedPages = 0;
                const startTime = Date.now();

                // Sort categories to ensure they are created serially
                selectedCategories.sort((a, b) => {
                    const aMatch = a.title.match(/(\d+)/);
                    const bMatch = b.title.match(/(\d+)/);
                    return (aMatch && bMatch) ? parseInt(aMatch[1]) - parseInt(bMatch[1]) : 0;
                });

                const createCategoriesSequentially = (categories, index = 0) => {
    if (index >= categories.length) {
        this.totalTime = (Date.now() - startTime) / 1000;
        this.showProgress = false;
        this.showSuccessDialog = true;
        this.showSuccessMessage('বিষয়শ্রেণীগুলো সফলভাবে তৈরি/হালনাগাদ করা হয়েছে।');
        return;
    }

                    const category = categories[index];
    this.checkAndUpdateCategory(category.title, this.previewContent)
        .then((result) => {
            if (result === 'create') this.createdPages++;
            if (result === 'update') this.updatedPages++;
            createCategoriesSequentially(categories, index + 1);
        })
        .catch((error) => {
            console.error('Error creating/updating category:', error);
            this.showProgress = false;
            this.showErrorMessage('বিষয়শ্রেণী তৈরি/হালনাগাদ করার সময় একটি ত্রুটি ঘটেছে৷');
        });
};

                createCategoriesSequentially(selectedCategories);
            },
            resetForm: function() {
                this.year = '';
                this.selectedValue = [];
                this.chips = [];
                this.categoryType = 'date';
                this.previewContent = '';
                this.selectedCategories = [];
                this.resetMessageState();
            },
            resetMessageState: function() {
                this.showMessage = false;
                this.messageType = '';
                this.messageContent = '';
            },
            showWarningMessage: function(message) {
                this.messageType = 'warning';
                this.messageContent = message;
                this.showMessage = true;
            },
            showErrorMessage: function(message) {
                this.messageType = 'error';
                this.messageContent = message;
                this.showMessage = true;
            },
            showSuccessMessage: function(message) {
                this.messageType = 'success';
                this.messageContent = message;
                this.showMessage = true;
            },
            handleMessageDismiss: function() {
                this.showMessage = false;
            },
            handleSuccessDialogClose: function() {
                this.showSuccessDialog = false;
                this.resetForm();
            },
            handleConfirmDialogCancel: function() {
                this.showConfirmDialog = false;
            },
            getPreviewDateCategories: function(year, months) {
                return months.map(month => {
                    const daysInMonth = new Date(year, month, 0).getDate();
                    return Array.from({length: daysInMonth}, (_, i) => ({
                        title: `Category:Wn/bn/${this.convertToBengaliNumber(i + 1)} ${this.getBengaliMonthName(month)} ${this.convertToBengaliNumber(year)}`
                    }));
                });
            },
            getPreviewMonthCategories: function(year, months) {
                return months.map(month => [{
                    title: `Category:Wn/bn/${this.getBengaliMonthName(month)} ${this.convertToBengaliNumber(year)}`
                }]);
            },
            checkAndUpdateCategory: function(title, content) {
                return createCategories.api.get({
                    action: 'query',
                    format: 'json',
                    prop: 'revisions',
                    titles: title,
                    formatversion: '2',
                    rvprop: 'content',
                    rvslots: '*'
                }).then(data => {
                    const page = data.query.pages[0];
                    const action = page.missing !== undefined ? 'create' : 'update';
                    return this.createOrUpdateCategory(title, content, action);
                });
            },
            createOrUpdateCategory: function(title, content, actionType) {
                const summary = actionType === 'create' 
                    ? '[[User:Asked42/উইকিসংবাদ স্ক্রিপ্ট#QuickCat|QuickCat]] ব্যবহার করে নতুন বিষয়শ্রেণী পৃষ্ঠা তৈরি করা' 
                    : '[[User:Asked42/উইকিসংবাদ স্ক্রিপ্ট#QuickCat|QuickCat]] ব্যবহার করে বিষয়শ্রেণী পৃষ্ঠা হালনাগাদ করা';

                return createCategories.api.postWithToken('csrf', {
                    action: 'edit',
                    title: title,
                    text: content,
                    summary: summary
                }).then(() => actionType);
            },
            convertToBengaliNumber: function(num) {
                return num.toString().replace(/\d/g, d => "০১২৩৪৫৬৭৮৯"[d]);
            },
            getBengaliMonthName: function(month) {
                const monthNames = [
                    "জানুয়ারি", "ফেব্রুয়ারি", "মার্চ", "এপ্রিল", "মে", "জুন",
                    "জুলাই", "আগস্ট", "সেপ্টেম্বর", "অক্টোবর", "নভেম্বর", "ডিসেম্বর"
                ];
                return monthNames[month - 1];
            },
            handleChipChange: function(newChips) {
                this.selectedValue = newChips.map((chip) => chip.value);
            },
            handleSelection: function(newSelected) {
    this.chips = newSelected.map((value) => {
        const selectedMonth = this.monthOptions.find(m => m.value === value);
        return { value, label: selectedMonth.label }; 
    });
},
            onKeydown: function(e) {
                if (e.key === ' ') {
                    return;
                }
                if (this.$refs.menu) {
                    this.$refs.menu.delegateKeyNavigation(e);
                }
            },
            onClick: function() {
                this.expanded = true;
            }
        },
        template: `
            <div style="max-width: 500px; margin: 20px auto; padding: 20px; border: 1px solid #ccc; border-radius: 8px;">
                <cdx-label input-id="cc_year">
                    বছর
                </cdx-label>
                <cdx-text-input id="cc_year" v-model="year" placeholder="বছর লিখুন" style="margin-bottom: 15px;" />

                <cdx-label input-id="cc_months">
                    মাস বাছাই করুন
                </cdx-label>
                <div class="cdx-docs-multiselect-menu" style="margin-bottom: 15px; position: relative;">
                    <cdx-chip-input
                        ref="chipInput"
                        v-model:input-chips="chips"
                        class="cdx-docs-multiselect-menu__input"
                        role="combobox"
                        :aria-expanded="expanded"
                        :aria-controls="menuId"
                        :aria-activedescendant="activeDescendant"
                        remove-button-label="Remove"
                        @click="onClick"
                        @blur="expanded = false"
                        @keydown="onKeydown"
                        @update:input-chips="handleChipChange"
                    ></cdx-chip-input>
                    <cdx-menu
                        :id="menuId"
                        ref="menu"
                        v-model:selected="selectedValue"
                        v-model:expanded="expanded"
                        :menu-items="monthOptions"
                        @update:selected="handleSelection"
                        style="position: absolute; width: 100%; z-index: 1;"
                    ></cdx-menu>
                </div>

                <cdx-label input-id="cc_type">
                    বিষয়শ্রেণীর ধরণ
                </cdx-label>
                <cdx-select id="cc_type" v-model:selected="categoryType" :menu-items="categoryTypeOptions" default-label="বিষয়শ্রেণীর ধরণ নির্বাচন করুন" style="margin-bottom: 15px;" />

                <div style="display: flex; justify-content: space-between;">
                    <cdx-button @click="generatePreview" action="progressive" weight="primary" style="margin-bottom: 15px; margin-right: 5px;">
                        প্রাকদর্শন
                    </cdx-button>
                    <cdx-button @click="resetForm" action="normal" style="margin-bottom: 15px;">
                        নতুন করে শুরু করুন
                    </cdx-button>
                </div>

                <div v-if="selectedCategories.length > 0">
                    <cdx-label input-id="cc_preview">
                        নির্বাচিত বিষয়শ্রেণী পাতাগুলোতে যা যোগ করা হবে:
                    </cdx-label>
                    <cdx-textarea id="cc_preview" v-model="previewContent" aria-label="বিষয়শ্রেণী বিষয়বস্তু" rows="4" style="margin-bottom: 15px;" />

                    <cdx-label>নির্বাচিত বিষয়শ্রেণী</cdx-label>
                    <div style="max-height: 200px; overflow-y: auto; border: 1px solid #ccc; padding: 10px; margin-bottom: 15px;">
                        <cdx-checkbox v-for="category in selectedCategories" :key="category.title" v-model="category.selected" :input-id="category.title">
                            {{ category.title }}
                        </cdx-checkbox>
                    </div>

                    <cdx-button @click="showConfirmationDialog" action="progressive" weight="primary" style="margin-bottom: 15px;">
                        বিষয়শ্রেণী তৈরি করুন
                    </cdx-button>
                </div>

                <cdx-progress-bar v-if="showProgress" inline />
            </div>

            <cdx-dialog v-if="showConfirmDialog" :open="showConfirmDialog" @close="handleConfirmDialogCancel" title="নিশ্চিতকরণ">
                <template #default>
                    <p>আপনি কি নিশ্চিত যে আপনি নির্বাচিত বিষয়শ্রেণীগুলি তৈরি/হালনাগাদ করতে চান?</p>
                </template>
                <template #footer>
                    <cdx-button action="progressive" weight="primary" @click="createCategories" style="margin-right: 10px;">
                        হ্যাঁ, নিশ্চিত
                    </cdx-button>
                    <cdx-button action="normal" @click="handleConfirmDialogCancel">
                        বাতিল
                    </cdx-button>
                </template>
            </cdx-dialog>

            <cdx-dialog v-if="showSuccessDialog" :open="showSuccessDialog" @close="handleSuccessDialogClose" title="সফল অপারেশন">
                <template #default>
                    <p>বিষয়শ্রেণীগুলো সফলভাবে তৈরি/হালনাগাদ করা হয়েছে।</p>
                    <p>মোট তৈরি করা পৃষ্ঠা: {{ createdPages }}</p>
                    <p>মোট হালনাগাদ করা পৃষ্ঠা: {{ updatedPages }}</p>
                    <p>মোট সময় লেগেছে: {{ totalTime.toFixed(2) }} সেকেন্ড</p>
                </template>
                <template #footer>
                    <cdx-button action="progressive" weight="primary" @click="handleSuccessDialogClose">
                        ঠিক আছে
                    </cdx-button>
                </template>
            </cdx-dialog>

            <div v-if="showMessage" style="position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); width: 60%; z-index: 999;">
                <cdx-message
                    :type="messageType"
                    :fade-in="true"
                    :auto-dismiss="messageType === 'success'"
                    :display-time="3000"
                    dismiss-button-label="Close"
                    @dismissed="handleMessageDismiss"
                >
                    {{ messageContent }}
                </cdx-message>
            </div>
        `
    })
    .component('cdx-text-input', Codex.CdxTextInput)
    .component('cdx-textarea', Codex.CdxTextArea)
    .component('cdx-select', Codex.CdxSelect)
    .component('cdx-checkbox', Codex.CdxCheckbox)
    .component('cdx-button', Codex.CdxButton)
    .component('cdx-progress-bar', Codex.CdxProgressBar)
    .component('cdx-message', Codex.CdxMessage)
    .component('cdx-dialog', Codex.CdxDialog)
    .component('cdx-label', Codex.CdxLabel)
    .component('cdx-chip-input', Codex.CdxChipInput)
    .component('cdx-menu', Codex.CdxMenu)
    .mount('#category-create-form');
});

// </nowiki>