Commit 59c8c491 authored by Segolene Brisemeur's avatar Segolene Brisemeur Committed by Florent Chehab

feature(language storing)

* Added language model
* Added CSV data and loading script
* Language stored in course feedback

Fixes #116
Fixes #32 (Not really fixed, but language now store in feedback)
parent c2c2f7d4
Pipeline #40482 passed with stages
in 3 minutes and 41 seconds
"code_iso","name"
"aa","Afar"
"ab","Abkhaze"
"ae","Avestique"
"af","Afrikaans"
"ak","Akan"
"am","Amharique"
"an","Aragonais"
"ar","Arabe"
"as","Assamais"
"av","Avar"
"ay","Aymara"
"az","Azéri"
"ba","Bachkir"
"be","Biélorusse"
"bg","Bulgare"
"bh","Bihari"
"bi","Bichelamar"
"bm","Bambara"
"bn","Bengali"
"bo","Tibétain"
"br","Breton"
"bs","Bosnien"
"ca","Catalan"
"ce","Tchétchène"
"ch","Chamorro"
"co","Corse"
"cr","Cri"
"cs","Tchèque"
"cu","Vieux-slave"
"cv","Tchouvache"
"cy","Gallois"
"da","Danois"
"de","Allemand"
"dv","Maldivien"
"dz","Dzongkha"
"ee","Ewe"
"el","Grec moderne"
"en","Anglais"
"eo","Espéranto"
"es","Espagnol"
"et","Estonien"
"eu","Basque"
"fa","Persan"
"ff","Peul"
"fi","Finnois"
"fj","Fidjien"
"fo","Féroïen"
"fr","Français"
"fy","Frison occidental"
"ga","Irlandais"
"gd","Écossais"
"gl","Galicien"
"gn","Guarani"
"gu","Gujarati"
"gv","Mannois"
"ha","Haoussa"
"he","Hébreu"
"hi","Hindi"
"ho","Hiri motu"
"hr","Croate"
"ht","Créole haïtien"
"hu","Hongrois"
"hy","Arménien"
"hz","Héréro"
"ia","Interlingua"
"id","Indonésien"
"ie","Occidental"
"ig","Igbo"
"ii","Yi"
"ik","Inupiak"
"io","Ido"
"is","Islandais"
"it","Italien"
"iu","Inuktitut"
"ja","Japonais"
"jv","Javanais"
"ka","Géorgien"
"kg","Kikongo"
"ki","Kikuyu"
"kj","Kuanyama"
"kk","Kazakh"
"kl","Groenlandais"
"km","Khmer"
"kn","Kannada"
"ko","Coréen"
"kr","Kanouri"
"ks","Cachemiri"
"ku","Kurde"
"kv","Komi"
"kw","Cornique"
"ky","Kirghiz"
"la","Latin"
"lb","Luxembourgeois"
"lg","Ganda"
"li","Limbourgeois"
"ln","Lingala"
"lo","Lao"
"lt","Lituanien"
"lu","Luba"
"lv","Letton"
"mg","Malgache"
"mh","Marshallais"
"mi","Maori de Nouvelle-Zélande"
"mk","Macédonien"
"ml","Malayalam"
"mn","Mongol"
"mo","Moldave"
"mr","Marathi"
"ms","Malais"
"mt","Maltais"
"my","Birman"
"na","Nauruan"
"nb","Norvégien Bokmål"
"nd","Sindebele"
"ne","Népalais"
"ng","Ndonga"
"nl","Néerlandais"
"nn","Norvégien Nynorsk"
"no","Norvégien"
"nr","Nrebele"
"nv","Navajo"
"ny","Chichewa"
"oc","Occitan"
"oj","Ojibwé"
"om","Oromo"
"or","Oriya"
"os","Ossète"
"pa","Pendjabi"
"pi","Pali"
"pl","Polonais"
"ps","Pachto"
"pt","Portugais"
"qu","Quechua"
"rc","Créole Réunionnais"
"rm","Romanche"
"rn","Kirundi"
"ro","Roumain"
"ru","Russe"
"rw","Kinyarwanda"
"sa","Sanskrit"
"sc","Sarde"
"sd","Sindhi"
"se","Same du Nord"
"sg","Sango"
"sh","Serbo-croate"
"si","Cingalais"
"sk","Slovaque"
"sl","Slovène"
"sm","Samoan"
"sn","Shona"
"so","Somali"
"sq","Albanais"
"sr","Serbe"
"ss","Swati"
"st","Sotho du Sud"
"su","Soundanais"
"sv","Suédois"
"sw","Swahili"
"ta","Tamoul"
"te","Télougou"
"tg","Tadjik"
"th","Thaï"
"ti","Tigrigna"
"tk","Turkmène"
"tl","Tagalog"
"tn","Tswana"
"to","Tongien"
"tr","Turc"
"ts","Tsonga"
"tt","Tatar"
"tw","Twi"
"ty","Tahitien"
"ug","Ouïghour"
"uk","Ukrainien"
"ur","Ourdou"
"uz","Ouzbek"
"ve","Venda"
"vi","Vietnamien"
"vo","Volapük"
"wa","Wallon"
"wo","Wolof"
"xh","Xhosa"
"yi","Yiddish"
"yo","Yoruba"
"za","Zhuang"
"zh","Chinois"
"zu","Zoulou"
\ No newline at end of file
...@@ -4,6 +4,7 @@ from backend_app.load_data.loading_scripts.loadAdminUser import LoadAdminUser ...@@ -4,6 +4,7 @@ from backend_app.load_data.loading_scripts.loadAdminUser import LoadAdminUser
from backend_app.load_data.loading_scripts.loadCountries import LoadCountries from backend_app.load_data.loading_scripts.loadCountries import LoadCountries
from backend_app.load_data.loading_scripts.loadCurrencies import LoadCurrencies from backend_app.load_data.loading_scripts.loadCurrencies import LoadCurrencies
from backend_app.load_data.loading_scripts.loadGroups import LoadGroups from backend_app.load_data.loading_scripts.loadGroups import LoadGroups
from backend_app.load_data.loading_scripts.loadLanguages import LoadLanguages
from backend_app.load_data.loading_scripts.loadTags import LoadTags from backend_app.load_data.loading_scripts.loadTags import LoadTags
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.loadUniversityEx import LoadUniversityEx from backend_app.load_data.loading_scripts.loadUniversityEx import LoadUniversityEx
...@@ -21,4 +22,5 @@ def load_all(): ...@@ -21,4 +22,5 @@ def load_all():
LoadCountries(admin).load() LoadCountries(admin).load()
LoadUniversities(admin).load() LoadUniversities(admin).load()
LoadTags(admin).load() LoadTags(admin).load()
LoadLanguages().load()
LoadUniversityEx(admin).load() LoadUniversityEx(admin).load()
import csv
from os.path import join, abspath
from backend_app.load_data.utils import ASSETS_PATH
from backend_app.models.language import Language
from .loadGeneric import LoadGeneric
class LoadLanguages(LoadGeneric):
"""
Load languages in the app
"""
def load(self):
languages_file_loc = abspath(join(ASSETS_PATH, "languages.csv"))
with open(languages_file_loc) as csvfile:
reader = csv.reader(csvfile, quotechar='"')
next(reader)
for r in reader:
Language.objects.create(code_iso=r[0], name=r[1])
...@@ -7,6 +7,7 @@ from backend_app.models.courseFeedback import CourseFeedback ...@@ -7,6 +7,7 @@ from backend_app.models.courseFeedback import CourseFeedback
from backend_app.models.currency import Currency from backend_app.models.currency import Currency
from backend_app.models.exchange import Exchange from backend_app.models.exchange import Exchange
from backend_app.models.exchangeFeedback import ExchangeFeedback from backend_app.models.exchangeFeedback import ExchangeFeedback
from backend_app.models.language import Language
from backend_app.models.tag import Tag from backend_app.models.tag import Tag
from backend_app.models.university import University from backend_app.models.university import University
from backend_app.models.universityDri import UniversityDri from backend_app.models.universityDri import UniversityDri
...@@ -159,6 +160,7 @@ class LoadUniversityEx(LoadGeneric): ...@@ -159,6 +160,7 @@ class LoadUniversityEx(LoadGeneric):
CourseFeedback.objects.update_or_create( CourseFeedback.objects.update_or_create(
course=course1, course=course1,
defaults=dict( defaults=dict(
language=Language.objects.first(),
comment="Trop bien", comment="Trop bien",
adequation=5, adequation=5,
working_dose=4, working_dose=4,
......
# Generated by Django 2.1.7 on 2019-05-25 13:22
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [("backend_app", "0007_file_picture")]
operations = [
migrations.CreateModel(
name="Language",
fields=[
(
"code_iso",
models.CharField(max_length=5, primary_key=True, serialize=False),
),
("name", models.CharField(max_length=100)),
],
options={"abstract": False},
),
migrations.AddField(
model_name="coursefeedback",
name="language",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="courses",
to="backend_app.Language",
),
),
]
...@@ -3,12 +3,16 @@ from django.db import models ...@@ -3,12 +3,16 @@ from django.db import models
from backend_app.models.abstract.essentialModule import EssentialModule from backend_app.models.abstract.essentialModule import EssentialModule
from backend_app.models.course import Course from backend_app.models.course import Course
from backend_app.models.language import Language
class CourseFeedback(EssentialModule): class CourseFeedback(EssentialModule):
course = models.OneToOneField( course = models.OneToOneField(
Course, on_delete=models.CASCADE, default=0, related_name="course_feedback" Course, on_delete=models.CASCADE, default=0, related_name="course_feedback"
) )
language = models.ForeignKey(
Language, on_delete=models.SET_NULL, related_name="courses", null=True
)
comment = models.TextField(null=True, max_length=1500) comment = models.TextField(null=True, max_length=1500)
adequation = models.IntegerField( adequation = models.IntegerField(
default=0, validators=[MaxValueValidator(5), MinValueValidator(-5)] default=0, validators=[MaxValueValidator(5), MinValueValidator(-5)]
......
from django.db import models
from backend_app.models.abstract.base import (
BaseModel,
BaseModelSerializer,
BaseModelViewSet,
)
from backend_app.permissions.app_permissions import IsStaff, ReadOnly
class Language(BaseModel):
code_iso = models.CharField(max_length=5, primary_key=True)
name = models.CharField(max_length=100, blank=False)
class LanguageSerializer(BaseModelSerializer):
class Meta:
model = Language
fields = BaseModelSerializer.Meta.fields + ("name",)
class LanguageViewSet(BaseModelViewSet):
serializer_class = LanguageSerializer
queryset = Language.objects.all() # pylint: disable=E1101
end_point_route = "languages"
permission_classes = (IsStaff | ReadOnly,)
...@@ -9,6 +9,7 @@ class CourseFeedbackSerializer(EssentialModuleSerializer): ...@@ -9,6 +9,7 @@ class CourseFeedbackSerializer(EssentialModuleSerializer):
class Meta: class Meta:
model = CourseFeedback model = CourseFeedback
fields = EssentialModuleSerializer.Meta.fields + ( fields = EssentialModuleSerializer.Meta.fields + (
"language",
"comment", "comment",
"adequation", "adequation",
"working_dose", "working_dose",
......
...@@ -21,6 +21,7 @@ from backend_app.models.exchangeFeedback import ExchangeFeedbackViewSet ...@@ -21,6 +21,7 @@ from backend_app.models.exchangeFeedback import ExchangeFeedbackViewSet
from backend_app.models.file_picture import FileViewSet, PictureViewSet from backend_app.models.file_picture import FileViewSet, PictureViewSet
from backend_app.models.for_testing.moderation import ForTestingModerationViewSet from backend_app.models.for_testing.moderation import ForTestingModerationViewSet
from backend_app.models.for_testing.versioning import ForTestingVersioningViewSet from backend_app.models.for_testing.versioning import ForTestingVersioningViewSet
from backend_app.models.language import LanguageViewSet
from backend_app.models.offer import OfferViewSet from backend_app.models.offer import OfferViewSet
from backend_app.models.pendingModeration import ( from backend_app.models.pendingModeration import (
PendingModerationViewSet, PendingModerationViewSet,
...@@ -63,6 +64,7 @@ ALL_API_VIEWSETS = [ ...@@ -63,6 +64,7 @@ ALL_API_VIEWSETS = [
CurrencyViewSet, CurrencyViewSet,
DepartmentViewSet, DepartmentViewSet,
OfferViewSet, OfferViewSet,
LanguageViewSet,
PendingModerationViewSet, PendingModerationViewSet,
PendingModerationObjViewSet, PendingModerationObjViewSet,
FileViewSet, FileViewSet,
......
...@@ -60,10 +60,12 @@ App.propTypes = { ...@@ -60,10 +60,12 @@ App.propTypes = {
}; };
// Already load some of the data even if it's not use here. // Already load some of the data even if it's not use here.
// /!\ Don't delete it
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
countries: state.api.countriesAll, countries: state.api.countriesAll,
currencies: state.api.currenciesAll, currencies: state.api.currenciesAll,
languages: state.api.languagesAll,
serverModerationStatus: state.api.serverModerationStatusAll, serverModerationStatus: state.api.serverModerationStatusAll,
}; };
}; };
...@@ -73,6 +75,7 @@ const mapDispatchToProps = (dispatch) => { ...@@ -73,6 +75,7 @@ const mapDispatchToProps = (dispatch) => {
api: { api: {
countries: () => dispatch(getActions("countries").readAll()), countries: () => dispatch(getActions("countries").readAll()),
currencies: () => dispatch(getActions("currencies").readAll()), currencies: () => dispatch(getActions("currencies").readAll()),
languages: () => dispatch(getActions("languages").readAll()),
serverModerationStatus: () => dispatch(getActions("serverModerationStatus").readAll()), // not needed for server moderation status serverModerationStatus: () => dispatch(getActions("serverModerationStatus").readAll()), // not needed for server moderation status
}, },
}; };
......
...@@ -9,6 +9,7 @@ import TableRow from "@material-ui/core/TableRow"; ...@@ -9,6 +9,7 @@ import TableRow from "@material-ui/core/TableRow";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import compose from "recompose/compose"; import compose from "recompose/compose";
import withStyles from "@material-ui/core/styles/withStyles"; import withStyles from "@material-ui/core/styles/withStyles";
import {getLatestReadDataFromStore} from "../../../redux/api/utils";
const styles = theme => ({ const styles = theme => ({
...@@ -24,6 +25,8 @@ class CourseFeedback extends Component { ...@@ -24,6 +25,8 @@ class CourseFeedback extends Component {
render() { render() {
const {classes, exchangeCourses} = this.props; const {classes, exchangeCourses} = this.props;
const languages = getLatestReadDataFromStore("languagesAll");
return ( return (
<> <>
<Table className={classes.table}> <Table className={classes.table}>
...@@ -43,7 +46,14 @@ class CourseFeedback extends Component { ...@@ -43,7 +46,14 @@ class CourseFeedback extends Component {
<TableRow key={idx}> <TableRow key={idx}>
<TableCell scope="course">{course.code}</TableCell> <TableCell scope="course">{course.code}</TableCell>
<TableCell>{course.nb_credit}</TableCell> <TableCell>{course.nb_credit}</TableCell>
<TableCell>langue</TableCell> <TableCell>
{
course.course_feedback.language ?
languages.find(lang => lang.id === course.course_feedback.language).name
:
<span>Non spécifié</span>
}
</TableCell>
<TableCell>{course.course_feedback.adequation}</TableCell> <TableCell>{course.course_feedback.adequation}</TableCell>
<TableCell>{course.course_feedback.working_dose}</TableCell> <TableCell>{course.course_feedback.working_dose}</TableCell>
<TableCell>{course.course_feedback.language_following_ease}</TableCell> <TableCell>{course.course_feedback.language_following_ease}</TableCell>
......
...@@ -20,15 +20,24 @@ const styles = theme => ({ ...@@ -20,15 +20,24 @@ const styles = theme => ({
paper: { paper: {
margin: `${theme.spacing.unit}px auto`, margin: `${theme.spacing.unit}px auto`,
padding: theme.spacing.unit * 2, padding: theme.spacing.unit * 2,
width: "80%",
}, },
paperGrid: { paperGrid: {
textAlign: "center", textAlign: "center",
padding: theme.spacing.unit * 3, padding: theme.spacing.unit * 3,
width: "100%", width: "100%",
background: "#767676", background: "#9EBFF8",
}, },
gradingDiv: { gradingDiv: {
margin: theme.spacing.unit, margin: `${theme.spacing.unit}px auto`,
width: "80%",
},
chip: {
marginTop: theme.spacing.unit * 5,
},
expansionPanel:{
margin: `${theme.spacing.unit}px auto`,
width: "80%",
} }
}); });
...@@ -121,7 +130,7 @@ class PreviousDeparture extends React.Component { ...@@ -121,7 +130,7 @@ class PreviousDeparture extends React.Component {
<TruncatedCommentaryOrMore commentary={rawModelData.general_comment}/> <TruncatedCommentaryOrMore commentary={rawModelData.general_comment}/>
</Paper> </Paper>
<ExpansionPanel> <ExpansionPanel className={classes.expansionPanel}>
<ExpansionPanelSummary expandIcon={<ExpandMoreIcon/>}> <ExpansionPanelSummary expandIcon={<ExpandMoreIcon/>}>
<Typography className={classes.heading}>Evaluation des cours suivis</Typography> <Typography className={classes.heading}>Evaluation des cours suivis</Typography>
</ExpansionPanelSummary> </ExpansionPanelSummary>
......
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