Commit b5895a1b authored by Adrien Pavie's avatar Adrien Pavie

Merge branch 'develop'

parents ce4377b0 a75b4730
......@@ -80,10 +80,13 @@ class App {
});
const params = readURLParams(window.location.href);
if(params.oauth_token) {
this.auth.bootstrapToken(params.oauth_token, () => {
const token = params.oauth_token || localStorage.getItem("oauth_token") || null;
if(token) {
this.auth.bootstrapToken(token, () => {
this._checkAuth();
window.history.pushState({}, "", window.location.href.replace("?oauth_token="+params.oauth_token, ""));
window.history.pushState({}, "", window.location.href.replace("?oauth_token="+token, ""));
localStorage.setItem("oauth_token", token);
});
}
else {
......@@ -111,6 +114,7 @@ class App {
}
this.user = null;
localStorage.removeItem("oauth_token");
PubSub.publish("USER.INFO.READY", this.user);
});
......
......@@ -445,6 +445,37 @@ class API {
});
}
/**
* Get mission statistics for given user
* @param {int} mid The mission ID
* @param {int} uid The user ID
* @return {Promise} A promise resolving on features statistics
*/
static GetMissionUserStatistics(mid, uid) {
return new Promise((resolve, reject) => {
request(CONST.P4R_URL + '/missions/' + mid + '/stats/' + uid, (err, res, body) => {
if(err) {
reject(err);
}
else {
try {
const data = typeof body === "string" ? JSON.parse(body) : body;
if(data.error) {
reject(new Error(data.error));
}
else {
resolve(data);
}
}
catch(e) {
reject(e);
}
}
});
});
}
/**
* Get missing pictures
* @return {Promise} A promise resolving on pictures list
......
......@@ -16,9 +16,9 @@ import Map from './MissionReviewMapComponent';
import Markdown from 'react-markdown';
import Paper from 'material-ui/Paper';
import Question from './MissionReviewQuestionComponent';
import Statistics from './MissionReviewStatisticsComponent';
import Tooltip from 'material-ui/Tooltip';
import Tags from './MissionReviewTagsComponent';
import Typography from 'material-ui/Typography';
const PICTURE_HEIGHT = { "xs": 400, "sm": 500, "md": 600, "lg": 700, "xl": 800 };
const BANNER_HEIGHT = { "xs": 150, "sm": 150, "md": 200, "lg": 200, "xl": 200 };
......@@ -40,13 +40,14 @@ class MissionReviewComponent extends Component {
currentPictureId: null,
clickedPictureId: null,
prevFeature: null,
count: parseInt(sessionStorage.getItem(EDITS_COUNT)) || 0,
count: null,
firstReview: false,
openEditors: false,
editorsAnchor: null,
currentAnswer: null,
openConfirmEdit: false,
hideConfirmEdit: false
hideConfirmEdit: false,
stats: {}
};
this.psTokens = {};
......@@ -60,7 +61,12 @@ class MissionReviewComponent extends Component {
wasSkipped = wasSkipped || false;
const prevCoords = !wasSkipped && this.state.feature !== null ? this.state.feature.coordinates : null;
this.setState({ feature: null, currentPictureId: null, clickedPictureId: null, prevFeature: this.state.feature, currentAnswer: null });
this.setState({
feature: null, currentPictureId: null, clickedPictureId: null,
prevFeature: this.state.feature, currentAnswer: null,
count: parseInt(sessionStorage.getItem(EDITS_COUNT+"_"+this.props.mission.id)) || 0
});
PubSub.publish("UI.MESSAGE.WAIT", { message: I18n.t("Retrieving next feature to review") });
API.GetMissionNextFeature(this.props.mission.id, prevCoords)
......@@ -76,6 +82,12 @@ class MissionReviewComponent extends Component {
if(!f.pictures || f.pictures.length === 0) {
PubSub.publish("UI.MESSAGE.BASIC", { type: "info", message: I18n.t("No pictures available around this feature") });
}
//Load user statistics for this mission
API.GetMissionUserStatistics(this.props.mission.id, this.props.user.id)
.then(s => {
this.setState({ stats: s });
});
}
else {
PubSub.publish("UI.MESSAGE.WAITDONE");
......@@ -332,9 +344,7 @@ class MissionReviewComponent extends Component {
<Markdown className={this.props.classes.root} source={this.props.mission.description.full} />
</div>;
const counter = <Typography variant="body1" align="center">
{I18n.t({zero: "You're doing your first edit !", one: "You have done one edit !", other: "You have done %{count} edits !"}, {count: this.state.count})}
</Typography>;
const counter = <Statistics count={this.state.count} data={this.state.stats} />;
return <div style={this.props.style} ref="container">
<Grid container spacing={8}>
......@@ -395,8 +405,8 @@ class MissionReviewComponent extends Component {
<Grid item xs={12} hidden={{ smUp: true }}>
{map}
<Hidden only="xs">{instructions}</Hidden>
{counter}
{instructions}
</Grid>
</Grid>
......@@ -443,7 +453,7 @@ class MissionReviewComponent extends Component {
PubSub.publish("UI.MESSAGE.BASIC", { type: "info", message: goMessages[nextState.count].msg, smiley: goMessages[nextState.count].sml, duration: 6000 });
}
sessionStorage.setItem(EDITS_COUNT, nextState.count);
sessionStorage.setItem(EDITS_COUNT+"_"+this.props.mission.id, nextState.count);
}
}
......
import React, { Component } from 'react';
import { Account, ArrowUpBold, Pencil, Run, RunFast } from 'mdi-material-ui';
import Grid from 'material-ui/Grid';
import Tooltip from 'material-ui/Tooltip';
import Typography from 'material-ui/Typography';
/**
* Mission review statistics component show user statistics for one mission.
*/
class MissionReviewStatisticsComponent extends Component {
render() {
return <div>
<Typography variant="subheading">{I18n.t("Amount of edits")}</Typography>
<Grid container direction="column" justify="flex-start" alignItems="flex-start">
{this.props.data && this.props.data.next !== undefined && <Grid item>
<RunFast style={{verticalAlign: "middle"}} />
<ArrowUpBold style={{verticalAlign: "middle", color: "green"}} />
{I18n.t("%{count} to overtake next user", { count: this.props.data.next })}
</Grid>}
{this.props.count !== null && <Grid item>
<Account style={{verticalAlign: "middle"}} />
<Pencil style={{verticalAlign: "middle", color: "grey"}} />
{I18n.t("%{count} since you started", { count: this.props.count })}
&nbsp;
{this.props.data && this.props.data.place !== undefined && I18n.t("(ranked #%{rank})", { rank: this.props.data.place })}
</Grid>}
{this.props.data && this.props.data.prev !== undefined && <Grid item>
<Run style={{verticalAlign: "middle"}} />
<ArrowUpBold style={{verticalAlign: "middle", color: "red"}} />
{I18n.t("%{count} before previous user passes you", { count: this.props.data.prev })}
</Grid>}
</Grid>
</div>;
}
}
export default MissionReviewStatisticsComponent;
......@@ -30,9 +30,9 @@ class MissionSummaryComponent extends Component {
{THEMES[this.props.mission.theme].icon}
</Tooltip>
<Tooltip title={EDITORS[this.props.mission.options.canEdit].name}>
{this.props.mission.options.canEdit && <Tooltip title={EDITORS[this.props.mission.options.canEdit].name}>
{EDITORS[this.props.mission.options.canEdit].icon}
</Tooltip>
</Tooltip>}
</span>
</Typography>
......
......@@ -272,31 +272,9 @@ class NewMissionComponent extends Component {
API.GetMissionLoading(pictoken)
.then(loading => {
if(loading >= 100) {
//Get details
API.GetMissionDetails(mid)
.then(mission => {
//And publish
mission.status = "online";
API.UpdateMission(mission, this.props.user.name, this.props.user.id)
.then(() => {
PubSub.publish("UI.MESSAGE.WAITDONE");
PubSub.publish("UI.MESSAGE.BASIC", { type: "info", message: I18n.t("Your mission was succesfully created !") });
this.props.history.push("/mission/"+mid);
})
.catch(e => {
console.log("Failed updating");
console.error(e);
PubSub.publish("UI.MESSAGE.WAITDONE");
PubSub.publish("UI.MESSAGE.BASIC", { type: "error", message: I18n.t("Oops ! Something went wrong when creating the mission") });
});
})
.catch(e => {
console.log("Failed getting details");
console.error(e);
PubSub.publish("UI.MESSAGE.WAITDONE");
PubSub.publish("UI.MESSAGE.BASIC", { type: "error", message: I18n.t("Oops ! Something went wrong when creating the mission") });
});
PubSub.publish("UI.MESSAGE.WAITDONE");
PubSub.publish("UI.MESSAGE.BASIC", { type: "info", message: I18n.t("Your mission was succesfully created !") });
this.props.history.push("/mission/"+mid);
}
else {
PubSub.publish("UI.MESSAGE.WAIT", { progress: loading });
......
......@@ -122,11 +122,6 @@
"edit_this_feature_with_an_openstreetmap_editor_4522da18": "Edit this feature with an OpenStreetMap editor",
"validate_fdf76f9d": "Validate",
"mark_the_feature_as_done_when_you_have_edited_open_378db828": "Mark the feature as done when you have edited OpenStreetMap",
"you_have_done_count_edits_7c6397df": {
"zero": "You're doing your first edit !",
"one": "You have done one edit !",
"other": "You have done %{count} edits !"
},
"you_made_you_first_edit_great_e2ee0245": "You made you first edit, great !",
"10_edits_keep_going_1ed4d47c": "10 edits, keep going !",
"30_edits_not_bad_d37dbf98": "30 edits, not bad",
......@@ -155,6 +150,11 @@
"this_need_an_advanced_edit_2cdafa13": "This need an advanced edit !",
"edit_the_feature_according_to_mission_description__7aa23328": "Edit the feature according to mission description below",
"details_98a31b68": "Details",
"amount_of_edits_5729a31b": "Amount of edits",
"count_to_overtake_next_user_9002b5af": "%{count} to overtake next user",
"count_since_you_started_7a4b2fa1": "%{count} since you started",
"ranked_rank_151814b0": "(ranked #%{rank})",
"count_before_previous_user_passes_you_8b96b12d": "%{count} before previous user passes you",
"key_f2a919d5": "Key",
"value_d842f16d": "Value",
"oops_can_t_get_statistics_for_this_mission_5d88085b": "Oops ! Can't get statistics for this mission",
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment