Skip to content

Commit

Permalink
Mega commit, contains fix #60, #59, #58, #57"
Browse files Browse the repository at this point in the history
> - #57, when multiple commits were conducted by the same user, the revert url redirect to history page so the reviewer can have a better overview.
>   we will further improve this with ROLLBACK feature or ADMIN notice feature in future release when we are granted Oauth
> - #58, package-lock.json rescyned by running `npm i`
> - #59, added template.env
> - #60, the error is caused by when ORES score is not available for an individual revision. We ignore them in this case.
  • Loading branch information
xinbenlv committed Aug 7, 2019
1 parent 5d37423 commit 0e5c6ec
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 35 deletions.
Binary file added assets/wikiloop-battlefield-logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 54 additions & 18 deletions components/NewRevisionCard.vue
Expand Up @@ -96,14 +96,13 @@
class="btn btn-sm" target="_blank"
>Should revert {{getJudgementCount(`ShouldRevert`)}}
</button>
<!-- TODO(xinbenlv, #57 https://github.com/google/wikiloop-battlefield/issues/57): temp disable revert per Grahamwp@'s report-->
<!-- <transition name="fade">-->
<!-- <button v-if="enableRevertRedirect()"-->
<!-- v-on:click="redirectToRevert()"-->
<!-- class="btn btn-outline-primary">-->
<!-- Go-->
<!-- </button>-->
<!-- </transition>-->
<transition name="fade">
<button v-if="enableRevertRedirect()"
v-on:click="redirectToRevert()"
class="btn btn-outline-primary">
Go
</button>
</transition>

</div>
</div>
Expand All @@ -118,7 +117,7 @@
<td class="col-4">
<router-link :to="`/marked/?userGaId=${judgement.userGaId}`" replace>
<object class="avatar-object" v-bind:data="`/api/avatar/${judgement.userGaId}`" ></object>
<span v-if="$cookies.get('_ga') === judgement.userGaId ">Me</span>
<span v-if="$cookiez.get('_ga') === judgement.userGaId ">Me</span>
<span v-else>Someone</span>
</router-link>
</td>
Expand Down Expand Up @@ -191,7 +190,17 @@
},
loadStiki: async function() {
console.log(`Load Stiki`);
let stikiRemote = this.stikiProp || await this.$axios.$get(`/extra/stiki/${this.wikiRevId}`);
let stikiRemote;
if (this.stikiProp) {
stikiRemote = this.stikiProp;
} else {
try {
await this.$axios.$get(`/extra/stiki/${this.wikiRevId}`);
} catch(err) {
// ignoring
stikiRemote = [];
}
}
if (stikiRemote.length) {
this.stiki = parseFloat(stikiRemote[0].SCORE);
} else {
Expand All @@ -201,7 +210,17 @@
},
loadCbng: async function() {
console.log(`Load CBNG for ${this.wikiRevId}`);
let cbngRemote = this.stikiProp || await this.$axios.$get(`/extra/cbng/${this.wikiRevId}`);
let cbngRemote;
if (this.cbngProp) {
cbngRemote = this.cbngProp;
} else {
try {
await this.$axios.$get(`/extra/cbng/${this.wikiRevId}`);
} catch(err) {
// ignoring
cbngRemote = [];
}
}
if (cbngRemote.length) {
this.cbng = parseFloat(cbngRemote[0].SCORE);
} else {
Expand All @@ -220,7 +239,7 @@
},
getMyJudgement: function() {
if (this.interaction) {
let myGaId = this.$cookies.get("_ga");
let myGaId = this.$cookiez.get("_ga");
let result = this.interaction.judgements.filter(j => j.userGaId === myGaId);
if (result.length === 1) {
return result[0].judgement;
Expand All @@ -238,19 +257,34 @@
}
});
return this.myJudgement === `ShouldRevert` && !this.isOverriden();
},
redirectToRevert: async function() {
if (this.myJudgement === `ShouldRevert` && !this.isOverriden()) {
const version = await this.$axios.$get(`/api/version`);
let url = `${this.getUrlBaseByWiki(this.revision.wiki)}/w/index.php?title=${this.revision.title}&action=edit&undoafter=${this.revision.parentid}&undo=${this.revision.revid}&summary=Identified as test/vandalism using [[:m:WikiLoop Battlefield]](version ${version}) at battlefield.wikiloop.org.`;
window.open(url, '_blank');
let revertUrl = `${this.getUrlBaseByWiki(this.revision.wiki)}/w/index.php?title=${this.revision.title}&action=edit&undoafter=${this.revision.parentid}&undo=${this.revision.revid}&summary=Identified as test/vandalism using [[:m:WikiLoop Battlefield]](version ${version}) at battlefield.wikiloop.org.`;
let historyUrl = `${this.getUrlBaseByWiki(this.revision.wiki)}/w/index.php?title=${this.revision.title}action=history`;
let result = await this.$axios.$get(`/api/mediawiki`, {params: {
wiki: this.revision.wiki,
apiQuery: {
action: "query",
format: "json",
prop: "revisions",
titles: this.revision.title,
rvlimit: 10,
}
}});
let revisions = Object.values(result.query.pages)[0].revisions;
if (revisions[1].user === revisions[0].user) {
window.open(historyUrl, '_blank');
} else {
window.open(revertUrl, '_blank');
}
}
},
interactionBtn: async function (myJudgement) {
this.myJudgement = myJudgement;
let revision = this.revision;
let gaId = this.$cookies.get("_ga");
let gaId = this.$cookiez.get("_ga");
let postBody = {
gaId: gaId, // Deprecated
userGaId: gaId,
Expand Down Expand Up @@ -300,8 +334,10 @@
this.interaction = this.interactionProp || await this.$axios.$get(`/api/interaction/${this.wikiRevId}`);
this.revision = this.revisionProp || await this.$axios.$get(`/api/revision/${this.wikiRevId}`);
this.ores = this.oresProp || await this.$axios.$get(`/api/ores/${this.wikiRevId}`);
await this.loadStiki();
await this.loadCbng();
if (this.$store.state.flags && this.$store.state.flags.useStiki) {
await this.loadStiki();
await this.loadCbng();
}
if (!this.diff) {
this.diff = await this.$axios.$get(`/api/diff/${this.wikiRevId}`);
}
Expand Down
6 changes: 3 additions & 3 deletions layouts/default.vue
Expand Up @@ -44,8 +44,8 @@
</b-navbar-nav>
<b-navbar-nav class="ml-auto">
<b-nav-item right href="#"><i class="fas fa-users"></i> Online ({{ liveUserCount }})</b-nav-item>
<b-nav-item :href="`/marked/?userGaId=${$cookies.get('_ga')}`" right>
<object class="avatar-navbar" v-bind:data="`/api/avatar/${$cookies.get('_ga')}`" ></object>Me
<b-nav-item :href="`/marked/?userGaId=${$cookiez.get('_ga')}`" right>
<object class="avatar-navbar" v-bind:data="`/api/avatar/${$cookiez.get('_ga')}`" ></object>Me
</b-nav-item>
</b-navbar-nav>
</b-collapse>
Expand Down Expand Up @@ -80,7 +80,7 @@
this.stats = await this.$axios.$get(`/api/stats`);
});
socket.on('interaction', async (interaction) => {
if (interaction.newJudgement.userGaId === this.$cookies.get('_ga')) {
if (interaction.newJudgement.userGaId === this.$cookiez.get('_ga')) {
this.$bvToast.toast(
`Your judgement for ${interaction.recentChange.title} for revision ${interaction.wikiRevId} is logged.`, {
title: 'Your Judgement',
Expand Down
5 changes: 1 addition & 4 deletions nuxt.config.js
Expand Up @@ -71,10 +71,7 @@ module.exports = {
['@nuxtjs/google-analytics', {
id: process.env.GA_ID
}],
{
src: 'nuxt-universal-cookies',
options: {}
}
['cookie-universal-nuxt', { alias: 'cookiez' }],
],
/*
** Axios module configuration
Expand Down
44 changes: 43 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -27,6 +27,7 @@
"bootstrap": "^4.1.3",
"bootstrap-vue": "^2.0.0-rc.24",
"cookie-parser": "^1.4.4",
"cookie-universal-nuxt": "^2.0.17",
"cross-env": "^5.2.0",
"csv-stringify": "^5.3.0",
"dotenv": "^7.0.0",
Expand All @@ -38,7 +39,6 @@
"mongodb": "^3.2.3",
"mysql2": "^1.6.5",
"nuxt": "^2.8.1",
"nuxt-universal-cookies": "0.0.5",
"querystring": "^0.2.0",
"request": "^2.88.0",
"request-promise": "^4.2.4",
Expand Down
4 changes: 2 additions & 2 deletions pages/leaderboard.vue
Expand Up @@ -29,14 +29,14 @@
</thead>
<tbody>
<template v-for="(leader, index) in leaderboard">
<tr v-bind:class="{ 'table-success': $cookies.get('_ga') == leader.userGaId }">
<tr v-bind:class="{ 'table-success': $cookiez.get('_ga') == leader.userGaId }">
<td scope="col">
{{index + 1}}
</td>
<td scope="col">
<router-link :to="`/marked/?userGaId=${leader.userGaId}`" replace>
<object class="avatar-object" v-bind:data="`/api/avatar/${leader.userGaId}`" ></object>
<span v-if="$cookies.get('_ga') === leader.userGaId ">Me</span>
<span v-if="$cookiez.get('_ga') === leader.userGaId ">Me</span>
<span v-else>Someone</span>
</router-link>
</td>
Expand Down
2 changes: 1 addition & 1 deletion pages/marked.vue
Expand Up @@ -18,7 +18,7 @@

<section>
<div class="container small-screen-padding" style="margin-top:80px">
<h4 v-if="$router.history.current.query.userGaId === $cookies.get('_ga')">My History</h4>
<h4 v-if="$router.history.current.query.userGaId === $cookiez.get('_ga')">My History</h4>
<h4 v-else >History</h4>
<div v-for="wikiRevId of wikiRevIds"
v-bind:key="wikiRevId"
Expand Down
39 changes: 34 additions & 5 deletions server/index.js
Expand Up @@ -33,10 +33,10 @@ const config = require('../nuxt.config.js');
config.dev = !(process.env.NODE_ENV === 'production');

function computeOresField(oresJson, wiki, revId) {
let damagingScore = oresJson.damagingScore || oresJson[wiki].scores[revId].damaging.score.probability.true;
let badfaithScore = oresJson.badfaithScore || oresJson[wiki].scores[revId].goodfaith.score.probability.false;
let damaging = oresJson.damaging || oresJson[wiki].scores[revId].damaging.score.prediction;
let badfaith = oresJson.badfaith || !oresJson[wiki].scores[revId].goodfaith.score.prediction;
let damagingScore = oresJson.damagingScore || (oresJson[wiki].scores[revId].damaging.score && oresJson[wiki].scores[revId].damaging.score.probability.true);
let badfaithScore = oresJson.badfaithScore || (oresJson[wiki].scores[revId].goodfaith.score && oresJson[wiki].scores[revId].goodfaith.score.probability.false);
let damaging = oresJson.damaging || (oresJson[wiki].scores[revId].damaging.score && oresJson[wiki].scores[revId].damaging.score.prediction);
let badfaith = oresJson.badfaith || (oresJson[wiki].scores[revId].goodfaith.score && !oresJson[wiki].scores[revId].goodfaith.score.prediction);
return {
wikiRevId: `${wiki}:${revId}`,
damagingScore: damagingScore,
Expand Down Expand Up @@ -1166,6 +1166,33 @@ function setupApiRequestListener(db, io, app) {

}));

apiRouter.get('/flags', (req, res, next) => {
let useStiki = (process.env.STIKI_MYSQL && process.env.STIKI_MYSQL.length > 0) || false;
res.send({
useStiki: useStiki
});
req.visitor
.event({ec: "api", ea: "/"})
.send();
});

apiRouter.get('/mediawiki', asyncHandler(async (req, res) => {
// TODO add sanitize if we see abuse.
apiLogger.debug('req.params:', req.params);
apiLogger.debug('req.query:', req.query);
const fetchUrl = new URL(`${getUrlBaseByWiki(req.query.wiki)}/w/api.php`);
let params = JSON.parse(req.query.apiQuery);

Object.keys(params).forEach(key => {
fetchUrl.searchParams.set(key, params[key]);
});
let retJson = await rp.get(fetchUrl, {json: true});
res.send(retJson);
req.visitor
.event({ec: "mediawiki", ea: "/"})
.send();
}));

apiRouter.get('/version', (req, res, next) => {
var packageson = require('./../package.json');
res.send(packageson.version);
Expand Down Expand Up @@ -1306,7 +1333,9 @@ async function start() {
setupIoSocketListener(io);
setupMediaWikiListener(db, io);
setupApiRequestListener(db, io, app);
await setupSTikiApiLisenter(app);
if (process.env.STIKI_MYSQL) {
await setupSTikiApiLisenter(app);
}

// Give nuxt middleware to express
app.use(nuxt.render);
Expand Down
20 changes: 20 additions & 0 deletions store/flags.js
@@ -0,0 +1,20 @@
export const state = () => ({
flags: null
});

export const mutations = {
setFlags (state, flagObject) {
state.flags = flagObject;
},
clearFlags (state, ) {
state.flags = null
},

};

export const actions = {
async nuxtServerInit({ commit, state }) {
const flags = await this.$axios.$get(`/api/flags`);
commit('setFlags', flags);
}
};
12 changes: 12 additions & 0 deletions template.env
@@ -0,0 +1,12 @@
# this file was created automatically by heroku-config
AXIOS_BASE_URL="http://localhost:3000"
# This is our GAID for dev
GA_ID=UA-122681777-3
HOST="0.0.0.0"
NPM_CONFIG_PRODUCTION=false

# This can be automatically filled in when you have a mlab add-on enabled for Heroku
# MONGODB_URI=

# We will work with STIKI Author to work out a public solution
# STIKI_MYSQL=

0 comments on commit 0e5c6ec

Please sign in to comment.