diff --git a/.github/actions/setup_project/action.yml b/.github/actions/setup_project/action.yml
index 0ec83445..720d36bc 100644
--- a/.github/actions/setup_project/action.yml
+++ b/.github/actions/setup_project/action.yml
@@ -12,7 +12,7 @@ runs:
steps:
- name: Install apt packages
if: ${{ inputs.full == 'true' }}
- uses: awalsh128/cache-apt-pkgs-action@v1.4.3
+ uses: awalsh128/cache-apt-pkgs-action@v1.6.0
with:
packages: gettext
version: 1.0 # increment to reset cache
@@ -23,26 +23,29 @@ runs:
with:
redis-version: "7.x"
- - name: Install uv
- uses: astral-sh/setup-uv@v5
- with:
- version: "0.5.14"
- enable-cache: true
- cache-dependency-glob: "uv.lock"
-
- name: "Set up Python"
- uses: actions/setup-python@v5
+ uses: actions/setup-python@v6
with:
python-version-file: ".python-version"
- - name: Restore cached virtualenv
- uses: actions/cache/restore@v4
+ - name: Install uv
+ uses: astral-sh/setup-uv@v8.1.0
+ with:
+ version: "0.11.8"
+ enable-cache: false
+ cache-dependency-glob: "uv.lock"
+
+ - name: Restore cached virtualenv
+ uses: actions/cache@v5
with:
- key: venv-${{ runner.os }}-${{ hashFiles('.python-version') }}-${{ hashFiles('pyproject.toml') }}-${{ env.CACHE_SUFFIX }}
path: .venv
+ key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
+ restore-keys: |
+ uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
+ uv-${{ runner.os }}
- name: Install dependencies
- run: uv sync
+ run: uv sync --locked
shell: bash
- name: Install Xapian
@@ -50,15 +53,6 @@ runs:
run: uv run ./manage.py install_xapian
shell: bash
- # compiling xapian accounts for almost the entirety of the virtualenv setup,
- # so we save the virtual environment only on workflows where it has been installed
- - name: Save cached virtualenv
- if: ${{ inputs.full == 'true' }}
- uses: actions/cache/save@v4
- with:
- key: venv-${{ runner.os }}-${{ hashFiles('.python-version') }}-${{ hashFiles('pyproject.toml') }}-${{ env.CACHE_SUFFIX }}
- path: .venv
-
- name: Compile gettext messages
if: ${{ inputs.full == 'true' }}
run: uv run ./manage.py compilemessages
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8919d04c..e92bf82e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -18,8 +18,8 @@ jobs:
name: Launch pre-commits checks (ruff)
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
+ - uses: actions/checkout@v6
+ - uses: actions/setup-python@v6
with:
python-version-file: ".python-version"
- uses: pre-commit/action@v3.0.1
@@ -35,7 +35,7 @@ jobs:
pytest-mark: [not slow]
steps:
- name: Check out repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- uses: ./.github/actions/setup_project
with:
full: true
@@ -49,7 +49,7 @@ jobs:
uv run coverage report
uv run coverage html
- name: Archive code coverage results
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@v7
with:
name: coverage-report-${{ matrix.pytest-mark }}
path: coverage_report
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 8df48378..d46feb8a 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -14,7 +14,7 @@ jobs:
steps:
- name: SSH Remote Commands
- uses: appleboy/ssh-action@v1.1.0
+ uses: appleboy/ssh-action@v1.2.5
with:
# Proxy
proxy_host : ${{secrets.PROXY_HOST}}
@@ -29,8 +29,6 @@ jobs:
username : ${{secrets.USER}}
key: ${{secrets.KEY}}
- script_stop: true
-
# See https://github.com/ae-utbm/sith/wiki/GitHub-Actions#deployment-action
script: |
cd ${{secrets.SITH_PATH}}
diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml
index 236917a3..cae93e7b 100644
--- a/.github/workflows/deploy_docs.yml
+++ b/.github/workflows/deploy_docs.yml
@@ -9,10 +9,10 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- uses: ./.github/actions/setup_project
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- - uses: actions/cache@v3
+ - uses: actions/cache@v5
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache
diff --git a/.github/workflows/taiste.yml b/.github/workflows/taiste.yml
index 729e051c..9a49c8f3 100644
--- a/.github/workflows/taiste.yml
+++ b/.github/workflows/taiste.yml
@@ -13,7 +13,7 @@ jobs:
steps:
- name: SSH Remote Commands
- uses: appleboy/ssh-action@v1.1.0
+ uses: appleboy/ssh-action@v1.2.5
with:
# Proxy
proxy_host : ${{secrets.PROXY_HOST}}
@@ -28,8 +28,6 @@ jobs:
username : ${{secrets.USER}}
key: ${{secrets.KEY}}
- script_stop: true
-
# See https://github.com/ae-utbm/sith/wiki/GitHub-Actions#deployment-action
script: |
cd ${{secrets.SITH_PATH}}
diff --git a/club/templates/club/club_detail.jinja b/club/templates/club/club_detail.jinja
index 168c4b6c..14a5a384 100644
--- a/club/templates/club/club_detail.jinja
+++ b/club/templates/club/club_detail.jinja
@@ -26,10 +26,9 @@
{% if club.logo %}

{% endif %}
+ {{ club.name }}
{% if page_revision %}
{{ page_revision|markdown }}
- {% else %}
- {{ club.name }}
{% endif %}
{% endblock %}
diff --git a/com/static/com/css/news-list.scss b/com/static/com/css/news-list.scss
index b53ff784..a1dcb966 100644
--- a/com/static/com/css/news-list.scss
+++ b/com/static/com/css/news-list.scss
@@ -3,6 +3,7 @@
#news {
display: flex;
+ gap: 1em;
@media (max-width: 800px) {
flex-direction: column;
@@ -26,12 +27,14 @@
}
h3 {
- background: $second-color;
- box-shadow: $shadow-color 1px 1px 1px;
- padding: 0.4em;
+ --box-shadow: rgb(60 64 67 / 30%) 0 1px 3px 0, rgb(60 64 67 / 15%) 0 3px 7px 2px;
+ background: lighten($second-color, 5%);
+ box-shadow: var(--box-shadow);
+ padding: .75rem;
margin: 0 0 0.5em 0;
text-transform: uppercase;
font-size: 17px;
+ border-radius: 10px;
&:not(:first-of-type) {
margin: 2em 0 1em 0;
@@ -39,12 +42,11 @@
.feed {
float: right;
- color: #f26522;
+ color: #e25512;
}
}
@media screen and (max-width: $small-devices) {
-
#left_column,
#right_column {
flex: 100%;
@@ -57,6 +59,7 @@
max-height: 600px;
overflow-y: scroll;
overflow-x: clip;
+ margin-top: 1em;
#load-more-news-button {
text-align: center;
@@ -76,15 +79,11 @@
font-size: 70%;
margin-bottom: 1em;
- h3 {
- margin-bottom: 0;
- }
-
#links_content {
overflow: auto;
box-shadow: $shadow-color 1px 1px 1px;
min-height: 20em;
- padding-bottom: 1em;
+ padding: 1em;
h4 {
margin-left: 5px;
@@ -121,6 +120,8 @@
}
#birthdays_content {
+ box-shadow: $shadow-color 1px 1px 1px;
+ padding: 1em;
ul.birthdays_year {
margin: 0;
list-style-type: none;
@@ -135,8 +136,7 @@
}
ul {
- margin: 0;
- margin-left: 1em;
+ margin: .5em 0 0 1em;
list-style-type: square;
list-style-position: inside;
font-weight: normal;
@@ -150,9 +150,13 @@
/* EVENTS TODAY AND NEXT FEW DAYS */
.news_events_group {
box-shadow: $shadow-color 1px 1px 1px;
- margin-left: 1em;
+ margin-left: 0;
margin-bottom: 0.5em;
+ @media screen and (max-width: $small-devices) {
+ margin-left: 3px;
+ }
+
.news_events_group_date {
display: table-cell;
padding: 0.6em;
diff --git a/com/templates/com/news_list.jinja b/com/templates/com/news_list.jinja
index 2f6dc26e..975fb2ac 100644
--- a/com/templates/com/news_list.jinja
+++ b/com/templates/com/news_list.jinja
@@ -23,7 +23,7 @@
{% if user.is_authenticated and (user.is_com_admin or user.memberships.board().ongoing().exists()) %}
-
+
{% trans %}Create news{% endtrans %}
diff --git a/com/tests/test_notifications.py b/com/tests/test_notifications.py
index 8ddbfcb3..fc0e6aee 100644
--- a/com/tests/test_notifications.py
+++ b/com/tests/test_notifications.py
@@ -7,7 +7,7 @@ from model_bakery import baker
from com.models import News, NewsDate
from core.baker_recipes import subscriber_user
-from core.models import Group, Notification, User
+from core.models import Group, Notification, SithFile, User
@pytest.mark.django_db
@@ -18,6 +18,7 @@ def test_notification_created():
past_news = baker.make(News, is_published=False)
baker.make(NewsDate, news=past_news, start_date=now() - timedelta(days=1))
com_admin_group = Group.objects.get(pk=settings.SITH_GROUP_COM_ADMIN_ID)
+ SithFile.objects.filter(owner__in=com_admin_group.users.all()).delete()
com_admin_group.users.all().delete()
Notification.objects.all().delete()
com_admin = baker.make(User, groups=[com_admin_group])
diff --git a/core/management/commands/populate.py b/core/management/commands/populate.py
index a326b8ed..22541841 100644
--- a/core/management/commands/populate.py
+++ b/core/management/commands/populate.py
@@ -622,8 +622,7 @@ class Command(BaseCommand):
)
pict.file.name = p.name
pict.full_clean()
- pict.generate_thumbnails()
- pict.save()
+ pict.generate_thumbnails(save=True)
img_skia = Picture.objects.get(name="skia.jpg")
img_sli = Picture.objects.get(name="sli.jpg")
diff --git a/core/migrations/0050_alter_sithfile_moderator.py b/core/migrations/0050_alter_sithfile_moderator.py
new file mode 100644
index 00000000..0b6e9ef1
--- /dev/null
+++ b/core/migrations/0050_alter_sithfile_moderator.py
@@ -0,0 +1,47 @@
+# Generated by Django 5.2.12 on 2026-05-01 08:59
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+from django.db.migrations.state import StateApps
+from django.db.models import F
+
+
+def set_updated_at(apps: StateApps, schema_editor):
+ SithFile = apps.get_model("core", "SithFile")
+ SithFile.objects.update(updated_at=F("date"))
+
+
+class Migration(migrations.Migration):
+ dependencies = [("core", "0049_user_whitelisted_users")]
+
+ operations = [
+ migrations.AlterField(
+ model_name="sithfile",
+ name="moderator",
+ field=models.ForeignKey(
+ blank=True,
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ related_name="moderated_files",
+ to=settings.AUTH_USER_MODEL,
+ verbose_name="owner",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="sithfile",
+ name="owner",
+ field=models.ForeignKey(
+ on_delete=django.db.models.deletion.PROTECT,
+ related_name="owned_files",
+ to=settings.AUTH_USER_MODEL,
+ verbose_name="owner",
+ ),
+ ),
+ migrations.AddField(
+ model_name="sithfile",
+ name="updated_at",
+ field=models.DateTimeField(auto_now=True, verbose_name="updated at"),
+ ),
+ migrations.RunPython(set_updated_at, reverse_code=migrations.RunPython.noop),
+ ]
diff --git a/core/models.py b/core/models.py
index ffbdebfc..208f1937 100644
--- a/core/models.py
+++ b/core/models.py
@@ -853,7 +853,7 @@ class SithFile(models.Model):
User,
related_name="owned_files",
verbose_name=_("owner"),
- on_delete=models.CASCADE,
+ on_delete=models.PROTECT,
)
edit_groups = models.ManyToManyField(
Group, related_name="editable_files", verbose_name=_("edit group"), blank=True
@@ -865,6 +865,7 @@ class SithFile(models.Model):
mime_type = models.CharField(_("mime type"), max_length=30)
size = models.IntegerField(_("size"), default=0)
date = models.DateTimeField(_("date"), default=timezone.now)
+ updated_at = models.DateTimeField(_("updated at"), auto_now=True)
is_moderated = models.BooleanField(_("is moderated"), default=False)
moderator = models.ForeignKey(
User,
@@ -872,7 +873,7 @@ class SithFile(models.Model):
verbose_name=_("owner"),
null=True,
blank=True,
- on_delete=models.CASCADE,
+ on_delete=models.SET_NULL,
)
asked_for_removal = models.BooleanField(_("asked for removal"), default=False)
is_in_sas = models.BooleanField(
diff --git a/core/static/bundled/core/components/tabs-index.ts b/core/static/bundled/core/components/tabs-index.ts
index 7bd85998..260467d5 100644
--- a/core/static/bundled/core/components/tabs-index.ts
+++ b/core/static/bundled/core/components/tabs-index.ts
@@ -28,7 +28,7 @@ export class Tab extends HTMLElement {
return html`