Commit f4549210 authored by Florent Chehab's avatar Florent Chehab

馃帀 feat(beta) 馃帀 got ready, i.e. TWEAKS

Beta time has come ! 馃帀

WARNING: migrations have been reset one last time!

This MR concerns tones of little tweaks:

Reviewed:
* model moderation levels
* serializers.meta.fields value
* Viewset permissions
* on_delete values

Changed:
* Update dark theme color
* Added load prod base script
* beta logo on website
* Added missing about project markdown
* Added RGPD notice to all forms
* Put media files in a docker volume
* More frequent currency exhange rates update

Fixed:
* Front handling of scholarships
* Currencies conversion in the front
* Front theme icons color
* No default networks in prod docker compose to prevent nasty VM routing

Closes #135 #119 #96
parent abbba24b
Pipeline #42771 passed with stages
in 3 minutes and 54 seconds
......@@ -18,6 +18,9 @@ down_dev:
init_dev_data:
docker-compose exec backend sh -c "cd backend && ./manage.py shell < init_dev_data.py"
init_prod_data:
docker-compose $(prod_yml) exec backend sh -c "cd backend && ./manage.py shell < init_prod_data.py"
docker-pull:
docker-compose pull
......@@ -64,7 +67,8 @@ prod_yml = -f ./server/docker-compose.prod.yml
prod: setup
$(info In production, we need to reset the webpack-stats.json file to make sure the front is up-to-date)
sudo rm -f frontend/webpack-stats.json
docker-compose $(prod_yml) up --build -d
# Need higher compose timeout as the big map container can take a lot of time to wake up
COMPOSE_HTTP_TIMEOUT=600 docker-compose $(prod_yml) up --build -d
down_prod:
docker-compose $(prod_yml) down
......
......@@ -30,3 +30,21 @@ def load_all():
LoadUniversityEx(admin).load()
LoadRecommendationLists(admin).load()
LoadSiteInformation(admin).load()
def load_prod():
"""
for PRODUCTION ENV
Function to load all the initial data in the app
"""
with reversion.create_revision():
LoadGroups()
admin = LoadBaseUsers().get_admin()
LoadCurrencies(admin).load()
LoadCountries(admin).load()
LoadLanguages().load()
LoadSiteInformation(admin).load()
# LoadUniversities(admin).load()
# LoadUniversityEx(admin).load()
# LoadRecommendationLists(admin).load()
......@@ -19,4 +19,6 @@ class LoadLanguages(LoadGeneric):
reader = csv.reader(csvfile, quotechar='"')
next(reader)
for r in reader:
Language.objects.create(code_iso=r[0], name=r[1])
Language.objects.update_or_create(
code_iso=r[0], defaults=dict(name=r[1])
)
# Generated by Django 2.1.7 on 2019-06-26 21:10
# Generated by Django 2.1.7 on 2019-06-30 20:48
import backend_app.fields
import backend_app.models.abstract.essentialModule
import backend_app.utils
import backend_app.validation.validators
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = []
dependencies = [
("base_app", "0001_initial"),
("contenttypes", "0002_remove_content_type_name"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
......@@ -26,43 +33,6 @@ class Migration(migrations.Migration):
verbose_name="ID",
),
),
("updated_on", models.DateTimeField(null=True)),
("moderated_on", models.DateTimeField(null=True)),
(
"obj_moderation_level",
models.SmallIntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("nb_versions", models.PositiveIntegerField(default=0)),
("title", models.CharField(blank=True, default="", max_length=150)),
("comment", models.CharField(blank=True, default="", max_length=5000)),
(
"useful_links",
backend_app.fields.JSONField(
default=list,
validators=[
backend_app.validation.validators.UsefulLinksValidator()
],
),
),
(
"importance_level",
models.CharField(
choices=[
("-", "normal"),
("+", "important"),
("++", "IMPORTANT"),
],
default="-",
max_length=2,
),
),
("is_main_campus", models.BooleanField()),
("name", models.CharField(blank=True, default="", max_length=200)),
(
......@@ -192,6 +162,12 @@ class Migration(migrations.Migration):
max_length=2,
),
),
(
"countries",
models.ManyToManyField(
related_name="country_dri", to="backend_app.Country"
),
),
],
options={"abstract": False},
),
......@@ -283,6 +259,12 @@ class Migration(migrations.Migration):
validators=[django.core.validators.MinValueValidator(0)],
),
),
(
"countries",
models.ManyToManyField(
related_name="country_scholarships", to="backend_app.Country"
),
),
],
options={"abstract": False},
),
......@@ -336,6 +318,14 @@ class Migration(migrations.Migration):
],
),
),
(
"country",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="country_tagged_items",
to="backend_app.Country",
),
),
],
),
migrations.CreateModel(
......@@ -350,15 +340,17 @@ class Migration(migrations.Migration):
verbose_name="ID",
),
),
("utc_id", models.IntegerField(unique=True)),
("utc_exchange_id", models.IntegerField()),
("course_id", models.IntegerField()),
("code", models.CharField(max_length=10)),
("code", models.CharField(blank=True, max_length=10, null=True)),
("title", models.CharField(blank=True, default="", max_length=200)),
("link", models.URLField(blank=True, max_length=500, null=True)),
(
"title",
models.CharField(blank=True, default="", max_length=200, null=True),
"ects",
models.DecimalField(
decimal_places=2, default=0, max_digits=7, null=True
),
),
("link", models.URLField(blank=True, max_length=500, null=True)),
("nb_credit", models.PositiveIntegerField(default=0)),
("category", models.CharField(blank=True, max_length=5, null=True)),
("profile", models.CharField(blank=True, max_length=10, null=True)),
("tsh_profile", models.CharField(blank=True, max_length=21, null=True)),
......@@ -366,6 +358,7 @@ class Migration(migrations.Migration):
"student_login",
models.CharField(blank=True, max_length=8, null=True),
),
("unlinked", models.BooleanField(default=False)),
],
options={"abstract": False},
),
......@@ -435,6 +428,16 @@ class Migration(migrations.Migration):
],
),
),
("untouched", models.BooleanField(default=True)),
(
"course",
models.OneToOneField(
default=0,
on_delete=django.db.models.deletion.CASCADE,
related_name="course_feedback",
to="backend_app.Course",
),
),
],
options={"abstract": False},
),
......@@ -458,18 +461,6 @@ class Migration(migrations.Migration):
],
options={"abstract": False},
),
migrations.CreateModel(
name="Department",
fields=[
(
"code",
models.CharField(max_length=6, primary_key=True, serialize=False),
),
("name", models.CharField(max_length=100)),
("active", models.BooleanField()),
],
options={"abstract": False},
),
migrations.CreateModel(
name="Exchange",
fields=[
......@@ -482,24 +473,41 @@ class Migration(migrations.Migration):
verbose_name="ID",
),
),
("utc_departure_id", models.IntegerField()),
("year", models.PositiveIntegerField(default=2018)),
("utc_id", models.IntegerField(unique=True)),
("utc_partner_id", models.IntegerField(null=True)),
("year", models.PositiveIntegerField(default=2018, null=True)),
(
"semester",
models.CharField(
choices=[("a", "autumn"), ("p", "spring")],
default="a",
max_length=5,
choices=[("A", "autumn"), ("P", "spring")],
default="A",
max_length=1,
null=True,
),
),
("duration", models.PositiveIntegerField()),
("dual_degree", models.BooleanField()),
("double_degree", models.BooleanField()),
("master_obtained", models.BooleanField()),
("student_major", models.CharField(max_length=20)),
("student_minor", models.CharField(max_length=7)),
("student_option", models.CharField(max_length=7)),
(
"student_major_and_semester",
models.CharField(blank=True, max_length=20),
),
(
"student_minor",
models.CharField(blank=True, max_length=47, null=True),
),
(
"student_option",
models.CharField(blank=True, max_length=7, null=True),
),
("utc_allow_courses", models.BooleanField()),
("utc_allow_login", models.BooleanField()),
(
"student_major",
models.CharField(blank=True, max_length=20, null=True),
),
("student_semester", models.IntegerField(null=True)),
("unlinked", models.BooleanField(default=False)),
],
options={"abstract": False},
),
......@@ -534,7 +542,6 @@ class Migration(migrations.Migration):
models.CharField(blank=True, default="", max_length=500, null=True),
),
],
options={"abstract": False},
),
migrations.CreateModel(
name="ForTestingModeration",
......@@ -618,21 +625,35 @@ class Migration(migrations.Migration):
verbose_name="ID",
),
),
("year", models.PositiveIntegerField(default=2018)),
("utc_partner_id", models.IntegerField()),
("year", models.PositiveIntegerField(default=2018, null=True)),
(
"semester",
models.CharField(
choices=[("a", "autumn"), ("p", "spring")],
default="a",
choices=[("A", "autumn"), ("P", "spring")],
default="A",
max_length=2,
null=True,
),
),
("nb_seats_offered", models.PositiveIntegerField()),
("nb_seats_offered_exchange", models.PositiveIntegerField(null=True)),
(
"nb_seats_offered_double_degree",
models.PositiveIntegerField(null=True),
("comment", models.TextField(max_length=500, null=True)),
("double_degree", models.BooleanField(default=False)),
("is_master_offered", models.BooleanField(default=False, null=True)),
("nb_seats_offered", models.PositiveIntegerField(null=True)),
("majors", models.CharField(max_length=4000, null=True)),
],
),
migrations.CreateModel(
name="Partner",
fields=[
("utc_id", models.IntegerField(primary_key=True, serialize=False)),
("univ_name", models.CharField(max_length=80)),
("address1", models.CharField(blank=True, max_length=100, null=True)),
("address2", models.CharField(blank=True, max_length=100, null=True)),
("zipcode", models.CharField(max_length=40, null=True)),
("city", models.CharField(max_length=40)),
("country", models.CharField(max_length=50)),
("iso_code", models.CharField(max_length=2)),
],
options={"abstract": False},
),
......@@ -651,6 +672,13 @@ class Migration(migrations.Migration):
("object_id", models.CharField(max_length=100)),
("updated_on", models.DateTimeField(null=True)),
("new_object", backend_app.fields.JSONField(default=dict)),
(
"content_type",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="contenttypes.ContentType",
),
),
],
),
migrations.CreateModel(
......@@ -719,7 +747,7 @@ class Migration(migrations.Migration):
options={"abstract": False},
),
migrations.CreateModel(
name="Specialty",
name="SharedUnivFeedback",
fields=[
(
"id",
......@@ -730,11 +758,24 @@ class Migration(migrations.Migration):
verbose_name="ID",
),
),
("code", models.CharField(max_length=6)),
("name", models.CharField(max_length=100)),
("active", models.BooleanField()),
("updated_on", models.DateTimeField(null=True)),
("moderated_on", models.DateTimeField(null=True)),
(
"obj_moderation_level",
models.SmallIntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("nb_versions", models.PositiveIntegerField(default=0)),
("comment", models.CharField(blank=True, default="", max_length=5000)),
],
options={"abstract": False},
),
migrations.CreateModel(
name="University",
fields=[
......@@ -762,20 +803,8 @@ class Migration(migrations.Migration):
("has_pending_moderation", models.BooleanField(default=False)),
("name", models.CharField(max_length=200)),
("acronym", models.CharField(blank=True, default="", max_length=20)),
(
"logo",
models.URLField(
blank=True,
default="",
validators=[
backend_app.validation.validators.PathExtensionValidator(
["jpg", "jpeg", "png", "svg"]
)
],
),
),
("website", models.URLField(blank=True, default="", max_length=300)),
("utc_id", models.IntegerField(unique=True)),
("denormalized_infos", backend_app.fields.JSONField(default=dict)),
],
options={"abstract": False},
),
......@@ -919,6 +948,14 @@ class Migration(migrations.Migration):
validators=[django.core.validators.MinValueValidator(0)],
),
),
(
"currency",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.PROTECT,
to="backend_app.Currency",
),
),
],
options={"abstract": False},
),
......@@ -973,4 +1010,751 @@ class Migration(migrations.Migration):
),
],
),
migrations.CreateModel(
name="UnivMajorMinors",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("major", models.CharField(blank=True, max_length=20, null=True)),
("minors", backend_app.fields.JSONField(default=list)),
],
),
migrations.CreateModel(
name="UserData",
fields=[
(
"owner",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
primary_key=True,
serialize=False,
to=settings.AUTH_USER_MODEL,
),
),
(
"theme",
backend_app.fields.JSONField(
default=backend_app.utils.get_default_theme_settings,
validators=[backend_app.validation.validators.ThemeValidator()],
),
),
],
options={"abstract": False},
),
migrations.CreateModel(
name="ExchangeFeedback",
fields=[
("updated_on", models.DateTimeField(null=True)),
("moderated_on", models.DateTimeField(null=True)),
(
"obj_moderation_level",
models.SmallIntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
(
"exchange",
models.OneToOneField(
default=0,
on_delete=django.db.models.deletion.CASCADE,
primary_key=True,
related_name="feedbacks",
serialize=False,
to="backend_app.Exchange",
),
),
("general_comment", models.TextField(max_length=1500, null=True)),
(
"academical_level_appreciation",
models.IntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(-5),
django.core.validators.MaxValueValidator(5),
],
),
),
(
"foreign_student_welcome",
models.IntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(-5),
django.core.validators.MaxValueValidator(5),
],
),
),
(
"cultural_interest",
models.IntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(-5),
django.core.validators.MaxValueValidator(5),
],
),
),
("untouched", models.BooleanField(default=True)),
(
"moderated_by",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="+",
to=settings.AUTH_USER_MODEL,
),
),
],
options={"abstract": False},
),
migrations.CreateModel(
name="UniversityInfo",
fields=[
("updated_on", models.DateTimeField(null=True)),
("moderated_on", models.DateTimeField(null=True)),
(
"obj_moderation_level",
models.SmallIntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("nb_versions", models.PositiveIntegerField(default=0)),
("title", models.CharField(blank=True, default="", max_length=150)),
("comment", models.CharField(blank=True, default="", max_length=5000)),
(
"useful_links",
backend_app.fields.JSONField(
default=list,
validators=[
backend_app.validation.validators.UsefulLinksValidator()
],
),
),
(
"importance_level",
models.CharField(
choices=[
("-", "normal"),
("+", "important"),
("++", "IMPORTANT"),
],
default="-",
max_length=2,
),
),
(
"university",
models.OneToOneField(
on_delete=django.db.models.deletion.PROTECT,
primary_key=True,
related_name="university_info",
serialize=False,
to="backend_app.University",
),
),
(
"cost_exchange",
models.DecimalField(
decimal_places=2,
max_digits=20,
null=True,
validators=[django.core.validators.MinValueValidator(0)],
),
),
(
"cost_double_degree",
models.DecimalField(
decimal_places=2,
max_digits=20,
null=True,
validators=[django.core.validators.MinValueValidator(0)],
),
),
(
"costs_currency",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.PROTECT,
to="backend_app.Currency",
),
),
],
options={"abstract": False},
),
migrations.CreateModel(
name="UniversitySemestersDates",
fields=[
("updated_on", models.DateTimeField(null=True)),
("moderated_on", models.DateTimeField(null=True)),
(
"obj_moderation_level",
models.SmallIntegerField(
default=0,
validators=[
django.core.validators.MinValueValidator(0),
backend_app.models.abstract.essentialModule.validate_obj_model_lv,
],
),
),
("has_pending_moderation", models.BooleanField(default=False)),
("nb_versions", models.PositiveIntegerField(default=0)),
("title", models.CharField(blank=True, default="", max_length=150)),
("comment", models.CharField(blank=True, default="", max_length=5000)),
(
"useful_links",
backend_app.fields.JSONField(
default=list,
validators=[
backend_app.validation.validators.UsefulLinksValidator()
],
),
),
(
"importance_level",
models.CharField(
choices=[
("-", "normal"),
("+", "important"),
("++", "IMPORTANT"),
],
default="-",
max_length=2,
),
),
(
"university",
models.OneToOneField(
on_delete=django.db.models.deletion.PROTECT,
primary_key=True,
related_name="university_semesters_dates",
serialize=False,
to="backend_app.University",
),
),
("spring_begin", models.DateField(blank=True, null=True)),
("spring_end", models.DateField(blank=True, null=True)),
("autumn_begin", models.DateField(blank=True, null=True)),
("autumn_end", models.DateField(blank=True, null=True)),
(
"moderated_by",