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: ...@@ -18,6 +18,9 @@ down_dev:
init_dev_data: init_dev_data:
docker-compose exec backend sh -c "cd backend && ./manage.py shell < init_dev_data.py" 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-pull:
docker-compose pull docker-compose pull
...@@ -64,7 +67,8 @@ prod_yml = -f ./server/docker-compose.prod.yml ...@@ -64,7 +67,8 @@ prod_yml = -f ./server/docker-compose.prod.yml
prod: setup prod: setup
$(info In production, we need to reset the webpack-stats.json file to make sure the front is up-to-date) $(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 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: down_prod:
docker-compose $(prod_yml) down docker-compose $(prod_yml) down
......
...@@ -30,3 +30,21 @@ def load_all(): ...@@ -30,3 +30,21 @@ def load_all():
LoadUniversityEx(admin).load() LoadUniversityEx(admin).load()
LoadRecommendationLists(admin).load() LoadRecommendationLists(admin).load()
LoadSiteInformation(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): ...@@ -19,4 +19,6 @@ class LoadLanguages(LoadGeneric):
reader = csv.reader(csvfile, quotechar='"') reader = csv.reader(csvfile, quotechar='"')
next(reader) next(reader)
for r in 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.fields
import backend_app.models.abstract.essentialModule import backend_app.models.abstract.essentialModule
import backend_app.utils
import backend_app.validation.validators import backend_app.validation.validators
from django.conf import settings
import django.core.validators import django.core.validators
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True initial = True
dependencies = [] dependencies = [
("base_app", "0001_initial"),
("contenttypes", "0002_remove_content_type_name"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
...@@ -26,43 +33,6 @@ class Migration(migrations.Migration): ...@@ -26,43 +33,6 @@ class Migration(migrations.Migration):
verbose_name="ID", 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()), ("is_main_campus", models.BooleanField()),
("name", models.CharField(blank=True, default="", max_length=200)), ("name", models.CharField(blank=True, default="", max_length=200)),
( (
...@@ -192,6 +162,12 @@ class Migration(migrations.Migration): ...@@ -192,6 +162,12 @@ class Migration(migrations.Migration):
max_length=2, max_length=2,
), ),
), ),
(
"countries",
models.ManyToManyField(
related_name="country_dri", to="backend_app.Country"
),
),
], ],
options={"abstract": False}, options={"abstract": False},
), ),
...@@ -283,6 +259,12 @@ class Migration(migrations.Migration): ...@@ -283,6 +259,12 @@ class Migration(migrations.Migration):
validators=[django.core.validators.MinValueValidator(0)], validators=[django.core.validators.MinValueValidator(0)],
), ),
), ),
(
"countries",
models.ManyToManyField(
related_name="country_scholarships", to="backend_app.Country"
),
),
], ],
options={"abstract": False}, options={"abstract": False},
), ),
...@@ -336,6 +318,14 @@ class Migration(migrations.Migration): ...@@ -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( migrations.CreateModel(
...@@ -350,15 +340,17 @@ class Migration(migrations.Migration): ...@@ -350,15 +340,17 @@ class Migration(migrations.Migration):
verbose_name="ID", verbose_name="ID",
), ),
), ),
("utc_id", models.IntegerField(unique=True)),
("utc_exchange_id", models.IntegerField()), ("utc_exchange_id", models.IntegerField()),
("course_id", models.IntegerField()), ("code", models.CharField(blank=True, max_length=10, null=True)),
("code", models.CharField(max_length=10)), ("title", models.CharField(blank=True, default="", max_length=200)),
("link", models.URLField(blank=True, max_length=500, null=True)),
( (
"title", "ects",
models.CharField(blank=True, default="", max_length=200, null=True), 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)), ("category", models.CharField(blank=True, max_length=5, null=True)),
("profile", models.CharField(blank=True, max_length=10, null=True)), ("profile", models.CharField(blank=True, max_length=10, null=True)),
("tsh_profile", models.CharField(blank=True, max_length=21, null=True)), ("tsh_profile", models.CharField(blank=True, max_length=21, null=True)),
...@@ -366,6 +358,7 @@ class Migration(migrations.Migration): ...@@ -366,6 +358,7 @@ class Migration(migrations.Migration):
"student_login", "student_login",
models.CharField(blank=True, max_length=8, null=True), models.CharField(blank=True, max_length=8, null=True),
), ),
("unlinked", models.BooleanField(default=False)),
], ],
options={"abstract": False}, options={"abstract": False},
), ),
...@@ -435,6 +428,16 @@ class Migration(migrations.Migration): ...@@ -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}, options={"abstract": False},
), ),
...@@ -458,18 +461,6 @@ class Migration(migrations.Migration): ...@@ -458,18 +461,6 @@ class Migration(migrations.Migration):
], ],
options={"abstract": False}, 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( migrations.CreateModel(
name="Exchange", name="Exchange",
fields=[ fields=[
...@@ -482,24 +473,41 @@ class Migration(migrations.Migration): ...@@ -482,24 +473,41 @@ class Migration(migrations.Migration):
verbose_name="ID", verbose_name="ID",
), ),
), ),
("utc_departure_id", models.IntegerField()), ("utc_id", models.IntegerField(unique=True)),
("year", models.PositiveIntegerField(default=2018)), ("utc_partner_id", models.IntegerField(null=True)),
("year", models.PositiveIntegerField(default=2018, null=True)),
( (
"semester", "semester",
models.CharField( models.CharField(
choices=[("a", "autumn"), ("p", "spring")], choices=[("A", "autumn"), ("P", "spring")],
default="a", default="A",
max_length=5, max_length=1,
null=True,
), ),
), ),
("duration", models.PositiveIntegerField()), ("duration", models.PositiveIntegerField()),
("dual_degree", models.BooleanField()), ("double_degree", models.BooleanField()),
("master_obtained", models.BooleanField()), ("master_obtained", models.BooleanField()),
("student_major", models.CharField(max_length=20)), (
("student_minor", models.CharField(max_length=7)), "student_major_and_semester",
("student_option", models.CharField(max_length=7)), 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_courses", models.BooleanField()),
("utc_allow_login", 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}, options={"abstract": False},
), ),
...@@ -534,7 +542,6 @@ class Migration(migrations.Migration): ...@@ -534,7 +542,6 @@ class Migration(migrations.Migration):
models.CharField(blank=True, default="", max_length=500, null=True), models.CharField(blank=True, default="", max_length=500, null=True),
), ),
], ],
options={"abstract": False},
), ),
migrations.CreateModel( migrations.CreateModel(
name="ForTestingModeration", name="ForTestingModeration",
...@@ -618,21 +625,35 @@ class Migration(migrations.Migration): ...@@ -618,21 +625,35 @@ class Migration(migrations.Migration):
verbose_name="ID", verbose_name="ID",
), ),
), ),
("year", models.PositiveIntegerField(default=2018)), ("utc_partner_id", models.IntegerField()),
("year", models.PositiveIntegerField(default=2018, null=True)),
( (
"semester", "semester",
models.CharField( models.CharField(
choices=[("a", "autumn"), ("p", "spring")], choices=[("A", "autumn"), ("P", "spring")],
default="a", default="A",
max_length=2, max_length=2,
null=True,
), ),
), ),
("nb_seats_offered", models.PositiveIntegerField()), ("comment", models.TextField(max_length=500, null=True)),
("nb_seats_offered_exchange", models.PositiveIntegerField(null=True)), ("double_degree", models.BooleanField(default=False)),
( ("is_master_offered", models.BooleanField(default=False, null=True)),
"nb_seats_offered_double_degree", ("nb_seats_offered", models.PositiveIntegerField(null=True)),
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}, options={"abstract": False},
), ),
...@@ -651,6 +672,13 @@ class Migration(migrations.Migration): ...@@ -651,6 +672,13 @@ class Migration(migrations.Migration):
("object_id", models.CharField(max_length=100)), ("object_id", models.CharField(max_length=100)),
("updated_on", models.DateTimeField(null=True)), ("updated_on", models.DateTimeField(null=True)),
("new_object", backend_app.fields.JSONField(default=dict)), ("new_object", backend_app.fields.JSONField(default=dict)),
(
"content_type",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="contenttypes.ContentType",
),
),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(
...@@ -719,7 +747,7 @@ class Migration(migrations.Migration): ...@@ -719,7 +747,7 @@ class Migration(migrations.Migration):
options={"abstract": False}, options={"abstract": False},
), ),
migrations.CreateModel( migrations.CreateModel(
name="Specialty", name="SharedUnivFeedback",
fields=[ fields=[
( (
"id", "id",
...@@ -730,10 +758,23 @@ class Migration(migrations.Migration): ...@@ -730,10 +758,23 @@ class Migration(migrations.Migration):
verbose_name="ID", verbose_name="ID",
), ),
), ),
("code", models.CharField(max_length=6)), ("updated_on", models.DateTimeField(null=True)),
("name", models.CharField(max_length=100)), ("moderated_on", models.DateTimeField(null=True)),
("active", models.BooleanField()), (
"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( migrations.CreateModel(
name="University", name="University",
...@@ -762,20 +803,8 @@ class Migration(migrations.Migration): ...@@ -762,20 +803,8 @@ class Migration(migrations.Migration):
("has_pending_moderation", models.BooleanField(default=False)), ("has_pending_moderation", models.BooleanField(default=False)),
("name", models.CharField(max_length=200)), ("name", models.CharField(max_length=200)),
("acronym", models.CharField(blank=True, default="", max_length=20)), ("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)), ("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}, options={"abstract": False},
), ),
...@@ -919,6 +948,14 @@ class Migration(migrations.Migration): ...@@ -919,6 +948,14 @@ class Migration(migrations.Migration):
validators=[django.core.validators.MinValueValidator(0)], 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}, options={"abstract": False},
), ),
...@@ -973,4 +1010,751 @@ class Migration(migrations.Migration): ...@@ -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()
</