Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
ff42b38
+ prp quality changes pie chart in ec generalstats
agoujot Jun 27, 2025
a863827
Merge branch 'main' into ecprpchanges
agoujot Jul 14, 2025
5fbe22d
compile
agoujot Jul 14, 2025
8dd215d
Merge branch 'main' into ecprpchanges
agoujot Jul 17, 2025
6e737bc
compile
agoujot Jul 17, 2025
9bcab4a
Merge branch 'main' into ecprpchanges
agoujot Jul 21, 2025
fc4cd54
compile
agoujot Jul 21, 2025
949b3ff
Merge branch 'main' into ecprpchanges
agoujot Aug 6, 2025
c434248
compile
agoujot Aug 6, 2025
10949d6
Merge branch 'x-tools:main' into ecprpchanges
agoujot Aug 19, 2025
6ee93c7
add column in pages; take quality changes from the api; (and other th…
agoujot Aug 19, 2025
9835557
Merge branch 'main' into ecprpchanges
agoujot Aug 19, 2025
dde5474
commpile
agoujot Aug 19, 2025
8ed29c1
lints
agoujot Aug 19, 2025
7303495
PC: add pie chart; rm unused method (migrated to project)
agoujot Aug 20, 2025
54ae97b
refactor some ugly duplication on pa selects
agoujot Aug 20, 2025
c378fac
clean up getTopEditsAllNamespaces and fetch prp quality in both
agoujot Aug 20, 2025
01f086d
lint
agoujot Aug 20, 2025
55486be
add column to TE and add proper sort keys for quality
agoujot Aug 20, 2025
64f584c
add in wikitext, tsv, csv
agoujot Aug 20, 2025
d791813
add tests for most of EditCounter; a few other tweaks
agoujot Aug 20, 2025
dd23577
a few more tests and finish removing an unused method
agoujot Aug 20, 2025
a28e61d
code coverage for AutoEdits
agoujot Aug 20, 2025
14db2fb
fix
agoujot Aug 20, 2025
462ee05
these two lines did have coverage; try explicit false
agoujot Aug 20, 2025
80614ba
as always, the cache is god and the devil
agoujot Aug 20, 2025
880df65
+forgotten paren
agoujot Aug 20, 2025
302d6cc
code coverage for Project.php; rewrite testEditData cleaner with prov…
agoujot Aug 21, 2025
2b77a63
try to fix and finish Project.php coverage
agoujot Aug 21, 2025
c52008d
code coverage for TopEdits
agoujot Aug 21, 2025
82f10ad
fixed test for te not opted in
agoujot Aug 21, 2025
fe716d2
do test model-side caching in EC
agoujot Aug 21, 2025
e1cd739
do test PA in Project; fix EC average test case
agoujot Aug 21, 2025
cd88cc7
coverage for UserRights
agoujot Aug 21, 2025
737ec27
finish coverage for UserRights
agoujot Aug 21, 2025
b24cd58
coverage for Pages.php
agoujot Aug 21, 2025
0559fef
coverage for a few small classes
agoujot Aug 21, 2025
b37bcb3
coverage for blame
agoujot Aug 21, 2025
8bf740a
lints
agoujot Aug 21, 2025
dd3887a
fix coverage of asof caching in blame
agoujot Aug 21, 2025
3951249
coverage for Edit.php
agoujot Aug 21, 2025
619bd75
fix test for edit wikifystring with section
agoujot Aug 21, 2025
07987ee
lint
agoujot Aug 21, 2025
cd1a6f6
codeCoverageignore the admin score
agoujot Aug 21, 2025
725f0bd
coverage for admin stats
agoujot Aug 22, 2025
cd8a7d8
finish admin stats coverage
agoujot Aug 22, 2025
120ccf9
code coverage for page.php
agoujot Aug 23, 2025
48cb2cb
coverage for User.php
agoujot Aug 23, 2025
af8b259
lint
agoujot Aug 23, 2025
2182462
lint
agoujot Aug 23, 2025
cbc888f
coverage for Authorship.php
agoujot Aug 23, 2025
e498358
coverage for PageAssessments.php
agoujot Aug 23, 2025
451c77f
lint
agoujot Aug 23, 2025
48f9e28
start work on pageinfo coverage
agoujot Aug 23, 2025
cc7a773
lint
agoujot Aug 23, 2025
62a9e50
lint
agoujot Aug 23, 2025
fb85638
continue pageinfo coverage
agoujot Aug 23, 2025
1596490
try and finish pageinfo coverage
agoujot Aug 24, 2025
e5db1b1
try and finish pageinfo coverage
agoujot Aug 24, 2025
b4e83a0
I think it's done
agoujot Aug 24, 2025
89bdbb9
quick xtoolshttpexception coverage
agoujot Aug 24, 2025
bab4f18
Merge branch 'main' into ecprpchanges
agoujot Aug 27, 2025
468f560
compile
agoujot Aug 27, 2025
e10812c
Merge branch 'main' into ecprpchanges
agoujot Oct 26, 2025
3866cee
test autoeditcount in EC
agoujot Oct 26, 2025
003fba8
try to fix tests
agoujot Oct 26, 2025
9786b15
ok, try again
agoujot Jan 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

# Unix-style newlines with a newline ending every file
[*]
indent_style = tab
indent_size = tab
tab_width = 4
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

# 4 space indentation
[*.{php,js,twig}]
# Tabs may not be valid YAML
# @see https://yaml.org/spec/1.2/spec.html#id2777534
[*.{yml,yaml}]
indent_style = space
indent_size = 4
indent_size = 2
19 changes: 19 additions & 0 deletions assets/css/_darkmode.scss
Original file line number Diff line number Diff line change
Expand Up @@ -329,4 +329,23 @@ $tooltip-shadow: #333;
filter:invert(1) hue-rotate(180deg);
}

.prp-qualitytext {
color:white; /* needed to have enough contrast */
}
.prp-quality0 {
background-color:#55585e;
}
.prp-quality1 {
background-color:#971602;
}
.prp-quality2 {
background-color:#40408c;
}
.prp-quality3 {
background-color:#5C5C00;
}
.prp-quality4 {
background-color:#00662e;
}

}
24 changes: 23 additions & 1 deletion assets/css/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,29 @@ a.help-icon {
clear: both;
}


.prp-qualitytext {
border-radius: 3px;
padding: 0 2px;
}

.prp-quality0 {
background-color:#ddd;
}
.prp-quality1 {
background-color:#ffabab;
}
.prp-quality2 {
background-color:#bbbbff;
}
.prp-quality3 {
background-color:#ffe867;
}
.prp-quality4 {
background-color:#90ff90;
}

.link-loading {
pointer-events: none;
font-style: italic;
}
}
4 changes: 4 additions & 0 deletions assets/css/editcounter.scss
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
height: auto;
width: auto;
}

div.chart-wrapper.qualitychangechart {
float:none;
}

.top-project-edit-counts td {
white-space: nowrap;
Expand Down
50 changes: 25 additions & 25 deletions assets/js/adminstats.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
xtools.adminstats = {};

$(function () {
var $projectInput = $('#project_input'),
lastProject = $projectInput.val();
var $projectInput = $('#project_input'),
lastProject = $projectInput.val();

// Don't do anything if this isn't an Admin Stats page.
if ($('body.adminstats, body.patrollerstats, body.stewardstats').length === 0) {
return;
}
// Don't do anything if this isn't an Admin Stats page.
if ($('body.adminstats, body.patrollerstats, body.stewardstats').length === 0) {
return;
}

xtools.application.setupMultiSelectListeners();
xtools.application.setupMultiSelectListeners();

$('.group-selector').on('change', function () {
$('.action-selector').addClass('hidden');
$('.action-selector--' + $(this).val()).removeClass('hidden');
$('.group-selector').on('change', function () {
$('.action-selector').addClass('hidden');
$('.action-selector--' + $(this).val()).removeClass('hidden');

// Update title of form.
$('.xt-page-title--title').text($.i18n('tool-' + $(this).val() + 'stats'));
$('.xt-page-title--desc').text($.i18n('tool-' + $(this).val() + 'stats-desc'));
var title = $.i18n('tool-' + $(this).val() + 'stats') + ' - ' + $.i18n('xtools-title');
document.title = title;
history.replaceState({}, title, '/' + $(this).val() + 'stats');
// Update title of form.
$('.xt-page-title--title').text($.i18n('tool-' + $(this).val() + 'stats'));
$('.xt-page-title--desc').text($.i18n('tool-' + $(this).val() + 'stats-desc'));
var title = $.i18n('tool-' + $(this).val() + 'stats') + ' - ' + $.i18n('xtools-title');
document.title = title;
history.replaceState({}, title, '/' + $(this).val() + 'stats');

// Change project to Meta if it's Steward Stats.
if ('steward' === $(this).val()) {
lastProject = $projectInput.val();
$projectInput.val('meta.wikimedia.org');
} else {
$projectInput.val(lastProject);
}
// Change project to Meta if it's Steward Stats.
if ('steward' === $(this).val()) {
lastProject = $projectInput.val();
$projectInput.val('meta.wikimedia.org');
} else {
$projectInput.val(lastProject);
}

xtools.application.setupMultiSelectListeners();
});
xtools.application.setupMultiSelectListeners();
});
});
22 changes: 11 additions & 11 deletions assets/js/authorship.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
$(function () {
if (!$('body.authorship').length) {
return;
}
if (!$('body.authorship').length) {
return;
}

const $showSelector = $('#show_selector');
const $showSelector = $('#show_selector');

$showSelector.on('change', e => {
$('.show-option').addClass('hidden')
.find('input').prop('disabled', true);
$(`.show-option--${e.target.value}`).removeClass('hidden')
.find('input').prop('disabled', false);
});
$showSelector.on('change', e => {
$('.show-option').addClass('hidden')
.find('input').prop('disabled', true);
$(`.show - option--${e.target.value}`).removeClass('hidden')
.find('input').prop('disabled', false);
});

window.onload = () => $showSelector.trigger('change');
window.onload = () => $showSelector.trigger('change');
});
126 changes: 63 additions & 63 deletions assets/js/autoedits.js
Original file line number Diff line number Diff line change
@@ -1,78 +1,78 @@
xtools.autoedits = {};

$(function () {
if (!$('body.autoedits').length) {
return;
}
if (!$('body.autoedits').length) {
return;
}

var $contributionsContainer = $('.contributions-container'),
$toolSelector = $('#tool_selector');
var $contributionsContainer = $('.contributions-container'),
$toolSelector = $('#tool_selector');

// For the form page.
if ($toolSelector.length) {
xtools.autoedits.fetchTools = function (project) {
$toolSelector.prop('disabled', true);
$.get('/api/project/automated_tools/' + project).done(function (tools) {
if (tools.error) {
$toolSelector.prop('disabled', false);
return; // Abort, project was invalid.
}
// For the form page.
if ($toolSelector.length) {
xtools.autoedits.fetchTools = function (project) {
$toolSelector.prop('disabled', true);
$.get('/api/project/automated_tools/' + project).done(function (tools) {
if (tools.error) {
$toolSelector.prop('disabled', false);
return; // Abort, project was invalid.
}

// These aren't tools, just metadata in the API response.
delete tools.project;
delete tools.elapsed_time;
// These aren't tools, just metadata in the API response.
delete tools.project;
delete tools.elapsed_time;

$toolSelector.html(
'<option value="none">' + $.i18n('none') + '</option>' +
'<option value="all">' + $.i18n('all') + '</option>'
);
Object.keys(tools).forEach(function (tool) {
$toolSelector.append(
'<option value="' + tool + '">' + (tools[tool].label || tool) + '</option>'
);
});
$toolSelector.html(
'<option value="none">' + $.i18n('none') + '</option>' +
'<option value="all">' + $.i18n('all') + '</option>'
);
Object.keys(tools).forEach(function (tool) {
$toolSelector.append(
'<option value="' + tool + '">' + (tools[tool].label || tool) + '</option>'
);
});

$toolSelector.prop('disabled', false);
});
};
$toolSelector.prop('disabled', false);
});
};

$(document).ready(function () {
$('#project_input').on('change.autoedits', function () {
xtools.autoedits.fetchTools($('#project_input').val());
});
});
$(document).ready(function () {
$('#project_input').on('change.autoedits', function () {
xtools.autoedits.fetchTools($('#project_input').val());
});
});

xtools.autoedits.fetchTools($('#project_input').val());
xtools.autoedits.fetchTools($('#project_input').val());

// All the other code below only applies to result pages.
return;
}
// All the other code below only applies to result pages.
return;
}

// For result pages only...
// For result pages only...

xtools.application.setupToggleTable(window.countsByTool, window.toolsChart, 'count', function (newData) {
var total = 0;
Object.keys(newData).forEach(function (tool) {
total += parseInt(newData[tool].count, 10);
});
var toolsCount = Object.keys(newData).length;
/** global: i18nLang */
$('.tools--tools').text(
toolsCount.toLocaleString(i18nLang) + " " +
$.i18n('num-tools', toolsCount)
);
$('.tools--count').text(total.toLocaleString(i18nLang));
});
xtools.application.setupToggleTable(window.countsByTool, window.toolsChart, 'count', function (newData) {
var total = 0;
Object.keys(newData).forEach(function (tool) {
total += parseInt(newData[tool].count, 10);
});
var toolsCount = Object.keys(newData).length;
/** global: i18nLang */
$('.tools--tools').text(
toolsCount.toLocaleString(i18nLang) + " " +
$.i18n('num-tools', toolsCount)
);
$('.tools--count').text(total.toLocaleString(i18nLang));
});

if ($contributionsContainer.length) {
// Load the contributions browser, or set up the listeners if it is already present.
var initFunc = $('.contributions-table').length ? 'setupContributionsNavListeners' : 'loadContributions';
xtools.application[initFunc](
function (params) {
return `${params.target}-contributions/${params.project}/${params.username}` +
`/${params.namespace}/${params.start}/${params.end}`;
},
$contributionsContainer.data('target')
);
}
if ($contributionsContainer.length) {
// Load the contributions browser, or set up the listeners if it is already present.
var initFunc = $('.contributions-table').length ? 'setupContributionsNavListeners' : 'loadContributions';
xtools.application[initFunc](
function (params) {
return `${params.target} - contributions / ${params.project} / ${params.username}` +
` / ${params.namespace} / ${params.start} / ${params.end}`;
},
$contributionsContainer.data('target')
);
}
});
70 changes: 35 additions & 35 deletions assets/js/blame.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,44 @@
xtools.blame = {};

$(function () {
if (!$('body.blame').length) {
return;
}
if (!$('body.blame').length) {
return;
}

if ($('.diff-empty').length === $('.diff tr').length - 1) {
$('.diff-empty').eq(0)
.text(`(${$.i18n('diff-empty').toLowerCase()})`)
.addClass('text-muted text-center')
.prop('width', '20%');
}
if ($('.diff-empty').length === $('.diff tr').length - 1) {
$('.diff-empty').eq(0)
.text(`(${$.i18n('diff-empty').toLowerCase()})`)
.addClass('text-muted text-center')
.prop('width', '20%');
}

$('.diff-addedline').each(function () {
// Escape query to make regex-safe.
const escapedQuery = xtools.blame.query.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
$('.diff-addedline').each(function () {
// Escape query to make regex-safe.
const escapedQuery = xtools.blame.query.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');

const highlightMatch = selector => {
const regex = new RegExp(`(${escapedQuery})`, 'gi');
$(selector).html(
$(selector).html().replace(regex, `<strong>$1</strong>`)
);
};
const highlightMatch = selector => {
const regex = new RegExp(`(${escapedQuery})`, 'gi');
$(selector).html(
$(selector).html().replace(regex, ` < strong > $1 < / strong > `)
);
};

if ($(this).find('.diffchange-inline').length) {
$('.diffchange-inline').each(function () {
highlightMatch(this);
});
} else {
highlightMatch(this);
}
});
if ($(this).find('.diffchange-inline').length) {
$('.diffchange-inline').each(function () {
highlightMatch(this);
});
} else {
highlightMatch(this);
}
});

// Handles the "Show" dropdown, show/hiding the associated input field accordingly.
const $showSelector = $('#show_selector');
$showSelector.on('change', e => {
$('.show-option').addClass('hidden')
.find('input').prop('disabled', true);
$(`.show-option--${e.target.value}`).removeClass('hidden')
.find('input').prop('disabled', false);
});
window.onload = () => $showSelector.trigger('change');
// Handles the "Show" dropdown, show/hiding the associated input field accordingly.
const $showSelector = $('#show_selector');
$showSelector.on('change', e => {
$('.show-option').addClass('hidden')
.find('input').prop('disabled', true);
$(`.show - option--${e.target.value}`).removeClass('hidden')
.find('input').prop('disabled', false);
});
window.onload = () => $showSelector.trigger('change');
});
Loading