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

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 (
LoadSiteInformation,
)
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
......@@ -48,6 +45,6 @@ def load_prod():
LoadCountries(admin).load()
LoadLanguages().load()
LoadSiteInformation(admin).load()
LoadUniversitiesProd(admin).load()
# LoadUniversitiesProd().load()
# LoadUniversityEx(admin).load()
# LoadRecommendationLists(admin).load()
import logging
from os.path import abspath, join
from backend_app.load_data.utils import ASSETS_PATH, csv_2_dict_list
......@@ -9,56 +10,60 @@ from backend_app.models.university import University
from base_app.models import User
from .loadGeneric import LoadGeneric
logger = logging.getLogger("django")
class LoadUniversitiesProd(LoadGeneric):
"""
Load the universities in the app
"""
def __init__(self, admin: User):
self.admin = admin
def __init__(self):
self.admin = User.objects.get(username="admin")
@staticmethod
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)
def load(self):
for row in self.get_destination_data():
lat = round(float(row["lat"]), 6)
lon = round(float(row["lon"]), 6)
partner_id = int(row["partner_id"])
univ_id = int(row["univ_id"])
country = Country.objects.get(pk=row["code_iso"])
city = City.objects.update_or_create(name=row["ville"], country=country)[0]
self.add_info_and_save(city, self.admin)
logger.info("Partner : {} ---- univ: {}".format(partner_id, univ_id))
if univ_id == partner_id:
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(
pk=partner_id, # Not perfect but should do the trick
defaults={
"name": row["name"],
"acronym": row["acronym"],
"website": row["website"],
# "logo": row["logo"], # WARNING FIX BETA not ok
},
)[0]
self.add_info_and_save(univ, self.admin)
univ = University.objects.update_or_create(
pk=univ_id, # Not perfect but should do the trick
defaults={
"name": row["name"],
"acronym": row["acronym"],
"website": row["website"],
# "logo": row["logo"], # WARNING FIX BETA not ok
},
)[0]
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(
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)
else:
univ = University.objects.get(pk=univ_id)
partner = Partner.objects.get(utc_id=partner_id)
partner.university = univ
partner.save()
def run():
admin = User.objects.get(username="admin")
LoadUniversitiesProd(admin).load()
......@@ -18,6 +18,7 @@ import getActions from "../../redux/api/getActions";
import {compose} from "recompose";
import uuid from "uuid/v4";
import {UniversityHelper} from "../../redux/api/helpers";
import {getMostNRecentSemesters} from "../../utils/compareSemesters";
/**
* Class that handle all the filter manipulation with caching
......@@ -158,6 +159,15 @@ class FilterHandler {
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) {
const id = parseInt(univId);
return this.universityIdsCountries.get(id).id;
......@@ -249,6 +259,8 @@ class Filter extends CustomComponentForAPI {
static hasSelection = false;
static nbSelection = 0;
static hasBeenChanged = false;
static univHandler = undefined;
static values = {
......@@ -280,9 +292,19 @@ class Filter extends CustomComponentForAPI {
Filter.hasSelection = Object.values(Filter.values).some(arr => arr.length !== 0);
Filter.nbSelection = selectedUniversities.length;
this.props.saveSelection(Filter.hasSelection ? selectedUniversities : null);
Filter.hasBeenChanged = true;
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() {
if (!Filter.hasSelection) return "(Aucun filtre est actif)";
......@@ -295,7 +317,8 @@ class Filter extends CustomComponentForAPI {
customRender() {
const countriesOptions = this.univHandler.countriesOptions,
majorMinorOptions = this.univHandler.majorMinorOptions,
semestersOptions = this.univHandler.semesterOptions;
semestersOptions = this.univHandler.semesterOptions,
mostRecentSemesters = this.univHandler.defaultSemesters;
const {classes} = this.props;
......@@ -339,6 +362,7 @@ class Filter extends CustomComponentForAPI {
options={semestersOptions}
onChange={(selection) => this.updateSelectedUniversities("semesters", selection)}
cacheId={Filter.DOWNSHIFT_SEMESTERS_ID}
value={[...mostRecentSemesters].reverse()}
/>
</div>
<div className={classes.input}>
......@@ -348,6 +372,9 @@ class Filter extends CustomComponentForAPI {
onChange={(selection) => this.updateSelectedUniversities("majorMinors", selection)}
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>
</ExpansionPanelDetails>
</ExpansionPanel>
......
......@@ -13,6 +13,8 @@ import Typography from "@material-ui/core/Typography";
import {getUnivName} from "./PageMyExchanges";
import EditModuleCoursesFeedback from "../university/modules/previousExchangeFeedback/edit/EditModuleCoursesFeedback";
import {withStyles} from "@material-ui/styles";
import CustomLink from "../common/CustomLink";
import {APP_ROUTES} from "../../config/appRoutes";
function getExchangeId(props) {
return parseInt(props.match.params.exchangeId);
......@@ -37,12 +39,18 @@ class PageEditExchangeFeedbacks extends CustomComponentForAPI {
const {classes} = this.props,
id = getExchangeId(this.props),
exchange = this.getLatestReadData("exchange"),
univName = getUnivName(exchange.university);
univId = exchange.university,
univName = getUnivName(univId);
if (id) {
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><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 {
getAmounts() {
const {amountMin, amountMax} = this.props;
if (amountMax != null && amountMax != amountMin) {
return `${amountMin}${this.getSymbol()}${amountMax}${this.getSymbol()}`;
if (amountMax != null && amountMax !== amountMin) {
if (amountMin === null) {
return `⩽ ${amountMax}${this.getSymbol()}`;
} else {
return `${amountMin}${this.getSymbol()}${amountMax}${this.getSymbol()}`;
}
} else {
return `${amountMin}${this.getSymbol()}`;
}
......@@ -79,34 +83,39 @@ class Scholarship extends React.Component {
return `Monnaie non reconnue: ${currency}`;
}
if (amountMax != null && amountMax != amountMin) {
return `${convertedMin}€ – ${this.convertAmountToEur(amountMax)}€`;
if (amountMax !== null && amountMax !== amountMin) {
if (amountMin === null) {
return `⩽ ${this.convertAmountToEur(amountMax)}€`;
} else {
return `${convertedMin}€ – ${this.convertAmountToEur(amountMax)}€`;
}
} else {
return `${convertedMin}€`;
}
}
renderFinancialAdvantage() {
const {amountMin, currency, classes} = this.props;
const {amountMin, amountMax, currency, classes} = this.props;
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>
{
currency != "EUR" ?
currency !== "EUR" ?
<Typography
variant='caption'><em>( {this.getConvertedAmounts()}{" "}{this.getFrequency()})</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) {
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", () => {
expect(compareSemester(2019, "a", 2019, "a")).toBeCloseTo(0);
......@@ -15,3 +15,17 @@ test("Compare different year same semester", () => {
test("Both different", () => {
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
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