//<nowiki>
(function () {
function formatDate(date) {
const day = date.getUTCDate();
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const month = monthNames[date.getUTCMonth()];
const year = date.getUTCFullYear();
let hours = date.getUTCHours();
const minutes = date.getUTCMinutes();
const seconds = date.getUTCSeconds();
const ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12;
if (hours === 0) hours = 12;
const minutesStr = minutes.toString().padStart(2, '0');
const secondsStr = seconds.toString().padStart(2, '0');
return `${day} ${month} ${year}, ${hours}:${minutesStr}:${secondsStr} ${ampm} (UTC)`;
}
mw.loader.using(['mediawiki.api', 'oojs-ui', 'mediawiki.util']).then(function () {
function addPortletLink() {
mw.util.addPortletLink(
'p-cactions',
'#',
'View metadata of deleted revisions',
'ca-show-deleted-revisions',
'View metadata of deleted revisions'
);
document.getElementById('ca-show-deleted-revisions').addEventListener('click', function (e) {
e.preventDefault();
const pageTitle = mw.config.get('wgPageName');
fetchRevisions(pageTitle);
});
}
function fetchRevisions(pageTitle, continuation) {
const params = {
action: 'query',
prop: 'deletedrevisions',
titles: pageTitle,
drvprop: 'user|timestamp|tags|size',
drvlimit: 'max',
formatversion: 2
};
if (continuation) {
params.drvcontinue = continuation;
}
new mw.Api().get(params).done(function (data) {
const pageData = data.query.pages[0];
if (pageData.deletedrevisions) {
const cont = data.continue ? data.continue.drvcontinue : null;
if (window.revisionDialog && window.revisionDialog.isOpen()) {
window.revisionDialog.appendRevisions(pageData.deletedrevisions);
window.revisionDialog.totalCount += pageData.deletedrevisions.length;
window.revisionDialog.$countDisplay.text('Total revisions loaded: ' + window.revisionDialog.totalCount);
window.revisionDialog.continuation = cont;
if (!cont && window.revisionDialog.$nextButton) {
window.revisionDialog.$nextButton.remove();
window.revisionDialog.$nextButton = null;
}
} else {
showDialog(pageData.deletedrevisions, pageData.title || pageTitle, cont);
}
} else {
new OO.ui.Alert('No deleted revisions found for this page.', { type: 'error' }).show();
}
}).fail(function (error) {
new OO.ui.Alert('Error loading revisions: ' + error, { type: 'error' }).show();
});
}
function showDialog(revisions, title, continuation) {
const RevisionDialog = function (config) {
RevisionDialog.super.call(this, config);
};
OO.inheritClass(RevisionDialog, OO.ui.ProcessDialog);
RevisionDialog.static.name = 'revisionDialog';
RevisionDialog.static.title = 'Deleted revisions: ' + title;
RevisionDialog.static.actions = [
{ action: 'close', icon: 'close', flags: ['safe'] }
];
RevisionDialog.prototype.initialize = function () {
RevisionDialog.super.prototype.initialize.call(this);
this.pageTitle = title;
this.continuation = continuation;
this.totalCount = revisions.length;
this.$countDisplay = $('<div>')
.css({ 'margin-top': '1em', 'margin-left': '1em', 'font-weight': 'bold' })
.text('Total revisions: ' + this.totalCount);
this.$body.append(this.$countDisplay);
const tablePanel = new OO.ui.PanelLayout({ padded: true, expanded: false });
this.$body.append(tablePanel.$element);
const $table = $('<table>')
.addClass('wikitable')
.css({ 'width': '100%', 'border-collapse': 'collapse', 'background-color': 'white', '--background-color-neutral-subtle': 'white' });
$table.append($('<thead>').append(
$('<tr>').append(
$('<th>').text('User').css('width', '25%'),
$('<th>').text('Date/Time').css('width', '35%'),
$('<th>').text('Size').css('width', '15%'),
$('<th>').text('Tags').css('width', '40%')
)
));
this.$tbody = $('<tbody>');
$table.append(this.$tbody);
tablePanel.$element.append($table);
this.appendRevisions(revisions);
if (this.continuation) {
this.$nextButton = $('<button>')
.addClass('mw-ui-button')
.text('Next')
.css({ 'margin-top': '1em' });
this.$body.append($('<div>').append(this.$nextButton));
this.$nextButton.on('click', () => {
this.loadMore();
});
}
};
RevisionDialog.prototype.appendRevisions = function (revisions) {
revisions.forEach(rev => {
const dateStr = formatDate(new Date(rev.timestamp));
const userUrl = mw.util.getUrl('User:' + rev.user);
const $userLink = $('<a>').attr('href', userUrl).text(rev.user);
const $tr = $('<tr>').append(
$('<td>').append($userLink),
$('<td>').text(dateStr),
$('<td>').text(rev.size.toLocaleString() + ' bytes'),
$('<td>').text((rev.tags && rev.tags.length > 0) ? rev.tags.join(', ') : '—')
);
this.$tbody.append($tr);
});
};
RevisionDialog.prototype.loadMore = function () {
if (!this.continuation) return;
if (this.$nextButton) {
this.$nextButton.prop('disabled', true).text('Loading...');
}
const params = {
action: 'query',
prop: 'deletedrevisions',
titles: this.pageTitle,
drvprop: 'user|timestamp|tags|size',
drvlimit: 'max',
formatversion: 2,
drvcontinue: this.continuation
};
new mw.Api().get(params).done((data) => {
const pageData = data.query.pages[0];
if (pageData.deletedrevisions) {
this.appendRevisions(pageData.deletedrevisions);
this.totalCount += pageData.deletedrevisions.length;
this.$countDisplay.text('Total revisions loaded: ' + this.totalCount);
}
this.continuation = data.continue ? data.continue.drvcontinue : null;
if (this.continuation) {
if (this.$nextButton) {
this.$nextButton.prop('disabled', false).text('Next');
}
} else {
if (this.$nextButton) {
this.$nextButton.remove();
this.$nextButton = null;
}
}
}).fail((error) => {
new OO.ui.Alert('Error loading more revisions: ' + error, { type: 'error' }).show();
if (this.$nextButton) {
this.$nextButton.prop('disabled', false).text('Next');
}
});
};
RevisionDialog.prototype.getActionProcess = function (action) {
return action === 'close' ?
new OO.ui.Process(() => this.close()) :
RevisionDialog.super.prototype.getActionProcess.call(this, action);
};
const windowManager = new OO.ui.WindowManager();
$('body').append(windowManager.$element);
const dialog = new RevisionDialog({ size: 'larger' });
windowManager.addWindows([dialog]);
windowManager.openWindow(dialog).then(openedDialog => {
openedDialog.get$frame().css({
width: '90%',
maxWidth: '1200px',
maxHeight: '80vh',
margin: '2rem auto'
});
openedDialog.$body.css('overflow', 'auto');
window.revisionDialog = openedDialog;
});
}
if (document.querySelector('li[data-mw-logaction^="delete/"]')) {
addPortletLink();
} else {
const pageTitle = mw.config.get('wgPageName');
const params = {
action: 'query',
prop: 'deletedrevisions',
titles: pageTitle,
drvprop: 'user|timestamp|tags|size',
drvlimit: 1,
formatversion: 2
};
new mw.Api().get(params).done(function (data) {
const pageData = data.query.pages[0];
if (pageData.deletedrevisions && pageData.deletedrevisions.length > 0) {
addPortletLink();
}
}).fail(function (error) {
console.error('Error checking for deleted revisions: ' + error);
});
}
});
})();
//</nowiki>