MediaWiki:Gadget-GoodAndFeaturedClosure-main.vue
Appearance
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.
<template>
<cdx-dialog
v-model:open="showDialog"
title="Підбиття підсумку"
close-button-label="Закрити"
:primary-action="notRun ? primaryAction : null"
:default-action="notRun ? defaultAction : null"
style="min-width:700px"
@primary="onPrimaryAction"
@default="onDefaultAction"
>
<template v-if="notRun">
<cdx-radio
v-for="radio in radios"
:key="'radio-' + radio.value"
v-model="radioValue"
name="radio-group-descriptions"
:input-value="radio.value"
>
{{ radio.label }}
</cdx-radio>
<label for="gfc-reason">
Причина (вікірозміткою, підпис згенерується автоматично):
</label>
<cdx-text-area
autosize
id="gfc-reason"
v-model="reasonText"
></cdx-text-area>
<div v-if="prev"
class="gfc-preview"
v-html="previewHtml">
</div>
</template>
<template v-else>
<p style="font-weight:600">
Будь ласка, зачекайте...
</p>
<p style="font-size: 120%; font-weight: bold;">{{ message }}</p>
<cdx-progress-bar aria-label="Запуск скрипта"></cdx-progress-bar>
</template>
</cdx-dialog>
</template>
<script>
const { CdxButton, CdxDialog, CdxTextArea, CdxRadio, CdxProgressBar } = require( '@wikimedia/codex' );
const currentPage = mw.config.get("wgPageName").replace(/_/g," ");
const date = new Date();
var month = date.getMonth() + 1;
if (month.toString().length == 1)
month = '0' + month;
const year = date.getFullYear();
var day = date.getDate();
if (day.toString().length == 1)
day = '0' + day;
module.exports = {
data: function() {
return {
showDialog: false,
notRun: true,
prev: false,
reasonText: "",
previewHtml: "",
message: null,
radios: [
{
label: 'Статус надано',
value: 'granted'
},
{
label: 'Статус не надано',
value: 'denied'
}],
radioValue: null,
primaryAction: { label: 'Зберегти' },
defaultAction: { label: 'Попередній перегляд' },
nominator: ""
};
},
components: {
CdxButton,
CdxDialog,
CdxTextArea,
CdxRadio,
CdxProgressBar
},
methods: {
openDialog (title, section) {
this.showDialog = true;
this.pageName = title;
this.sectionId =section;
},
closeDialog () {
this.showDialog = false;
},
onPrimaryAction () {
this.notRun = false;
this.archiveSubpage()
},
onDefaultAction () {
this.preview(this.reasonText)
},
preview (reason) {
var param = {
action: 'parse',
format: 'json',
prop: 'text',
text: reason
};
this.prev = true;
new mw.Api().get(param).done(function(data) {
$('.gfc-preview').html(data.parse.text['*']);
});
},
ukMonth () {
var month_name = "";
switch (month) {
case "01":
month_name = "січня";
break;
case "02":
month_name = "лютого";
break;
case "03":
month_name = "березня";
break;
case "04":
month_name = "квітня";
break;
case "05":
month_name = "травня";
break;
case "06":
month_name = "червня";
break;
case "07":
month_name = "липня";
break;
case "08":
month_name = "серпня";
break;
case "09":
month_name = "вересня";
break;
case 10:
month_name = "жовтня";
break;
case 11:
month_name = "листопада";
break;
case 12:
month_name = "грудня";
break;
}
return month_name
},
variable_names () {
var gfc = this;
switch (currentPage) {
case 'Вікіпедія:Кандидати в добрі статті':
return {
stat_template: 'Шаблон:Статистика добрих статей',
status_template: 'Добра стаття',
nomination_template: 'Кандидат у добрі статті',
talk_template: gfc.radioValue == 'granted' ? {
type: "добра",
status: "статус доброї надано"
} : {
type: "кандидат у добрі",
status: "статус доброї не надано"
},
genitive: 'доброї',
level: 'ДС',
badge: 'Q17437798',
authors_page: 'Вікіпедія:Добрі статті/Автори добрих статей'
};
break;
case 'Вікіпедія:Кандидати у вибрані статті':
return {
stat_template: 'Шаблон:Статистика вибраних статей',
status_template: 'Вибрана стаття',
nomination_template: 'Кандидат у вибрані статті',
talk_template: gfc.radioValue == 'granted' ? {
type: "вибрана",
status: "статус вибраної надано"
} : {
type: "кандидат у вибрані",
status: "статус вибраної не надано"
},
genitive: 'вибраної',
level: 'ВС',
badge: 'Q17437796',
authors_page: 'Вікіпедія:Добрі статті/Автори вибраних статей'
};
case 'Вікіпедія:Кандидати у вибрані списки':
return {
stat_template: 'Шаблон:Статистика вибраних статей',
status_template: 'Вибрана стаття',
nomination_template: 'Кандидат у вибрані статті',
talk_template: gfc.radioValue == 'granted' ? {
type: "вибрана",
status: "статус вибраної надано"
} : {
type: "кандидат у вибрані",
status: "статус вибраної не надано"
},
genitive: 'вибраного списку',
level: 'ВСП',
badge: 'Q17506997',
authors_page: 'Вікіпедія:Добрі статті/Автори вибраних списків'
};
break;
case 'Вікіпедія:Кандидати у вибрані портали':
return {
stat_template: 'Шаблон:Статистика вибраних статей',
status_template: 'Вибрана стаття',
nomination_template: 'Кандидат у вибрані статті',
talk_template: gfc.radioValue == 'granted' ? {
type: "вибрана",
status: "статус вибраної надано"
} : {
type: "кандидат у вибрані",
status: "статус вибраної не надано"
},
level: 'ВСП',
badge: 'Q17580674'
};
break;
}
},
sortEntries (arr) {
return arr.sort((a, b) => {
if (b.number !== a.number) {
return b.number - a.number;
}
return a.author.localeCompare(b.author, 'und', {
sensitivity: 'base'
});
});
},
incrementAuthor (arr, targetAuthor) {
return this.sortEntries(
arr.map(e =>
e.author === targetAuthor
? { ...e, number: e.number + 1 }
: e
)
);
},
archiveSubpage () {
var gfc = this;
this.wait("Переноситься тема до підсторінки архіву")
var params = {
action: 'query',
prop: 'revisions',
titles: currentPage,
rvprop: 'content',
rvslots: 'main',
rvsection: this.sectionId,
formatversion: '2',
format: 'json'
}
new mw.Api().get( params ).done( ( data ) => {
var topic = data.query.pages[0].revisions[0].slots.main["content"];
gfc.nominator = topic.match(/Взірцеві статті:Номінація.*?\[\[Користувач:(.*?)\|/s)[1]
var params2 = {
action: 'edit',
title: currentPage + '/Архів/' + year + '-' + month + '-' + day,
appendtext: "\n" + topic + "\n=== Підсумок ===\n" + gfc.reasonText + "--~~~~",
format: 'json'
}
new mw.Api().postWithEditToken(params2).done(() => {
new mw.Api().edit(currentPage, (revision) => {
var content = revision.content;
content = content.replace(RegExp("(Останній архів: \\[\\[" + mw.util.escapeRegExp(currentPage) + "/Архів/).*?\\]\\]"),"$1" + year + "-" + month + "-" + day + "|" + day + " " + gfc.ukMonth() +" року]]");
return {
text: content.replace("\n" + topic, ""),
summary: "Архівування теми, оновлення посилання на останній архів",
assert: "user"
}
}).then(() => {
gfc.archive()
}).fail((error) => {
gfc.apiError(error)
});
});
});
},
archive() {
var gfc = this;
this.wait("Редагується сторінка архіву")
new mw.Api().edit(currentPage + '/Архів', (revision) => {
var content = revision.content;
if (content.match(RegExp('==\\s*' + year + ' рік\\s*=='))) {
if (content.includes('/Архів/' + year + '-' + month + '-' + day))
content = content.replace(RegExp("(\\|\\[\\["+ mw.util.escapeRegExp(currentPage) +"/Архів/"+ year +"-"+ month +"-"+ day + ".*?\\]\\])(\n\\|-)","s"), "$1, [["+ gfc.pageName +"]]$2");
else
content = content.replace(RegExp("(===\\s*" + year + " рік\\s*===\\n\\|-)"),"$1\n|[["+ currentPage +"/Архів/" + year + "-" + month + "-" + day + "|"+ day + " " + gfc.ukMonth() +"]]\n|[["+ gfc.pageName +"]]\n|-");
}
else {
const previous_year = year - 1;
content = content.replace(RegExp("(===\\s*" + previous_year + " рік\\s*===\\n\\|-)"),"=== " + year + " ===\n|[["+ currentPage +"/Архів/" + year + "-" + month + "-" + day + "|"+ day + " " + gfc.ukMonth() +"]]\n|[["+ gfc.pageName +"]]\n|-\n| colspan=2 |\n$1")
}
return {
text: content,
summary: "Оновлення архіву",
assert: "user"
}
}).then(() => {
gfc.update_statistics()
}).fail((error) => {
gfc.apiError(error)
})
},
update_statistics () {
var gfc = this;
this.wait("Оновлюється статистика");
new mw.Api().edit(gfc.variable_names().stat_template, (revision) => {
var content = revision.content;
switch (currentPage) {
case 'Вікіпедія:Кандидати в добрі статті':
if (content.match(RegExp("\\|Рік\\d+ = " + year))) {
if(gfc.radioValue == 'granted')
content = content.replace(RegExp("(\\|Рік\\d+ = " + year + "\\s+\\|Значення\\d+\\s+=\\s+)(\\d+)(\\s+\\|Мітка\\d+ = )\\d+", "g"), (match, g1, g2, g3) => g1 + (Number(g2)+1) + g3 + (Number(g2)+1));
else
content = content.replace(RegExp("(загальної кількості.*?\\|Рік\\d+ = " + year + "\\s+\\|Значення\\d+\\s+=\\s+)(\\d+)(\\s+\\|Мітка\\d+ = )\\d+", "s"), (match, g1, g2, g3) => g1 + (Number(g2)+1) + g3 + (Number(g2)+1));
}
else {
if (gfc.radioValue == 'granted')
content = content.replace(RegExp("(\\|Мітка)(\\d+)(\\s=\\s+\\d+)\\*","g"), (match, g1, g2, g3) => g1 + g2 + g3 + "\n|Рік" + (Number(g2)+1) + " = " + year + " |Значення" + (Number(g2)+1) + " = 1 |Мітка" + (Number(g2)+1) + " = 1*");
else
content = content.replace(RegExp("(загальної кількості.*?\\|Мітка)(\\d+)(\\s=\\s+\\d+)\\*(.*?)\\*","s"), (match, g1, g2, g3, g4) => g1 + g2 + g3 + "\n|Рік" + (Number(g2)+1) + " = " + year + " |Значення" + (Number(g2)+1) + " = 0 |Мітка" + (Number(g2)+1) + " = 0*" + g4 + "\n|Рік" + (Number(g2)+1) + " = " + year + " |Значення" + (Number(g2)+1) + " = 1 |Мітка" + (Number(g2)+1) + " = 1*");
}
break;
case 'Вікіпедія:Кандидати у вибрані статті':
return 'Статистика вибраних статей';
break;
case 'Вікіпедія:Кандидати у вибрані списки':
return 'Статистика вибраних списків';
break;
case 'Вікіпедія:Кандидати у вибрані списки':
return 'Статистика вибраних списків';
break;
}
return {
text: content,
summary: "Оновлення статистики",
assert: "user"
}
}).then(() => {
gfc.change_status()
}).fail((error) => {
gfc.apiError(error)
})
},
change_status () {
var gfc = this;
this.wait("Редагується номінована сторінка");
new mw.Api().edit(gfc.pageName, (revision) => {
var content = revision.content;
content = content.replace(RegExp("{{" + gfc.variable_names().nomination_template + "}}\\s*"),"")
if (content.includes("[[Категорія:"))
content = content.replace(/\s*(\[\[Категорія:)/,"\n{{"+ gfc.variable_names().status_template +"}}\n\n$1");
else
content = content + "\n{{" + gfc.variable_names().status_template + "}}";
return {
text: content,
summary: "Оновлення статусу сторінки",
assert: "user"
}
}).then(() => {
gfc.add_talk_template()
}).fail((error) => {
gfc.apiError(error);
});
},
add_talk_template () {
var gfc = this;
this.wait("Редагується сторінка обговорення статті");
var content = '';
var params = {
action: 'query',
titles: 'talk:' + this.pageName,
prop: 'revisions',
rvprop: 'content',
rvslots: 'main',
format: 'json'
}
new mw.Api().get(params).done((data) => {
if (Object.keys(data.query.pages)[0] == -1) {
content = "{{Повідомлення ВЗВ|" + gfc.variable_names().talk_template.type + "|\n {{Повідомлення ВЗВ/Подія|" + gfc.variable_names().talk_template.status + "|" + day + " " + gfc.ukMonth() + " " + year + " року|" + currentPage + '/Архів/' + year + '-' + month + '-' + day + "}}\n}}";
new mw.Api().create("talk:" + this.pageName, {summary: "Створення сторінки обговорення" }, content).then(() => {
gfc.update_level(content);
}).fail((error) => {
gfc.apiError(error)
});
}
else {
content = data.query.pages[Object.keys(data.query.pages)[0]].revisions[0].slots.main["*"];
new mw.Api().edit("talk:" + this.pageName, (revision) => {
if (content.match(/{{Повідомлення ВЗВ/i))
content = content.replace(/({{Повідомлення ВЗВ\|)(.*?)(\|.*?)(\n}}\n)/s, '$1' + gfc.variable_names().talk_template.type + '$3{{Повідомлення ВЗВ/Подія|' + gfc.variable_names().talk_template.status + '|' + day + ' ' + gfc.ukMonth() + ' ' + year + ' року|' + currentPage + '/Архів/' + year + '-' + month + '-' + day + '}}$4')
else
content = '{{Повідомлення ВЗВ|' + gfc.variable_names().talk_template.type + '|\n {{Повідомлення ВЗВ/Подія|' + gfc.variable_names().talk_template.status + '|' + day + ' ' + gfc.ukMonth() + ' ' + year + ' року|' + currentPage + '/Архів/' + year + '-' + month + '-' + day + '}}\n}}\n' + content;
return {
text: content,
summary: "Оновлюються шаблони на сторінці обговорення статті",
assert: "user"
}
}).then(() => {
gfc.update_level(content)
}).fail((error) => {
gfc.apiError(error);
});
}
});
},
update_level (content) {
var gfc = this;
if (content.match(/{{(Стаття )?(Вікі)?(проєкт)у?/gi))
new mw.Api().edit("talk:" + this.pageName, (revision) => {
var wikitext = revision.content.replace(/({{(Стаття )?(Вікі)?(проєкт)у?.*?\|рівень=\s*)..I?/gi, "$1" + gfc.variable_names.level);
return {
text: wikitext,
summary: "",
assert: 'user'
}
}).then(() => {
//gfc.update_wikidata()
gfc.stabilize()
})
else
//gfc.update_wikidata()
gfc.stabilize()
},
update_wikidata () {
var gfc = this;
new mw.ForeignApi('https://www.wikidata.org/w/api.php').postWithToken('csrf', {
action: 'wbsetsitelink',
site: mw.config.get("wgWikiID"),
linksite: mw.config.get("wgWikiID"),
title: gfc.pageName,
badges: gfc.variable_names().badge,
summary: 'assign badge via API',
assert: 'user',
format: 'json'
}).then(() => {
gfc.stabilize()
}).fail((error) => {
if (error == 'no-such-entity-link')
console.log('skip');
});
},
stabilize () {
var gfc = this;
if (mw.config.get("wgUserGroups").includes("sysop")) {
this.wait("Стабілізовується сторінка");
new mw.Api().postWithEditToken({
action: 'stabilize',
title: gfc.pageName,
reason: 'Стабілізація доброї статті',
default: 'stable'
}).then(() => {
gfc.update_author()
}).fail((error) => {
gfc.apiError(error)
});
}
else {
this.wait("Подається запит на стабілізацію сторінки");
new mw.Api().edit('Вікіпедія:Захист сторінок', (revision) => {
return {
text: revision.content.replace("↓↓↓-->", "↓↓↓-->\n== Стабілізація статті " + gfc.pageName + " ==\nПрошу стабілізувати статтю [[" + gfc.pageName + "]] через отримання статусу " + gfc.variable_names().genitive + ".--~~~~"),
summary: "",
assert: "user"
}
}).then(() => {
gfc.update_author()
}).fail((error) => {
gfc.apiError(error)
});
}
},
update_author () {
var gfc = this;
gfc.wait("Оновлюється статистика авторів добрих статей")
new mw.Api().edit(gfc.variable_names().authors_page, (revision) => {
var content = revision.content;
var authors_arr, sorted_arr = [];
if (content.includes(gfc.nominator)) {
authors_arr = [...content.matchAll(/\[\[Користувач:(.*?)\|.*? \|\|\s*(\d+)/g)].map(m => ({
author: m[1],
number: Number(m[2])
}));
var prev_author_index = authors_arr.findIndex(e => e.author === gfc.nominator);
sorted_arr = gfc.incrementAuthor(authors_arr, gfc.nominator);
var author_index = sorted_arr.findIndex(e => e.author === gfc.nominator);
content = content.replace(RegExp("(" + mw.util.escapeRegExp(gfc.nominator) + ".*?\\|\\|)\\s*(\\d+)(.*?)(\\n\\|[-}])", "s"), (match, g1, g2, g3, g4) => g1 + " " + (Number(g2)+1) + g3 + ", [[" + gfc.pageName + "]]" + g4);
if (author_index != prev_author_index) {
var prev_entity = author_index == 0 ? sorted_arr[author_index] : sorted_arr[author_index-1]
var author_entity = sorted_arr[author_index]
var after_entity = author_index == sorted_arr.length -1 ? sorted_arr[author_index] : sorted_arr[author_index+1];
author_raw = content.match(RegExp("(\\|\\s*\\[\\[Користувач:" + mw.util.escapeRegExp(gfc.nominator) + "\n\\|.*?\n)(\\|)", "s"))[1];
if ((author_entity.number < 5 && prev_entity.number >= 5) || (author_entity.number < 10 && prev_entity.number >= 10) || (author_entity.number < 20 && prev_entity.number >= 20) || (sorted_arr[0].author == gfc.nominator)) {
content = content.replace(author_raw + "|-\n", "");
content = content.replace(RegExp("(\\|\\s*\\[\\[Користувач:" + mw.util.escapeRegExp(after_entity.author) + ")"), author_raw + "$1");
}
else if ((after_entity.number < 5 && author_entity.number >= 5) || (after_entity.number < 10 && author_entity.number >= 10) || (after_entity.number < 20 && author_entity.number >= 20)) {
content = content.replace(author_raw + "|-\n", "");
content = content.replace(RegExp("(\\|\\s*\\[\\[Користувач:" + mw.util.escapeRegExp(prev_entity.author) + ".*?)(\\|})", "s"), "$1" + author_raw + "$2");
}
else {
content = content.replace("|-\n" + author_raw, "");
content = content.replace(RegExp("(\\|\\s*\\[\\[Користувач:" + mw.util.escapeRegExp(prev_entity.author), "s"), author_raw + "|-\n$1");
}
}
}
else {
authors_arr = [...content.matchAll(/\|\s*\[\[Користувач:(.*?)\|\D+?\n/g)].map(m => ({
author: m[1],
number: 1
}));
authors_arr.push({
author: gfc.nominator,
number: 0
});
sorted_arr = gfc.incrementAuthor(authors_arr, gfc.nominator)
var author_index = sorted_arr.findIndex(e => e.author === gfc.nominator)
if (author_index == 0)
content = content.replace(RegExp("! Автор\\n! Стаття\\n\\|-"), "$&\n| [[Користувач:" + gfc.nominator + "|" + gfc.nominator + "]]\n| [[" + gfc.pageName + "]]\n");
else {
content = content.replace(RegExp("(\\| \\[\\[Користувач:" + mw.util.escapeRegExp(sorted_arr[author_index-1].author) + ".*?)(\\|-)", "s"), "$1|-\n| [[Користувач:" + gfc.nominator + "|" + gfc.nominator + "]]\n| [[" + gfc.pageName + "]]\n$2");
}
}
return {
text: content,
summary: "Оновлення статистики авторів",
assert: "user"
}
}).then(() => {
gfc.success()
}).fail((error) => {
gfc.apiError(error);
})
},
success() {
this.wait('Перезавантаження сторінки');
setTimeout(() => {
this.closeDialog ();
location.reload()
}, 1000);
},
wait(message) {
this.message = message;
},
apiError (code) {
console.log(code);
}
},
mounted() {
$('.mw-heading2').each((index, element) => {
if (index+1 < $('.mw-heading2').length-1) {
const $heading = $( element );
const title = $( element ).find( 'h2 a' ).attr( 'title' );
const span = document.createElement( 'span' );
const link = document.createElement( 'a' );
span.className = 'mw-editsection mw-editsection-summary';
link.href = '#';
link.innerHTML = '[<span>Підбити підсумок</span>]';
link.addEventListener( 'click', ( e ) => {
e.preventDefault();
this.openDialog( title, index+1 );
} );
$heading.find( '.mw-editsection' ).after(span);
$heading.find( '.mw-editsection-summary' ).append(link)
}
});
},
unmounted() {
//this.dialogTrigger.removeEventListener( this.openDialog );
}
};
</script>
<style>
.cdx-dialog__header__title {
text-align: center;
}
</style>