Qeyd: Dəyişiklikləri yayımladıqdan sonra etdiyiniz dəyişikliklərin görünməsi üçün brauzerinizin keşinin təmizlənməsi lazım ola bilər.
- Firefox / Safari: Reload düyməsinə basılı tutarkən Shift düyməsinə basın, və ya Ctrl+F5 və ya Ctrl+R (Mac üçün ⌘-R )
- Google Chrome: Ctrl-Shift-R (Mac üçün ⌘-Shift-R)
- Edge: Ctrl düyməsini basılı tutarkən Refresh düyməsinə basın, və ya sadəcə Ctrl+F5.
// [[Xüsusi:BoşSəhifə/İnzibatçılar]] səhifəsində inzibatçıların statistikası
// Müəllif: Toghrul R ()
(function($, mw) {
"use strict";
var conf = mw.config.get(["wgCanonicalSpecialPageName", "wgTitle"]);
if (conf.wgCanonicalSpecialPageName !== "Blankpage" || conf.wgTitle.split("/", 2)[1] !== "İnzibatçılar") return;
var apiUrlBase = "https://xtools.wmcloud.org/api/project/admin_stats/azwiki";
var groupsApiUrl = "https://xtools.wmcloud.org/api/project/admin_groups/azwiki";
var refreshInterval = 60000;
var columnsMap = {
"delete": { label: "Silmə", tooltip: "Səhifə silmə sayı" },
"revision-delete": { label: "V-sil", tooltip: "Səhifə versiyası silmə sayı" },
"restore": { label: "Bərpa", tooltip: "Səhifə bərpası sayı" },
"re-block": { label: "Blok", tooltip: "İstifadəçi bloklama sayı" },
"unblock": { label: "Blok-çıx", tooltip: "Blokdan çıxarma sayı" },
"re-protect": { label: "Mühafizə", tooltip: "Səhifə mühafizəsi sayı" },
"unprotect": { label: "Müh-çıx", tooltip: "Səhifə mühafizəsinin çıxarılma sayı" },
"rights": { label: "Hüquq", tooltip: "İstifadəçi hüquqlarının dəyişdirilməsi sayı" },
"merge": { label: "Birləş", tooltip: "Birləşdirmə əməliyyatları sayı" },
"abusefilter": { label: "Süzgəc", tooltip: "Dəyişiklik süzgəci dəyişdirilməsi sayı" },
"contentmodel": { label: "Kontent", tooltip: "Kontent modelinin təyin edilməsi sayı" }
};
var excludedColumns = ["log-delete", "import"];
var localRights = ["sysop", "bureaucrat", "interface-admin"];
var groupMap = {
"sysop": "inzibatçı",
"interface-admin": "interfeys inzibatçısı",
"bureaucrat": "bürokrat",
"global-sysop": "qlobal inzibatçı",
"steward": "stüard",
"global-deleter": "qlobal silici",
"global-interface-editor": "qlobal interfeys redaktoru",
"staff": "VMF əməkdaşı",
"sysadmin": "sistem inzibatçısı"
};
var showLocalOnly = true;
var currentAggregated = null;
var currentSort = { column: "total", order: "desc" };
var azMonths = ["yanvar", "fevral", "mart", "aprel", "may", "iyun", "iyul", "avqust", "sentyabr", "oktyabr", "noyabr", "dekabr"];
function addDays(date, days) {
var d = new Date(date);
d.setDate(d.getDate() + days);
return d;
}
function formatDate(date) {
var y = date.getFullYear();
var m = String(date.getMonth() + 1).padStart(2, "0");
var d = String(date.getDate()).padStart(2, "0");
return y + "-" + m + "-" + d;
}
function formatDateAZ(date) {
var day = date.getDate();
var month = azMonths[date.getMonth()];
var year = date.getFullYear();
return day + " " + month + " " + year;
}
function getIntervals(start, end) {
var intervals = [];
var currentStart = new Date(start);
while (currentStart <= end) {
var currentEndCandidate = addDays(currentStart, 30);
var currentEnd = currentEndCandidate > end ? end : currentEndCandidate;
intervals.push({ start: new Date(currentStart), end: new Date(currentEnd) });
currentStart = addDays(currentEnd, 1);
}
return intervals;
}
function fetchStatsForInterval(interval) {
var url = apiUrlBase + "/" + formatDate(interval.start) + "/" + formatDate(interval.end);
return $.getJSON(url);
}
function aggregateResults(results) {
var aggregated = {};
var actions = results.length > 0 ? results[0].actions : [];
results.forEach(function(res) {
for (var user in res.users) {
if (!aggregated[user]) {
aggregated[user] = $.extend(true, {}, res.users[user]);
} else {
var current = aggregated[user], newData = res.users[user];
for (var key in newData) {
if (key === "user-groups") {
current["user-groups"] = current["user-groups"] || [];
newData["user-groups"].forEach(function(g) {
if (current["user-groups"].indexOf(g) === -1) current["user-groups"].push(g);
});
} else if (typeof newData[key] === "number") {
current[key] = (current[key] || 0) + newData[key];
}
}
}
}
});
return { actions: actions, users: aggregated };
}
function sortUsers(aggregated) {
var usersArr = [];
$.each(aggregated.users, function(username, user) {
user.username = username;
usersArr.push(user);
});
usersArr.sort(function(a, b) {
var key = currentSort.column;
var valA, valB;
if (key === "username") {
valA = a.username.toLowerCase();
valB = b.username.toLowerCase();
return currentSort.order === "asc" ? (valA < valB ? -1 : valA > valB ? 1 : 0) : (valA > valB ? -1 : valA < valB ? 1 : 0);
} else {
valA = a[key] || 0;
valB = b[key] || 0;
return currentSort.order === "asc" ? valA - valB : valB - valA;
}
});
return usersArr;
}
function buildHtmlTable(aggregated) {
var filteredActions = aggregated.actions.filter(function(act) {
return !excludedColumns.includes(act);
});
var $table = $("<table>")
.addClass("wikitable")
.css({ width: "100%", "border-collapse": "collapse", "font-size": "90%", "line-height": "1.4" });
var $thead = $("<thead>");
var $headerRow = $("<tr>");
$headerRow.append($("<th>").text("İstifadəçi").css("text-align", "center").attr("data-sort-key", "username").css("cursor", "pointer"));
filteredActions.forEach(function(act) {
var colInfo = columnsMap[act];
var $th = $("<th>").css({ "text-align": "center", "text-decoration": "underline dotted", cursor: "pointer" });
if (colInfo) $th.text(colInfo.label).attr("title", colInfo.tooltip).attr("data-sort-key", act);
else $th.text(act).attr("data-sort-key", act);
$headerRow.append($th);
});
$headerRow.append($("<th>").text("Cəmi").css({ "text-align": "center", "text-decoration": "underline dotted", cursor: "pointer" }).attr("title", "Ümumi əməliyyatların cəmi").attr("data-sort-key", "total"));
$headerRow.append($("<th>").text("Lokal hüquqlar").css("text-align", "center"));
$thead.append($headerRow);
$table.append($thead);
var usersArr = sortUsers(aggregated);
var $tbody = $("<tbody>");
usersArr.forEach(function(user) {
var groups = user["user-groups"];
if (!Array.isArray(groups) || groups.length === 0) return;
var displayGroups;
if (showLocalOnly) {
displayGroups = groups.filter(function(g) { return localRights.indexOf(g) !== -1; });
if (displayGroups.length === 0) return;
} else displayGroups = groups;
var $row = $("<tr>");
var $userLink = $("<a>").attr("href", mw.util.getUrl("User:" + user.username)).text(user.username);
$row.append($("<td>").css("text-align", "center").append($userLink));
filteredActions.forEach(function(act) {
var value = user[act] || 0;
$row.append($("<td>").text(value).css("text-align", "center"));
});
$row.append($("<td>").text(user.total || 0).css("text-align", "center"));
var localizedGroups = displayGroups.map(function(g) { return groupMap[g] || g; });
$row.append($("<td>").text(localizedGroups.join(", ")).css("text-align", "center"));
$tbody.append($row);
});
$table.append($tbody);
$thead.find("th[data-sort-key]").css("cursor", "pointer").on("click", function() {
var sortKey = $(this).attr("data-sort-key");
if (currentSort.column === sortKey) {
currentSort.order = currentSort.order === "asc" ? "desc" : "asc";
} else {
currentSort.column = sortKey;
currentSort.order = "desc";
}
var $newTable = buildHtmlTable(aggregated);
$("#admin-stats-output").empty().append($newTable);
attachSortHandlers(aggregated);
});
return $table;
}
function attachSortHandlers(aggregated) {
$("#admin-stats-output thead th[data-sort-key]").css("cursor", "pointer").off("click").on("click", function() {
var sortKey = $(this).attr("data-sort-key");
if (currentSort.column === sortKey) {
currentSort.order = currentSort.order === "asc" ? "desc" : "asc";
} else {
currentSort.column = sortKey;
currentSort.order = "desc";
}
var $newTable = buildHtmlTable(aggregated);
$("#admin-stats-output").empty().append($newTable);
attachSortHandlers(aggregated);
});
}
function getIntervalSummary(start, end) {
var today = new Date();
if (formatDate(today) !== formatDate(end)) {
return formatDateAZ(start) + " – " + formatDateAZ(end) + " aralığı üçün:";
}
var years = end.getFullYear() - start.getFullYear();
var months = end.getMonth() - start.getMonth() + years * 12;
var days = end.getDate() - start.getDate();
if (days < 0) { months--; var prevMonth = new Date(end.getFullYear(), end.getMonth(), 0); days += prevMonth.getDate(); }
var parts = [];
if (months >= 12) { var yearsPart = Math.floor(months / 12); parts.push(yearsPart + " il"); months = months % 12; }
if (months > 0) parts.push(months + " ay");
if (days > 0) parts.push(days + " gün");
if (parts.length === 0) return "Son 0 gün üçün:";
return "Son " + parts.join(" ") + " üçün:";
}
function fetchAndDisplayStats(start, end) {
var intervals = getIntervals(start, end);
var promises = intervals.map(function(interval) {
return $.getJSON(apiUrlBase + "/" + formatDate(interval.start) + "/" + formatDate(interval.end));
});
$.when.apply($, promises)
.done(function() {
var results;
if (promises.length === 1) results = [arguments[0]];
else results = Array.prototype.slice.call(arguments).map(function(r) { return r[0]; });
var aggregated = aggregateResults(results);
$.getJSON(groupsApiUrl)
.done(function(adminGroupsData) {
var adminUsers = adminGroupsData.users_and_groups;
for (var username in adminUsers) {
if (!aggregated.users.hasOwnProperty(username)) {
if (adminUsers[username].indexOf("sysop") !== -1) {
var newUser = { total: 0, "user-groups": adminUsers[username] };
aggregated.actions.forEach(function(action) { newUser[action] = 0; });
aggregated.users[username] = newUser;
}
}
}
currentAggregated = aggregated;
var $table = buildHtmlTable(aggregated);
$("#admin-stats-output").empty().append($table);
attachSortHandlers(aggregated);
var summaryText = getIntervalSummary(start, end);
var $card = $('<span class="cdx-card">' +
'<span class="cdx-card__text">' +
'<span class="cdx-card__text__title">' + summaryText + '</span>' +
'</span>' +
'</span>');
$("#admin-stats-card").empty().append($card);
})
.fail(function() {
$("#admin-stats-output").text("İnzibatçı qruplarını əldə etmək mümkün olmadı.");
});
})
.fail(function() {
$("#admin-stats-output").text("İnzibatçı statistikalarını əldə etmək mümkün olmadı.");
});
}
function init() {
$("#content").empty().append(
$("<h2>").text("İnzibatçıların statistikası"),
$("<div>", { id: "date-inputs" }),
$("<div>", { id: "admin-stats-card" }).css("margin", "1em 0"),
$("<div>", { id: "admin-stats-output" })
);
var today = new Date();
var currentYearStart = new Date(today.getFullYear(), 0, 1);
var $startDateInput = $('<div class="cdx-text-input" style="margin-right: 0.5em;">' +
'<input class="cdx-text-input__input" type="date" placeholder="Başlanğıc tarixi" />' +
"</div>");
var $endDateInput = $('<div class="cdx-text-input" style="margin-right: 0.5em;">' +
'<input class="cdx-text-input__input" type="date" placeholder="Bitmə tarixi" />' +
"</div>");
$startDateInput.find("input").val(formatDate(currentYearStart));
$endDateInput.find("input").val(formatDate(today));
var $localCheckbox = $('<div class="cdx-checkbox" style="margin-left: 0.5em; margin-bottom: -17px;">' +
'<div class="cdx-checkbox__wrapper">' +
'<input id="checkbox-css-only-1" class="cdx-checkbox__input" type="checkbox" checked />' +
'<span class="cdx-checkbox__icon"></span>' +
'<div class="cdx-checkbox__label cdx-label">' +
'<label for="checkbox-css-only-1" class="cdx-label__label">' +
'<span class="cdx-label__label__text">Yalnız lokal inzibatçılar</span>' +
'</label>' +
'</div>' +
'</div>' +
'</div>');
var $updateButton = $('<button type="button" class="cdx-button cdx-button--action-progressive cdx-button--weight-primary" style="margin-left: 0.5em; margin-bottom: -17px;">Yenilə</button>');
$updateButton.on("click", function() {
var startValStr = $startDateInput.find("input").val();
var endValStr = $endDateInput.find("input").val();
var startVal = startValStr ? new Date(startValStr) : currentYearStart;
var endVal = endValStr ? new Date(endValStr) : today;
showLocalOnly = $("#checkbox-css-only-1").prop("checked");
fetchAndDisplayStats(startVal, endVal);
});
$("#date-inputs")
.css({ display: "flex", gap: "1em", "align-items": "center", "flex-wrap": "wrap" })
.append(
$("<label>").text("Başlanğıc tarixi: ").append($startDateInput),
$("<label>").text(" Bitmə tarixi: ").append($endDateInput),
$localCheckbox,
$updateButton
);
fetchAndDisplayStats(
$startDateInput.find("input").val() ? new Date($startDateInput.find("input").val()) : currentYearStart,
$endDateInput.find("input").val() ? new Date($endDateInput.find("input").val()) : today
);
setInterval(function() {
var startValStr = $startDateInput.find("input").val();
var endValStr = $endDateInput.find("input").val();
var startVal = startValStr ? new Date(startValStr) : currentYearStart;
var endVal = endValStr ? new Date($endDateInput.find("input").val()) : today;
showLocalOnly = $("#checkbox-css-only-1").prop("checked");
fetchAndDisplayStats(startVal, endVal);
}, refreshInterval);
}
$(init);
})(jQuery, mediaWiki);