Skip to content

Commit

Permalink
Merge pull request #158 from x-tools/topedits-reverts
Browse files Browse the repository at this point in the history
TopEdits: overhaul, better revert detection, more stats for single page
  • Loading branch information
MusikAnimal authored Jan 19, 2018
2 parents 061afa7 + 2ac7206 commit 09b1f0f
Show file tree
Hide file tree
Showing 13 changed files with 604 additions and 115 deletions.
1 change: 1 addition & 0 deletions app/Resources/views/base.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
'static/css/editcounter.scss'
'static/css/pages.scss'
'static/css/meta.scss'
'static/css/topedits.scss'
output='static/production/application.css' %}
<link rel="stylesheet" href="{{ asset_url }}" />
{% endstylesheets %}
Expand Down
212 changes: 148 additions & 64 deletions app/Resources/views/topedits/result_article.html.twig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{% extends 'base.html.twig' %}
{% import 'macros/layout.html.twig' as layout %}
{% import 'macros/wiki.html.twig' as wiki %}
{% import 'macros/pieChart.html.twig' as chart %}

{% block body %}
<div class="panel panel-primary">
Expand All @@ -22,72 +23,155 @@

<div class="panel-body xt-panel-body">
{% set content %}
<div class="col-lg-6 stat-list clearfix">
<table class="table">
<tr>
<td>{{ msg('article') }}</td>
<td>
<span class="display-title">
{{ wiki.pageLink(page, page.displaytitle|raw) }}
</span>
<small>({{ wiki.pageLogLink(page) }}
&middot; <a href="{{ path('ArticleInfoResult', {project:project.domain, article:page.title}) }}">{{ msg('tool-articleinfo') }}</a>)</small>
</td>
</tr>
<tr>
<td>{{ msg('user') }}</td>
<td>
{{ wiki.userLink(user, project) }}
<small>(<a href="{{ path('EditCounterResult', {project:project.domain, username:user.username}) }}" >{{ msg('tool-ec') }}</a>)</small>
</td>
</tr>
<tr>
<td>{{ msg('count') }}</td>
<td>{{ revision_count|num_format }}</td>
</tr>
<tr>
<td>{{ msg('added') }}</td>
<td>{{ total_added|diff_format }}</td>
</tr>
<tr>
<td>{{ msg('deleted') }}</td>
<td>{{ total_removed|diff_format }}</td>
</tr>
</table>
</div>
{% if te.numTopEdits == 0 %}
<div class="alert alert-info">
{{ msg('no-contribs') }}
</div>
{% else %}
<div class="col-lg-6 stat-list clearfix">
<table class="table">
<tr>
<td>{{ msg('article') }}</td>
<td>
<span class="display-title">
{{ wiki.pageLink(page, page.displaytitle|raw) }}
</span>
<small>({{ wiki.pageLogLink(page) }}
&middot; <a href="{{ path('ArticleInfoResult', {project:project.domain, article:page.title}) }}">{{ msg('tool-articleinfo') }}</a>)</small>
</td>
</tr>
<tr>
<td>{{ msg('user') }}</td>
<td>
{{ wiki.userLink(user, project) }}
<small>(<a href="{{ path('EditCounterResult', {project:project.domain, username:user.username}) }}" >{{ msg('tool-ec') }}</a>)</small>
</td>
</tr>
<tr>
<td class="stat-list--new-group">{{ msg('total-edits') }}</td>
<td class="stat-list--new-group">{{ te.numTopEdits|num_format }}</td>
</tr>
<tr>
<td>{{ msg('minor-edits') }}</td>
<td>
{{ te.totalMinor }}
({{ te.totalMinor|percent_format(te.numTopEdits) }})
</td>
</tr>
<tr>
<td>{{ msg('auto-edits') }}</td>
<td>
{{ te.totalAutomated }}
({{ te.totalAutomated|percent_format(te.numTopEdits) }})
</td>
</tr>
<tr>
<td><span class="color-icon" style="background:#fcf8e3"></span>{{ msg('reverted-edits') }}<sup>1</sup></td>
<td>
{{ te.totalReverted }}
({{ te.totalReverted|percent_format(te.numTopEdits) }})
</td>
</tr>
<tr>
<td>atbe<sup>2</sup></td>
<td>{{ te.atbe|round(1) }}</td>
</tr>
<tr>
<td class="stat-list--new-group">{{ msg('added-bytes') }}<sup>3</sup></td>
<td class="stat-list--new-group">{{ te.totalAdded|diff_format }}</td>
</tr>
<tr>
<td>{{ msg('deleted-bytes') }}</td>
<td>{{ te.totalRemoved|diff_format }}</td>
</tr>
</table>
</div>

<div class="basic-info-charts clearfix">
{{
chart.pie_chart('minor_edis',
[{
label: msg('minor-edits'),
value: te.totalMinor,
percentage: (te.totalMinor / te.numTopEdits) * 100
},
{
label: msg('major-edits'),
value: te.numTopEdits - te.totalMinor,
percentage: 100 - ((te.totalMinor / te.numTopEdits) * 100)
}]
)
}}
{{
chart.pie_chart('auto_edis',
[{
label: msg('auto-edits'),
value: te.totalAutomated,
percentage: (te.totalAutomated / te.numTopEdits) * 100
},
{
label: msg('manual-edits'),
value: te.numTopEdits - te.totalAutomated,
percentage: 100 - ((te.totalAutomated / te.numTopEdits) * 100)
}]
)
}}
{{
chart.pie_chart('reverted_edis',
[{
label: msg('reverted-edits'),
value: te.totalReverted,
percentage: (te.totalReverted / te.numTopEdits) * 100
},
{
label: msg('unreverted-edits'),
value: te.numTopEdits - te.totalReverted,
percentage: 100 - ((te.totalReverted / te.numTopEdits) * 100)
}]
)
}}
</div>

<div class="footnotes" style="clear:both">
<sup>1</sup> {{ msg('reverted-desc') }}
<br/><sup>2</sup> {{ msg('average-time-bw-edits') }}
<br/><sup>3</sup> {{ msg('text-added-description') }}
</div>

<table class="table table-bordered table-hover table-striped top-editors-table">
<thead><tr>
{% for key in ['date', 'links', 'size', 'edit-summary'] %}
<th>
<span{% if key != "links" %} class="sort-link sort-link--{{ key }}" data-column="{{ key }}"{% endif %}>
{{ msg(key)|capitalize_first }}
{% if key != "links" %}<span class="glyphicon glyphicon-sort"></span>{% endif %}
</span>
</th>
{% endfor %}
</tr></thead>
<table class="table table-bordered table-hover table-striped top-editors-table">
<thead><tr>
{% for key in ['date', 'links', 'size', 'edit-summary'] %}
<th>
<span{% if key != "links" %} class="sort-link sort-link--{{ key }}" data-column="{{ key }}"{% endif %}>
{{ msg(key)|capitalize_first }}
{% if key != "links" %}<span class="glyphicon glyphicon-sort"></span>{% endif %}
</span>
</th>
{% endfor %}
</tr></thead>

{% for rev in revisions|reverse %}
<tr>
<td class="sort-entry--date" data-value="{{ rev.timestamp|date('U') }}">
{{ wiki.permaLink(rev) }}
</td>
<td>
{{ wiki.diffLink(rev) }}
&middot;
{% set offset = date(rev.year ~ '-' ~ rev.month ~ '-01')|date('Ymt') ~ '235959' %}
{{ wiki.pageHistLink(page, msg('history'), offset) }}
</td>
<td class="sort-entry--size" data-value="{{ rev.size }}">
{{ rev.size|diff_format }}
</td>
<td class="sort-entry--summary" data-value="{{ rev.comment }}">
{{ rev.wikifiedSummary|raw }}
</td>
</tr>
{% endfor %}
</table>
{% for rev in te.topEdits %}
<tr{% if rev.reverted %} class="bg-warning"{% endif %}>
<td class="sort-entry--date" data-value="{{ rev.timestamp|date('U') }}">
{{ wiki.permaLink(rev) }}
</td>
<td>
{{ wiki.diffLink(rev) }}
&middot;
{% set offset = date(rev.year ~ '-' ~ rev.month ~ '-01')|date('Ymt') ~ '235959' %}
{{ wiki.pageHistLink(page, msg('history'), offset) }}
</td>
<td class="sort-entry--size" data-value="{{ rev.size }}">
{{ rev.size|diff_format }}
</td>
<td class="sort-entry--edit-summary" data-value="{{ rev.comment }}">
{% if rev.reverted %}<i class="text-info">({{ msg('reverted')|lower }})</i>&nbsp;{% endif %}
{{ rev.wikifiedSummary|raw }}
</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% endset %}
{{ layout.content_block('topedits-article', content, msg('topedits-article-desc'), null, false, false) }}

Expand Down
3 changes: 2 additions & 1 deletion app/config/semi_automated.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ parameters:
Undo:
regex: '^(Undid|Undo) revision \d+ by \[\[Special:(Contribs|Contributions)\/.*?\|.*?\]\]'
link: Special:MyLanguage/Project:Undo
revert: true
# This is not considered a revert because you can undo
# any arbitrary revision, not just the previous one.
Huggle:
regex: '\(\[\[WP:HG'
tag: huggle
Expand Down
5 changes: 5 additions & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"date-range-outside-revisions": "No revisions found for the given date range",
"delete": "Delete",
"deleted": "Deleted",
"deleted-bytes": "Deleted (bytes)",
"deleted-edits": "Deleted edits",
"deleted-pages": "Deleted pages",
"delpagesfilter-both": "Include live and deleted pages",
Expand Down Expand Up @@ -170,6 +171,7 @@
"major-contributors": "Major contributors",
"major-edits": "Major edits",
"major-edits-with-summaries": "Major edits with summaries",
"manual-edits": "Manual edits",
"max-text-added": "Max. text added",
"max-text-deleted": "Max. text deleted",
"memory-usage": "Taken $1 {{PLURAL:$2|megabyte|megabytes}} of memory to execute.",
Expand Down Expand Up @@ -279,6 +281,8 @@
"result": "Result",
"result-by-name": "Result by name / IP",
"result-by-time": "Result by time",
"reverted": "Reverted",
"reverted-desc": "Reverted edits are edits that were reverted with the immediately following edit",
"reverted-edits": "Reverted edits",
"revision-delete": "Revision delete",
"rfx-bureaucrat": "This tool can also analyze Requests for bureaucratship pages",
Expand Down Expand Up @@ -372,6 +376,7 @@
"unique-references": "Unique references",
"unknown": "Unknown",
"unprotect": "Unprotect",
"unreverted-edits": "Unreverted edits",
"user": "User",
"user-groups": "User groups",
"user-id": "User ID",
Expand Down
7 changes: 6 additions & 1 deletion i18n/qqq.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
"date-range-outside-revisions": "Text shown in info flash message saying that choosen date range does not contain any revisions",
"delete": "Name of a MediaWiki log action, used as header of a row in the table of log action counts for a user.\n{{Identical|Delete}}",
"deleted": "Deleted in the context of deleted text or deleted edits.\n{{Identical|Deleted}}",
"deleted-bytes": "Label for the number of bytes that were removed from an article.",
"deleted-edits": "Deleted edits of a user",
"deleted-pages": "Filter for page's deletion state",
"delpagesfilter-both": "Filter to show both deleted and live pages",
Expand Down Expand Up @@ -169,6 +170,7 @@
"major-contributors": "Heading for list of authors who made major contributions to XTools.",
"major-edits": "Label for number of non-minor edits.",
"major-edits-with-summaries": "Value for the number of major edits that have edit summaries.",
"manual-edits": "Label for number of manual edits made to an article, e.g. without the help of semi-automated tools like Huggle.",
"max-text-added": "Maximun text added by a user, short word or abbreviation for Max. (if possible)",
"max-text-deleted": "Maximum text deleted by a user, short word or abbreviation for Max. (if possible)",
"memory-usage": "Text showing how much memory the tool took to execute. $1 is the number of megabytes.",
Expand Down Expand Up @@ -278,7 +280,9 @@
"result": "Label/header for the query result\n{{Identical|Result}}",
"result-by-name": "Label for results by name or IP",
"result-by-time": "Label for Results by time",
"reverted-edits": "Reverted edits of a user",
"reverted": "Text indicating an edit was reverted.\n{{Identical|Reverted}}",
"reverted-desc": "Description of what it means that a edit was reverted in the TopEdits tool. It only detects surrounding edits, so the wording 'immediately following edit' is important.",
"reverted-edits": "Reverted edits of a user.",
"revision-delete": "Name of a MediaWiki log action, used as header of a row in the table of log action counts for a user.",
"rfx-bureaucrat": "Further intro message for RfX Analysis tool.",
"rfx-duplicates": "Label for number of duplicate votes that were detected in a RfX.\n{{Identical|Duplicate}}",
Expand Down Expand Up @@ -371,6 +375,7 @@
"unique-references": "Label for the number of unique references that are in an article.",
"unknown": "General term.\n{{Identical|Unknown}}",
"unprotect": "Name of a MediaWiki log action, used as header of a row in the table of log action counts for a user\n{{Identical|Unprotect}}",
"unreverted-edits": "Label for number of edits that were not reverted in an article.",
"user": "Label for the user that the statistics are about.\n{{Identical|User}}",
"user-groups": "Label for the list of 'groups' that a user belongs to.",
"user-id": "Registration id of a user (short term)",
Expand Down
31 changes: 11 additions & 20 deletions src/AppBundle/Controller/TopEditsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,13 @@ public function namespaceTopEdits(Request $request, User $user, Project $project
*/
$limit = $isSubRequest ? 10 : null;

$topEdits = new TopEdits($project, $user, $namespace, $limit);
$topEdits = new TopEdits($project, $user, null, $namespace, $limit);
$topEditsRepo = new TopEditsRepository();
$topEditsRepo->setContainer($this->container);
$topEdits->setRepository($topEditsRepo);

$topEdits->prepareData();

return $this->render('topedits/result_namespace.html.twig', [
'xtPage' => 'topedits',
'xtTitle' => $user->getUsername(),
Expand Down Expand Up @@ -168,21 +170,13 @@ protected function singlePageTopEdits(User $user, Project $project, $namespaceId
return $page;
}

// Get all revisions of this page by this user.
$revisionsData = $page->getRevisions($user);
// FIXME: add pagination.
$topEdits = new TopEdits($project, $user, $page);
$topEditsRepo = new TopEditsRepository();
$topEditsRepo->setContainer($this->container);
$topEdits->setRepository($topEditsRepo);

// Loop through all revisions and format dates, find totals, etc.
$totalAdded = 0;
$totalRemoved = 0;
$revisions = [];
foreach ($revisionsData as $revision) {
if ($revision['length_change'] > 0) {
$totalAdded += $revision['length_change'];
} else {
$totalRemoved += $revision['length_change'];
}
$revisions[] = new Edit($page, $revision);
}
$topEdits->prepareData();

// Send all to the template.
return $this->render('topedits/result_article.html.twig', [
Expand All @@ -191,10 +185,7 @@ protected function singlePageTopEdits(User $user, Project $project, $namespaceId
'project' => $project,
'user' => $user,
'page' => $page,
'total_added' => $totalAdded,
'total_removed' => $totalRemoved,
'revisions' => $revisions,
'revision_count' => count($revisions),
'te' => $topEdits,
]);
}

Expand Down Expand Up @@ -245,7 +236,7 @@ public function topEditsUserApiAction(Request $request, $namespace = 0, $article
$response->setEncodingOptions(JSON_NUMERIC_CHECK);

if ($article === '') {
$data = $topEdits->getTopEdits();
$data = $topEdits->getTopEditsNamespace();

if (is_numeric($namespace)) {
$data = $data[$namespace];
Expand Down
2 changes: 1 addition & 1 deletion src/AppBundle/Helper/AutomatedEditsHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ function ($tool) {
}
);

// If 'revert' is set to `true`, the use 'regex' as the regular expression,
// If 'revert' is set to `true`, then use 'regex' as the regular expression,
// otherwise 'revert' is assumed to be the regex string.
$this->revertTools[$projectDomain] = array_map(function ($revertTool) {
return [
Expand Down
Loading

0 comments on commit 09b1f0f

Please sign in to comment.