Commit 8bd21217 authored by Florent Chehab's avatar Florent Chehab
Browse files

tweaks( => v0.9.3): front filter & load prod

* Front Filter: default to the last 4 semesters available
* Tweaked load prod, removed load universities
* Tweaked loadUniversitiesProd to more correctly update universities
* Fixed scholarship not displaying max amount in some cases
* Added link from edit previous departure feedback to university
parent e5544326
Pipeline #43282 passed with stages
in 3 minutes and 52 seconds
...@@ -12,9 +12,6 @@ from backend_app.load_data.loading_scripts.loadSiteInformation import ( ...@@ -12,9 +12,6 @@ from backend_app.load_data.loading_scripts.loadSiteInformation import (
LoadSiteInformation, LoadSiteInformation,
) )
from backend_app.load_data.loading_scripts.loadUniversities import LoadUniversities from backend_app.load_data.loading_scripts.loadUniversities import LoadUniversities
from backend_app.load_data.loading_scripts.loadUniversitiesProd import (
LoadUniversitiesProd,
)
from backend_app.load_data.loading_scripts.loadUniversityEx import LoadUniversityEx from backend_app.load_data.loading_scripts.loadUniversityEx import LoadUniversityEx
...@@ -48,6 +45,6 @@ def load_prod(): ...@@ -48,6 +45,6 @@ def load_prod():
LoadCountries(admin).load() LoadCountries(admin).load()
LoadLanguages().load() LoadLanguages().load()
LoadSiteInformation(admin).load() LoadSiteInformation(admin).load()
LoadUniversitiesProd(admin).load() # LoadUniversitiesProd().load()
# LoadUniversityEx(admin).load() # LoadUniversityEx(admin).load()
# LoadRecommendationLists(admin).load() # LoadRecommendationLists(admin).load()
import logging
from os.path import abspath, join from os.path import abspath, join
from backend_app.load_data.utils import ASSETS_PATH, csv_2_dict_list from backend_app.load_data.utils import ASSETS_PATH, csv_2_dict_list
...@@ -9,56 +10,60 @@ from backend_app.models.university import University ...@@ -9,56 +10,60 @@ from backend_app.models.university import University
from base_app.models import User from base_app.models import User
from .loadGeneric import LoadGeneric from .loadGeneric import LoadGeneric
logger = logging.getLogger("django")
class LoadUniversitiesProd(LoadGeneric): class LoadUniversitiesProd(LoadGeneric):
""" """
Load the universities in the app Load the universities in the app
""" """
def __init__(self, admin: User): def __init__(self):
self.admin = admin self.admin = User.objects.get(username="admin")
@staticmethod @staticmethod
def get_destination_data(): def get_destination_data():
destinations_path = abspath(join(ASSETS_PATH, "beta-univs.csv")) destinations_path = abspath(join(ASSETS_PATH, "univsv0.9.3.csv"))
return csv_2_dict_list(destinations_path) return csv_2_dict_list(destinations_path)
def load(self): def load(self):
for row in self.get_destination_data(): for row in self.get_destination_data():
lat = round(float(row["lat"]), 6) partner_id = int(row["partner_id"])
lon = round(float(row["lon"]), 6) univ_id = int(row["univ_id"])
country = Country.objects.get(pk=row["code_iso"]) logger.info("Partner : {} ---- univ: {}".format(partner_id, univ_id))
city = City.objects.update_or_create(name=row["ville"], country=country)[0] if univ_id == partner_id:
self.add_info_and_save(city, self.admin) lat = round(float(row["lat"]), 6)
lon = round(float(row["lon"]), 6)
partner_id = row["id_etab"] country = Country.objects.get(pk=row["code_iso"])
city = City.objects.update_or_create(
name=row["ville"].title(), country=country
)[0]
self.add_info_and_save(city, self.admin)
univ = University.objects.update_or_create( univ = University.objects.update_or_create(
pk=partner_id, # Not perfect but should do the trick pk=univ_id, # Not perfect but should do the trick
defaults={ defaults={
"name": row["name"], "name": row["name"],
"acronym": row["acronym"], "acronym": row["acronym"],
"website": row["website"], "website": row["website"],
# "logo": row["logo"], # WARNING FIX BETA not ok # "logo": row["logo"], # WARNING FIX BETA not ok
}, },
)[0] )[0]
self.add_info_and_save(univ, self.admin) self.add_info_and_save(univ, self.admin)
main_campus = Campus.objects.update_or_create(
is_main_campus=True,
university=univ,
defaults=dict(
name="Campus - " + univ.name, city=city, lat=lat, lon=lon
),
)[0]
self.add_info_and_save(main_campus, self.admin)
main_campus = Campus.objects.update_or_create( else:
is_main_campus=True, univ = University.objects.get(pk=univ_id)
university=univ,
defaults=dict(
name="Campus - " + univ.name, city=city, lat=lat, lon=lon
),
)[0]
self.add_info_and_save(main_campus, self.admin)
partner = Partner.objects.get(utc_id=partner_id) partner = Partner.objects.get(utc_id=partner_id)
partner.university = univ partner.university = univ
partner.save() partner.save()
def run():
admin = User.objects.get(username="admin")
LoadUniversitiesProd(admin).load()
...@@ -18,6 +18,7 @@ import getActions from "../../redux/api/getActions"; ...@@ -18,6 +18,7 @@ import getActions from "../../redux/api/getActions";
import {compose} from "recompose"; import {compose} from "recompose";
import uuid from "uuid/v4"; import uuid from "uuid/v4";
import {UniversityHelper} from "../../redux/api/helpers"; import {UniversityHelper} from "../../redux/api/helpers";
import {getMostNRecentSemesters} from "../../utils/compareSemesters";
/** /**
* Class that handle all the filter manipulation with caching * Class that handle all the filter manipulation with caching
...@@ -158,6 +159,15 @@ class FilterHandler { ...@@ -158,6 +159,15 @@ class FilterHandler {
return FilterHandler._semesterOptions; return FilterHandler._semesterOptions;
} }
static _defaultSemesters = undefined;
get defaultSemesters() {
if (typeof FilterHandler._defaultSemesters === "undefined") {
FilterHandler._defaultSemesters = getMostNRecentSemesters(this.semesterOptions.map(el => el.value), 4);
}
return FilterHandler._defaultSemesters;
}
getCountryCodeForUniversity(univId) { getCountryCodeForUniversity(univId) {
const id = parseInt(univId); const id = parseInt(univId);
return this.universityIdsCountries.get(id).id; return this.universityIdsCountries.get(id).id;
...@@ -249,6 +259,8 @@ class Filter extends CustomComponentForAPI { ...@@ -249,6 +259,8 @@ class Filter extends CustomComponentForAPI {
static hasSelection = false; static hasSelection = false;
static nbSelection = 0; static nbSelection = 0;
static hasBeenChanged = false;
static univHandler = undefined; static univHandler = undefined;
static values = { static values = {
...@@ -280,9 +292,19 @@ class Filter extends CustomComponentForAPI { ...@@ -280,9 +292,19 @@ class Filter extends CustomComponentForAPI {
Filter.hasSelection = Object.values(Filter.values).some(arr => arr.length !== 0); Filter.hasSelection = Object.values(Filter.values).some(arr => arr.length !== 0);
Filter.nbSelection = selectedUniversities.length; Filter.nbSelection = selectedUniversities.length;
this.props.saveSelection(Filter.hasSelection ? selectedUniversities : null); this.props.saveSelection(Filter.hasSelection ? selectedUniversities : null);
Filter.hasBeenChanged = true;
this.forceUpdate(); this.forceUpdate();
} }
componentDidUpdate(prevProps, prevState, snapshot) {
super.componentDidUpdate(prevProps, prevState, snapshot);
if (Filter.univHandler){ // make sure it has been initialized elsewhere first
const mostRecentSemesters = this.univHandler.defaultSemesters;
// Set the default value for the filter
if (!Filter.hasBeenChanged) this.updateSelectedUniversities("semesters", mostRecentSemesters);
}
}
getEndMessage() { getEndMessage() {
if (!Filter.hasSelection) return "(Aucun filtre est actif)"; if (!Filter.hasSelection) return "(Aucun filtre est actif)";
...@@ -295,7 +317,8 @@ class Filter extends CustomComponentForAPI { ...@@ -295,7 +317,8 @@ class Filter extends CustomComponentForAPI {
customRender() { customRender() {
const countriesOptions = this.univHandler.countriesOptions, const countriesOptions = this.univHandler.countriesOptions,
majorMinorOptions = this.univHandler.majorMinorOptions, majorMinorOptions = this.univHandler.majorMinorOptions,
semestersOptions = this.univHandler.semesterOptions; semestersOptions = this.univHandler.semesterOptions,
mostRecentSemesters = this.univHandler.defaultSemesters;
const {classes} = this.props; const {classes} = this.props;
...@@ -339,6 +362,7 @@ class Filter extends CustomComponentForAPI { ...@@ -339,6 +362,7 @@ class Filter extends CustomComponentForAPI {
options={semestersOptions} options={semestersOptions}
onChange={(selection) => this.updateSelectedUniversities("semesters", selection)} onChange={(selection) => this.updateSelectedUniversities("semesters", selection)}
cacheId={Filter.DOWNSHIFT_SEMESTERS_ID} cacheId={Filter.DOWNSHIFT_SEMESTERS_ID}
value={[...mostRecentSemesters].reverse()}
/> />
</div> </div>
<div className={classes.input}> <div className={classes.input}>
...@@ -348,6 +372,9 @@ class Filter extends CustomComponentForAPI { ...@@ -348,6 +372,9 @@ class Filter extends CustomComponentForAPI {
onChange={(selection) => this.updateSelectedUniversities("majorMinors", selection)} onChange={(selection) => this.updateSelectedUniversities("majorMinors", selection)}
cacheId={Filter.DOWNSHIFT_MAJORS_ID} cacheId={Filter.DOWNSHIFT_MAJORS_ID}
/> />
<Typography variant={"caption"}>
Attention, en filtrant par filière, seuls les échanges déjà effectués sont pris en compte.
</Typography>
</div> </div>
</ExpansionPanelDetails> </ExpansionPanelDetails>
</ExpansionPanel> </ExpansionPanel>
......
...@@ -13,6 +13,8 @@ import Typography from "@material-ui/core/Typography"; ...@@ -13,6 +13,8 @@ import Typography from "@material-ui/core/Typography";
import {getUnivName} from "./PageMyExchanges"; import {getUnivName} from "./PageMyExchanges";
import EditModuleCoursesFeedback from "../university/modules/previousExchangeFeedback/edit/EditModuleCoursesFeedback"; import EditModuleCoursesFeedback from "../university/modules/previousExchangeFeedback/edit/EditModuleCoursesFeedback";
import {withStyles} from "@material-ui/styles"; import {withStyles} from "@material-ui/styles";
import CustomLink from "../common/CustomLink";
import {APP_ROUTES} from "../../config/appRoutes";
function getExchangeId(props) { function getExchangeId(props) {
return parseInt(props.match.params.exchangeId); return parseInt(props.match.params.exchangeId);
...@@ -37,12 +39,18 @@ class PageEditExchangeFeedbacks extends CustomComponentForAPI { ...@@ -37,12 +39,18 @@ class PageEditExchangeFeedbacks extends CustomComponentForAPI {
const {classes} = this.props, const {classes} = this.props,
id = getExchangeId(this.props), id = getExchangeId(this.props),
exchange = this.getLatestReadData("exchange"), exchange = this.getLatestReadData("exchange"),
univName = getUnivName(exchange.university); univId = exchange.university,
univName = getUnivName(univId);
if (id) { if (id) {
return ( return (
<> <>
<Typography variant={"h3"}>{univName} ({exchange.semester.toUpperCase()}{exchange.year})</Typography> <Typography variant={"h3"}>
{
univId ? <CustomLink to={APP_ROUTES.forUniversity(univId)}>{univName}</CustomLink>
:
univName
} ({exchange.semester.toUpperCase()}{exchange.year})</Typography>
<Typography variant={"h5"}>Page d'édition du feedback concernant votre échange.</Typography> <Typography variant={"h5"}>Page d'édition du feedback concernant votre échange.</Typography>
<Typography><em>Les informations issues de l'ENT (ECTS, etc.) sont modifiables uniquement depuis l'ENT.</em></Typography> <Typography><em>Les informations issues de l'ENT (ECTS, etc.) sont modifiables uniquement depuis l'ENT.</em></Typography>
......
...@@ -62,8 +62,12 @@ class Scholarship extends React.Component { ...@@ -62,8 +62,12 @@ class Scholarship extends React.Component {
getAmounts() { getAmounts() {
const {amountMin, amountMax} = this.props; const {amountMin, amountMax} = this.props;
if (amountMax != null && amountMax != amountMin) { if (amountMax != null && amountMax !== amountMin) {
return `${amountMin}${this.getSymbol()}${amountMax}${this.getSymbol()}`; if (amountMin === null) {
return `⩽ ${amountMax}${this.getSymbol()}`;
} else {
return `${amountMin}${this.getSymbol()}${amountMax}${this.getSymbol()}`;
}
} else { } else {
return `${amountMin}${this.getSymbol()}`; return `${amountMin}${this.getSymbol()}`;
} }
...@@ -79,34 +83,39 @@ class Scholarship extends React.Component { ...@@ -79,34 +83,39 @@ class Scholarship extends React.Component {
return `Monnaie non reconnue: ${currency}`; return `Monnaie non reconnue: ${currency}`;
} }
if (amountMax != null && amountMax != amountMin) { if (amountMax !== null && amountMax !== amountMin) {
return `${convertedMin}€ – ${this.convertAmountToEur(amountMax)}€`;
if (amountMin === null) {
return `⩽ ${this.convertAmountToEur(amountMax)}€`;
} else {
return `${convertedMin}€ – ${this.convertAmountToEur(amountMax)}€`;
}
} else { } else {
return `${convertedMin}€`; return `${convertedMin}€`;
} }
} }
renderFinancialAdvantage() { renderFinancialAdvantage() {
const {amountMin, currency, classes} = this.props; const {amountMin, amountMax, currency, classes} = this.props;
return ( return (
<> <>
{ {
amountMin !== null ? ( amountMin !== null || amountMax !== null ?
<> <>
<Typography className={classes.item} variant='h5'> Avantage financier : </Typography> <Typography className={classes.item} variant='h5'>Avantage financier :</Typography>
<Typography className={classes.textAmount}> {this.getAmounts()}{" "}{this.getFrequency()}</Typography> <Typography className={classes.textAmount}> {this.getAmounts()}{" "}{this.getFrequency()}</Typography>
{ {
currency != "EUR" ? currency !== "EUR" ?
<Typography <Typography
variant='caption'><em>( {this.getConvertedAmounts()}{" "}{this.getFrequency()})</em></Typography> variant='caption'><em>( {this.getConvertedAmounts()}{" "}{this.getFrequency()})</em></Typography>
: :
<></> <></>
} }
</> </>
) : ( :
<Typography variant='caption'><em>Aucun avantage financier est notifié.</em></Typography> <Typography variant='caption'><em>Aucun avantage financier est notifié.</em></Typography>
)
} }
</> </>
); );
......
...@@ -15,3 +15,17 @@ export default function compareSemesters(year1, period1, year2, period2) { ...@@ -15,3 +15,17 @@ export default function compareSemesters(year1, period1, year2, period2) {
return year1 - year2; return year1 - year2;
} }
} }
/**
*
* @param {Array.<String>} listOfSemesters
* @param {number} n
* @return {Array.<String>}
*/
export function getMostNRecentSemesters(listOfSemesters, n) {
const nToUse = Math.min(n, listOfSemesters.length);
const semesters = listOfSemesters.map(str => ({semester: str[0], year: str.slice(1, 5)}));
semesters.sort((a, b) => -compareSemesters(a.year, a.semester, b.year, b.semester));
return semesters.slice(0, nToUse).map(({semester, year}) => `${semester}${year}`);
}
\ No newline at end of file
import compareSemester from "../../src/utils/compareSemesters"; import compareSemester, {getMostNRecentSemesters} from "../../src/utils/compareSemesters";
test("Compare same", () => { test("Compare same", () => {
expect(compareSemester(2019, "a", 2019, "a")).toBeCloseTo(0); expect(compareSemester(2019, "a", 2019, "a")).toBeCloseTo(0);
...@@ -15,3 +15,17 @@ test("Compare different year same semester", () => { ...@@ -15,3 +15,17 @@ test("Compare different year same semester", () => {
test("Both different", () => { test("Both different", () => {
expect(compareSemester(2018, "p", 2019, "a")).toBeLessThan(0); expect(compareSemester(2018, "p", 2019, "a")).toBeLessThan(0);
}); });
test("Extract the correct list of semester", () => {
const listOfSemester = ["A2019", "A2014", "A2013", "A2012", "A2011",
"P2014", "P2009", "A2010", "A2009", "A2008", "P2012",
"P2011", "P2010", "P2015", "P2013", "A2018"];
const mostRecents = getMostNRecentSemesters(listOfSemester, 5);
expect(mostRecents[0]).toBe("A2019");
expect(mostRecents[1]).toBe("A2018");
expect(mostRecents[2]).toBe("P2015");
expect(mostRecents[3]).toBe("A2014");
expect(mostRecents[4]).toBe("P2014");
});
\ No newline at end of file
Supports Markdown
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