Compare commits

...

4 Commits

Author SHA1 Message Date
90c70a8d42 Add translation 2024-04-10 18:48:57 +02:00
dbe77d0ece Add UI button 2024-04-10 18:45:38 +02:00
d1812cdde7 Implement album and groupe zip download
Disabled by default for users not logged in
2024-04-10 18:38:47 +02:00
52894d37ea migration: Add --backup flag 2024-04-10 18:21:06 +02:00
10 changed files with 265 additions and 139 deletions

View File

@ -38,4 +38,7 @@ ENABLED_LOGS=["NEW_GROUPE", "NEW_ALBUM", "NEW_PARTITION", "NEW_USER", "PASSWORD_
LANGUAGES=['en', 'fr'] LANGUAGES=['en', 'fr']
# Show Launch page # Show Launch page
LAUNCH_PAGE=True LAUNCH_PAGE=True
# Check if account is logged in before serving zipped album/groupe
ZIP_REQUIRE_LOGIN=True

View File

@ -5,12 +5,12 @@ Albums module
import os import os
import pypdf import pypdf
import shutil import shutil
from uuid import uuid4 from uuid import uuid4
from typing import TypeVar from typing import TypeVar
from flask import (Blueprint, abort, flash, redirect, render_template, from flask import (Blueprint, abort, flash, redirect, render_template,
request, session, current_app) request, session, current_app, send_file, g, url_for)
from werkzeug.utils import secure_filename
from flask_babel import _ from flask_babel import _
from .auth import login_required from .auth import login_required
@ -115,6 +115,30 @@ def qr_code(uuid):
return utils.get_qrcode(f"/albums/{uuid}") return utils.get_qrcode(f"/albums/{uuid}")
@bp.route("/<uuid>/zip")
def zip_download(uuid):
"""
Télécharger un album comme fichier zip
"""
if g.user is None and current_app.config["ZIP_REQUIRE_LOGIN"]:
flash(_("You need to login to access this resource."))
return redirect(url_for("auth.login"))
try:
album = Album(uuid=uuid)
except LookupError:
try:
album = Album(uuid=utils.format_uuid(uuid))
return redirect(f"/albums/{utils.format_uuid(uuid)}")
except LookupError:
return abort(404)
return send_file(
album.to_zip(current_app.instance_path),
download_name=secure_filename(f"{album.name}.zip")
)
@bp.route("/create-album", methods=["POST"]) @bp.route("/create-album", methods=["POST"])
@login_required @login_required
def create_album_req(): def create_album_req():

View File

@ -2,6 +2,10 @@
Classe Album Classe Album
""" """
import os import os
import io
import zipfile
from werkzeug.utils import secure_filename
from ..db import get_db from ..db import get_db
from ..utils import new_uuid from ..utils import new_uuid
@ -165,6 +169,23 @@ class Album():
) )
db.commit() db.commit()
def to_zip(self, instance_path):
data = io.BytesIO()
with zipfile.ZipFile(data, mode="w") as z:
for partition in self.get_partitions():
z.write(os.path.join(
instance_path,
"partitions",
f"{partition['uuid']}.pdf"
), arcname=secure_filename(partition['name']+".pdf")
)
# Spooling back to the beginning of the buffer
data.seek(0)
return data
def create(name: str) -> str: def create(name: str) -> str:
"""Créer un nouvel album""" """Créer un nouvel album"""

View File

@ -1,3 +1,12 @@
"""
Classe Groupe
"""
import io
import os
import zipfile
from werkzeug.utils import secure_filename
from ..db import get_db from ..db import get_db
from .album import Album from .album import Album
@ -116,3 +125,21 @@ class Groupe():
(self.id,) (self.id,)
).fetchall() ).fetchall()
return [i["id"] for i in data] return [i["id"] for i in data]
def to_zip(self, instance_path):
data = io.BytesIO()
with zipfile.ZipFile(data, mode="w") as z:
for album in self.get_albums():
for partition in album.get_partitions():
z.write(os.path.join(
instance_path,
"partitions",
f"{partition['uuid']}.pdf"
), arcname=secure_filename(album.name)+"/"
+secure_filename(partition['name']+".pdf")
)
# Spooling back to the beginning of the buffer
data.seek(0)
return data

View File

@ -3,7 +3,8 @@
Groupe module Groupe module
""" """
from flask import (Blueprint, abort, flash, redirect, render_template, from flask import (Blueprint, abort, flash, redirect, render_template,
request, session, current_app) request, session, current_app, send_file, g, url_for)
from werkzeug.utils import secure_filename
from flask_babel import _ from flask_babel import _
from .auth import login_required from .auth import login_required
@ -261,6 +262,31 @@ def get_album(groupe_uuid, album_uuid):
) )
@bp.route("/<groupe_uuid>/zip")
def zip_download(groupe_uuid):
"""
Télécharger un groupe comme fichier zip
"""
if g.user is None and current_app.config["ZIP_REQUIRE_LOGIN"]:
flash(_("You need to login to access this resource."))
return redirect(url_for("auth.login"))
try:
groupe = Groupe(uuid=groupe_uuid)
except LookupError:
try:
groupe = Groupe(uuid=utils.format_uuid(groupe_uuid))
return redirect(f"/groupe/{utils.format_uuid(groupe_uuid)}/zip")
except LookupError:
return abort(404)
return send_file(
groupe.to_zip(current_app.instance_path),
download_name=secure_filename(f"{groupe.name}.zip")
)
@bp.route("/<groupe_uuid>/<album_uuid>/qr") @bp.route("/<groupe_uuid>/<album_uuid>/qr")
def groupe_qr_code(groupe_uuid, album_uuid): def groupe_qr_code(groupe_uuid, album_uuid):
return utils.get_qrcode(f"/groupe/{groupe_uuid}/{album_uuid}") return utils.get_qrcode(f"/groupe/{groupe_uuid}/{album_uuid}")

View File

@ -35,8 +35,8 @@
{% endif %} {% endif %}
{{ album.name }} {{ album.name }}
</h2> </h2>
{% if g.user %} <div id="header-actions">
<div id="header-actions"> {% if g.user %}
<section id="users"> <section id="users">
{% for album_user in album.users %} {% for album_user in album.users %}
<div class="user-profile-picture" style="background-color:{{ album_user.color }};" title="{{ album_user.username }}"> <div class="user-profile-picture" style="background-color:{{ album_user.color }};" title="{{ album_user.username }}">
@ -44,25 +44,28 @@
</div> </div>
{% endfor %} {% endfor %}
</section> </section>
<div class="dropdown dp1"> {% endif %}
+ <div class="dropdown dp1">
<div class="dropdown-content dp1"> +
{% if g.user %} <div class="dropdown-content dp1">
<a href="#add-partition">{{ _("Add a score") }}</a> {% if g.user %}
{% endif %} <a href="#add-partition">{{ _("Add a score") }}</a>
{% if not_participant %} {% endif %}
<a href="/albums/{{ album.uuid }}/join">{{ _("Join") }}</a> {% if not_participant %}
{% elif album.users | length > 1 %} <a href="/albums/{{ album.uuid }}/join">{{ _("Join") }}</a>
<a href="/albums/{{ album.uuid }}/quit">{{ _("Quit") }}</a> {% elif album.users | length > 1 %}
{% endif %} <a href="/albums/{{ album.uuid }}/quit">{{ _("Quit") }}</a>
<a href="#share">{{ _("Share") }}</a> {% endif %}
{% if g.user.access_level == 1 or (not not_participant and album.users | length == 1) %} <a href="#share">{{ _("Share") }}</a>
<a id="delete-album" href="#delete">{{ _("Delete") }}</a> {% if g.user or not config["ZIP_REQUIRE_LOGIN"] %}
{% endif %} <a href="/albums/{{ album.uuid }}/zip">{{ _("Download as zip") }}</a>
</div> {% endif %}
{% if g.user.access_level == 1 or (g.user and not not_participant and album.users | length == 1) %}
<a id="delete-album" href="#delete">{{ _("Delete") }}</a>
{% endif %}
</div> </div>
</div> </div>
{% endif %} </div>
</header> </header>
<hr/> <hr/>
{% if partitions|length != 0 %} {% if partitions|length != 0 %}

View File

@ -30,8 +30,8 @@
{% block content %} {% block content %}
<header id="album-header"> <header id="album-header">
<h2 id="groupe-title">{{ groupe.name }}</h2> <h2 id="groupe-title">{{ groupe.name }}</h2>
{% if g.user %} <div id="header-actions">
<div id="header-actions"> {% if g.user %}
<section id="users"> <section id="users">
{% for groupe_user in groupe.users %} {% for groupe_user in groupe.users %}
<div class="user-profile-picture" style="background-color:{{ groupe_user.color }};" title="{{ groupe_user.username }}"> <div class="user-profile-picture" style="background-color:{{ groupe_user.color }};" title="{{ groupe_user.username }}">
@ -39,23 +39,26 @@
</div> </div>
{% endfor %} {% endfor %}
</section> </section>
<div class="dropdown dp1"> {% endif %}
+ <div class="dropdown dp1">
<div class="dropdown-content dp1"> +
{% if not_participant %} <div class="dropdown-content dp1">
<a href="/groupe/{{ groupe.uuid }}/join">{{ _("Join") }}</a> {% if not_participant %}
{% elif groupe.users | length > 1 %} <a href="/groupe/{{ groupe.uuid }}/join">{{ _("Join") }}</a>
<a href="/groupe/{{ groupe.uuid }}/quit">{{ _("Quit") }}</a> {% elif groupe.users | length > 1 and g.user %}
{% endif %} <a href="/groupe/{{ groupe.uuid }}/quit">{{ _("Quit") }}</a>
<a href="#share">{{ _("Share") }}</a> {% endif %}
{% if g.user.access_level == 1 or user.id in groupe.get_admins() %} <a href="#share">{{ _("Share") }}</a>
<a href="#create-groupe-album">{{ _("Add an album") }}</a> {% if g.user or not config["ZIP_REQUIRE_LOGIN"] %}
<a id="delete-album" href="#delete">{{ _("Delete") }}</a> <a href="/groupe/{{ groupe.uuid }}/zip">{{ _("Download as zip") }}</a>
{% endif %} {% endif %}
</div> {% if g.user.access_level == 1 or (g.user and user.id in groupe.get_admins()) %}
<a href="#create-groupe-album">{{ _("Add an album") }}</a>
<a id="delete-album" href="#delete">{{ _("Delete") }}</a>
{% endif %}
</div> </div>
</div> </div>
{% endif %} </div>
</header> </header>
<hr/> <hr/>
{% if groupe.albums|length != 0 %} {% if groupe.albums|length != 0 %}

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-02-29 12:44+0100\n" "POT-Creation-Date: 2024-04-10 18:47+0200\n"
"PO-Revision-Date: 2024-01-22 15:38+0100\n" "PO-Revision-Date: 2024-01-22 15:38+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n" "Language: en\n"
@ -32,94 +32,95 @@ msgstr "This album does not exists, but user %(username)s has been created"
msgid "Missing search query" msgid "Missing search query"
msgstr "Missing search query" msgstr "Missing search query"
#: partitioncloud/modules/albums.py:125 partitioncloud/modules/groupe.py:71 #: partitioncloud/modules/albums.py:124 partitioncloud/modules/auth.py:27
#: partitioncloud/modules/groupe.py:185 #: partitioncloud/modules/auth.py:54 partitioncloud/modules/groupe.py:271
msgid "You need to login to access this resource."
msgstr "You need to login to access this resource."
#: partitioncloud/modules/albums.py:155 partitioncloud/modules/groupe.py:72
#: partitioncloud/modules/groupe.py:186
msgid "Missing name." msgid "Missing name."
msgstr "Missing name." msgstr "Missing name."
#: partitioncloud/modules/albums.py:162 #: partitioncloud/modules/albums.py:192
msgid "This album does not exist." msgid "This album does not exist."
msgstr "This album does not exist." msgstr "This album does not exist."
#: partitioncloud/modules/albums.py:165 #: partitioncloud/modules/albums.py:195
msgid "Album added to collection." msgid "Album added to collection."
msgstr "Album added to collection." msgstr "Album added to collection."
#: partitioncloud/modules/albums.py:179 partitioncloud/modules/albums.py:242 #: partitioncloud/modules/albums.py:209 partitioncloud/modules/albums.py:272
#: partitioncloud/modules/albums.py:354 #: partitioncloud/modules/albums.py:384
msgid "You are not a member of this album" msgid "You are not a member of this album"
msgstr "You are not a member of this album" msgstr "You are not a member of this album"
#: partitioncloud/modules/albums.py:183 #: partitioncloud/modules/albums.py:213
msgid "You are alone here, quitting means deleting this album." msgid "You are alone here, quitting means deleting this album."
msgstr "You are alone here, quitting means deleting this album." msgstr "You are alone here, quitting means deleting this album."
#: partitioncloud/modules/albums.py:187 #: partitioncloud/modules/albums.py:217
msgid "Album quitted." msgid "Album quitted."
msgstr "Album quitted." msgstr "Album quitted."
#: partitioncloud/modules/albums.py:206 #: partitioncloud/modules/albums.py:236
msgid "You are not alone in this album." msgid "You are not alone in this album."
msgstr "You are not alone in this album." msgstr "You are not alone in this album."
#: partitioncloud/modules/albums.py:208 #: partitioncloud/modules/albums.py:238
msgid "You don't own this album." msgid "You don't own this album."
msgstr "You don't own this album." msgstr "You don't own this album."
#: partitioncloud/modules/albums.py:219 #: partitioncloud/modules/albums.py:249
msgid "Album deleted." msgid "Album deleted."
msgstr "Album deleted." msgstr "Album deleted."
#: partitioncloud/modules/albums.py:248 partitioncloud/modules/partition.py:153 #: partitioncloud/modules/albums.py:278 partitioncloud/modules/partition.py:153
#: partitioncloud/modules/partition.py:199 #: partitioncloud/modules/partition.py:199
msgid "Missing title" msgid "Missing title"
msgstr "Missing title" msgstr "Missing title"
#: partitioncloud/modules/albums.py:250 partitioncloud/modules/partition.py:63 #: partitioncloud/modules/albums.py:280 partitioncloud/modules/partition.py:63
msgid "Missing file" msgid "Missing file"
msgstr "Missing file" msgstr "Missing file"
#: partitioncloud/modules/albums.py:262 #: partitioncloud/modules/albums.py:292
msgid "Search results expired" msgid "Search results expired"
msgstr "Search results expired" msgstr "Search results expired"
#: partitioncloud/modules/albums.py:272 #: partitioncloud/modules/albums.py:302
msgid "Invalid PDF file" msgid "Invalid PDF file"
msgstr "" msgstr ""
#: partitioncloud/modules/albums.py:334 #: partitioncloud/modules/albums.py:364
#, python-format #, python-format
msgid "Score %(partition_name)s added" msgid "Score %(partition_name)s added"
msgstr "Score %(partition_name)s added" msgstr "Score %(partition_name)s added"
#: partitioncloud/modules/albums.py:348 #: partitioncloud/modules/albums.py:378
msgid "Selecting an album is mandatory." msgid "Selecting an album is mandatory."
msgstr "Selecting an album is mandatory." msgstr "Selecting an album is mandatory."
#: partitioncloud/modules/albums.py:350 #: partitioncloud/modules/albums.py:380
msgid "Selecting a score is mandatory." msgid "Selecting a score is mandatory."
msgstr "Selecting a score is mandatory." msgstr "Selecting a score is mandatory."
#: partitioncloud/modules/albums.py:352 #: partitioncloud/modules/albums.py:382
msgid "Please specify a score type." msgid "Please specify a score type."
msgstr "Please specify a score type." msgstr "Please specify a score type."
#: partitioncloud/modules/albums.py:374 #: partitioncloud/modules/albums.py:404
msgid "Score added" msgid "Score added"
msgstr "Score added" msgstr "Score added"
#: partitioncloud/modules/albums.py:376 #: partitioncloud/modules/albums.py:406
msgid "Score is already in the album." msgid "Score is already in the album."
msgstr "Score is already in the album." msgstr "Score is already in the album."
#: partitioncloud/modules/albums.py:388 #: partitioncloud/modules/albums.py:418
msgid "Unknown score type." msgid "Unknown score type."
msgstr "Unknown score type." msgstr "Unknown score type."
#: partitioncloud/modules/auth.py:27 partitioncloud/modules/auth.py:54
msgid "You need to login to access this resource."
msgstr "You need to login to access this resource."
#: partitioncloud/modules/auth.py:59 partitioncloud/modules/settings.py:50 #: partitioncloud/modules/auth.py:59 partitioncloud/modules/settings.py:50
#: partitioncloud/modules/settings.py:82 #: partitioncloud/modules/settings.py:82
msgid "Missing rights." msgid "Missing rights."
@ -150,35 +151,35 @@ msgstr "Successfully created new user. You can log in."
msgid "Incorrect username or password" msgid "Incorrect username or password"
msgstr "Incorrect username or password" msgstr "Incorrect username or password"
#: partitioncloud/modules/groupe.py:120 #: partitioncloud/modules/groupe.py:121
msgid "Unknown group." msgid "Unknown group."
msgstr "Unknown group." msgstr "Unknown group."
#: partitioncloud/modules/groupe.py:123 #: partitioncloud/modules/groupe.py:124
msgid "Group added to collection." msgid "Group added to collection."
msgstr "Group added to collection." msgstr "Group added to collection."
#: partitioncloud/modules/groupe.py:134 #: partitioncloud/modules/groupe.py:135
msgid "You are not a member of this group." msgid "You are not a member of this group."
msgstr "You are not a member of this group." msgstr "You are not a member of this group."
#: partitioncloud/modules/groupe.py:138 #: partitioncloud/modules/groupe.py:139
msgid "You are alone here, quitting means deleting this group." msgid "You are alone here, quitting means deleting this group."
msgstr "You are alone here, quitting means deleting this group." msgstr "You are alone here, quitting means deleting this group."
#: partitioncloud/modules/groupe.py:142 #: partitioncloud/modules/groupe.py:143
msgid "Group quitted." msgid "Group quitted."
msgstr "Group quitted." msgstr "Group quitted."
#: partitioncloud/modules/groupe.py:155 #: partitioncloud/modules/groupe.py:156
msgid "You are not alone in this group." msgid "You are not alone in this group."
msgstr "You are not alone in this group." msgstr "You are not alone in this group."
#: partitioncloud/modules/groupe.py:166 #: partitioncloud/modules/groupe.py:167
msgid "Group deleted." msgid "Group deleted."
msgstr "Group deleted." msgstr "Group deleted."
#: partitioncloud/modules/groupe.py:188 #: partitioncloud/modules/groupe.py:189
msgid "You are not admin of this group." msgid "You are not admin of this group."
msgstr "You are not admin of this group." msgstr "You are not admin of this group."
@ -387,7 +388,7 @@ msgid "Scores list"
msgstr "Scores list" msgstr "Scores list"
#: partitioncloud/templates/admin/partitions.html:31 #: partitioncloud/templates/admin/partitions.html:31
#: partitioncloud/templates/albums/album.html:94 #: partitioncloud/templates/albums/album.html:97
msgid "No available scores" msgid "No available scores"
msgstr "No available scores" msgstr "No available scores"
@ -405,10 +406,10 @@ msgid "Do you really want to delete this album?"
msgstr "Do you really want to delete this album?" msgstr "Do you really want to delete this album?"
#: partitioncloud/templates/albums/album.html:16 #: partitioncloud/templates/albums/album.html:16
#: partitioncloud/templates/albums/album.html:60 #: partitioncloud/templates/albums/album.html:64
#: partitioncloud/templates/albums/delete-album.html:8 #: partitioncloud/templates/albums/delete-album.html:8
#: partitioncloud/templates/groupe/index.html:20 #: partitioncloud/templates/groupe/index.html:20
#: partitioncloud/templates/groupe/index.html:53 #: partitioncloud/templates/groupe/index.html:57
#: partitioncloud/templates/partition/delete.html:10 #: partitioncloud/templates/partition/delete.html:10
#: partitioncloud/templates/partition/details.html:86 #: partitioncloud/templates/partition/details.html:86
#: partitioncloud/templates/partition/edit.html:57 #: partitioncloud/templates/partition/edit.html:57
@ -416,25 +417,30 @@ msgstr "Do you really want to delete this album?"
msgid "Delete" msgid "Delete"
msgstr "Delete" msgstr "Delete"
#: partitioncloud/templates/albums/album.html:51 #: partitioncloud/templates/albums/album.html:52
msgid "Add a score" msgid "Add a score"
msgstr "Add a score" msgstr "Add a score"
#: partitioncloud/templates/albums/album.html:54 #: partitioncloud/templates/albums/album.html:55
#: partitioncloud/templates/groupe/index.html:46 #: partitioncloud/templates/groupe/index.html:47
msgid "Join" msgid "Join"
msgstr "Join" msgstr "Join"
#: partitioncloud/templates/albums/album.html:56 #: partitioncloud/templates/albums/album.html:57
#: partitioncloud/templates/groupe/index.html:48 #: partitioncloud/templates/groupe/index.html:49
msgid "Quit" msgid "Quit"
msgstr "Quit" msgstr "Quit"
#: partitioncloud/templates/albums/album.html:58 #: partitioncloud/templates/albums/album.html:59
#: partitioncloud/templates/groupe/index.html:50 #: partitioncloud/templates/groupe/index.html:51
msgid "Share" msgid "Share"
msgstr "Share" msgstr "Share"
#: partitioncloud/templates/albums/album.html:61
#: partitioncloud/templates/groupe/index.html:53
msgid "Download as zip"
msgstr "Download as zip"
#: partitioncloud/templates/albums/delete-album.html:3 #: partitioncloud/templates/albums/delete-album.html:3
#: partitioncloud/templates/partition/delete.html:4 #: partitioncloud/templates/partition/delete.html:4
#, python-format #, python-format
@ -539,15 +545,15 @@ msgstr "Delete group"
msgid "Do you really want to delete this group and the albums it contains?" msgid "Do you really want to delete this group and the albums it contains?"
msgstr "Do you really want to delete this group and the albums it contains?" msgstr "Do you really want to delete this group and the albums it contains?"
#: partitioncloud/templates/groupe/index.html:52 #: partitioncloud/templates/groupe/index.html:56
msgid "Add an album" msgid "Add an album"
msgstr "Add an album" msgstr "Add an album"
#: partitioncloud/templates/groupe/index.html:74 #: partitioncloud/templates/groupe/index.html:77
msgid "Create one" msgid "Create one"
msgstr "Create one" msgstr "Create one"
#: partitioncloud/templates/groupe/index.html:77 #: partitioncloud/templates/groupe/index.html:80
#, python-format #, python-format
msgid "No available album. %(create)s" msgid "No available album. %(create)s"
msgstr "No available album. %(create)s" msgstr "No available album. %(create)s"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PROJECT VERSION\n" "Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-02-29 12:44+0100\n" "POT-Creation-Date: 2024-04-10 18:47+0200\n"
"PO-Revision-Date: 2024-01-22 15:24+0100\n" "PO-Revision-Date: 2024-01-22 15:24+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: fr\n" "Language: fr\n"
@ -32,94 +32,95 @@ msgstr "Cet album n'existe pas. L'utilisateur %(username)s a été créé"
msgid "Missing search query" msgid "Missing search query"
msgstr "Aucun terme de recherche spécifié." msgstr "Aucun terme de recherche spécifié."
#: partitioncloud/modules/albums.py:125 partitioncloud/modules/groupe.py:71 #: partitioncloud/modules/albums.py:124 partitioncloud/modules/auth.py:27
#: partitioncloud/modules/groupe.py:185 #: partitioncloud/modules/auth.py:54 partitioncloud/modules/groupe.py:271
msgid "You need to login to access this resource."
msgstr "Vous devez être connecté pour accéder à cette page."
#: partitioncloud/modules/albums.py:155 partitioncloud/modules/groupe.py:72
#: partitioncloud/modules/groupe.py:186
msgid "Missing name." msgid "Missing name."
msgstr "Un nom est requis." msgstr "Un nom est requis."
#: partitioncloud/modules/albums.py:162 #: partitioncloud/modules/albums.py:192
msgid "This album does not exist." msgid "This album does not exist."
msgstr "Cet album n'existe pas." msgstr "Cet album n'existe pas."
#: partitioncloud/modules/albums.py:165 #: partitioncloud/modules/albums.py:195
msgid "Album added to collection." msgid "Album added to collection."
msgstr "Album ajouté à la collection." msgstr "Album ajouté à la collection."
#: partitioncloud/modules/albums.py:179 partitioncloud/modules/albums.py:242 #: partitioncloud/modules/albums.py:209 partitioncloud/modules/albums.py:272
#: partitioncloud/modules/albums.py:354 #: partitioncloud/modules/albums.py:384
msgid "You are not a member of this album" msgid "You are not a member of this album"
msgstr "Vous ne faites pas partie de cet album" msgstr "Vous ne faites pas partie de cet album"
#: partitioncloud/modules/albums.py:183 #: partitioncloud/modules/albums.py:213
msgid "You are alone here, quitting means deleting this album." msgid "You are alone here, quitting means deleting this album."
msgstr "Vous êtes seul dans cet album, le quitter entraînera sa suppression." msgstr "Vous êtes seul dans cet album, le quitter entraînera sa suppression."
#: partitioncloud/modules/albums.py:187 #: partitioncloud/modules/albums.py:217
msgid "Album quitted." msgid "Album quitted."
msgstr "Album quitté." msgstr "Album quitté."
#: partitioncloud/modules/albums.py:206 #: partitioncloud/modules/albums.py:236
msgid "You are not alone in this album." msgid "You are not alone in this album."
msgstr "Vous n'êtes pas seul dans cet album." msgstr "Vous n'êtes pas seul dans cet album."
#: partitioncloud/modules/albums.py:208 #: partitioncloud/modules/albums.py:238
msgid "You don't own this album." msgid "You don't own this album."
msgstr "Vous ne possédez pas cet album." msgstr "Vous ne possédez pas cet album."
#: partitioncloud/modules/albums.py:219 #: partitioncloud/modules/albums.py:249
msgid "Album deleted." msgid "Album deleted."
msgstr "Album supprimé." msgstr "Album supprimé."
#: partitioncloud/modules/albums.py:248 partitioncloud/modules/partition.py:153 #: partitioncloud/modules/albums.py:278 partitioncloud/modules/partition.py:153
#: partitioncloud/modules/partition.py:199 #: partitioncloud/modules/partition.py:199
msgid "Missing title" msgid "Missing title"
msgstr "Un titre est requis." msgstr "Un titre est requis."
#: partitioncloud/modules/albums.py:250 partitioncloud/modules/partition.py:63 #: partitioncloud/modules/albums.py:280 partitioncloud/modules/partition.py:63
msgid "Missing file" msgid "Missing file"
msgstr "Aucun fichier n'a été fourni." msgstr "Aucun fichier n'a été fourni."
#: partitioncloud/modules/albums.py:262 #: partitioncloud/modules/albums.py:292
msgid "Search results expired" msgid "Search results expired"
msgstr "Les résultats de la recherche ont expiré." msgstr "Les résultats de la recherche ont expiré."
#: partitioncloud/modules/albums.py:272 #: partitioncloud/modules/albums.py:302
msgid "Invalid PDF file" msgid "Invalid PDF file"
msgstr "Fichier PDF invalide" msgstr "Fichier PDF invalide"
#: partitioncloud/modules/albums.py:334 #: partitioncloud/modules/albums.py:364
#, python-format #, python-format
msgid "Score %(partition_name)s added" msgid "Score %(partition_name)s added"
msgstr "Partition %(partition_name)s ajoutée" msgstr "Partition %(partition_name)s ajoutée"
#: partitioncloud/modules/albums.py:348 #: partitioncloud/modules/albums.py:378
msgid "Selecting an album is mandatory." msgid "Selecting an album is mandatory."
msgstr "Il est nécessaire de sélectionner un album." msgstr "Il est nécessaire de sélectionner un album."
#: partitioncloud/modules/albums.py:350 #: partitioncloud/modules/albums.py:380
msgid "Selecting a score is mandatory." msgid "Selecting a score is mandatory."
msgstr "Il est nécessaire de sélectionner une partition." msgstr "Il est nécessaire de sélectionner une partition."
#: partitioncloud/modules/albums.py:352 #: partitioncloud/modules/albums.py:382
msgid "Please specify a score type." msgid "Please specify a score type."
msgstr "Il est nécessaire de spécifier un type de partition." msgstr "Il est nécessaire de spécifier un type de partition."
#: partitioncloud/modules/albums.py:374 #: partitioncloud/modules/albums.py:404
msgid "Score added" msgid "Score added"
msgstr "Partition ajoutée." msgstr "Partition ajoutée."
#: partitioncloud/modules/albums.py:376 #: partitioncloud/modules/albums.py:406
msgid "Score is already in the album." msgid "Score is already in the album."
msgstr "Partition déjà dans l'album." msgstr "Partition déjà dans l'album."
#: partitioncloud/modules/albums.py:388 #: partitioncloud/modules/albums.py:418
msgid "Unknown score type." msgid "Unknown score type."
msgstr "Type de partition inconnu." msgstr "Type de partition inconnu."
#: partitioncloud/modules/auth.py:27 partitioncloud/modules/auth.py:54
msgid "You need to login to access this resource."
msgstr "Vous devez être connecté pour accéder à cette page."
#: partitioncloud/modules/auth.py:59 partitioncloud/modules/settings.py:50 #: partitioncloud/modules/auth.py:59 partitioncloud/modules/settings.py:50
#: partitioncloud/modules/settings.py:82 #: partitioncloud/modules/settings.py:82
msgid "Missing rights." msgid "Missing rights."
@ -152,35 +153,35 @@ msgstr "Utilisateur créé avec succès. Vous pouvez vous connecter."
msgid "Incorrect username or password" msgid "Incorrect username or password"
msgstr "Nom d'utilisateur ou mot de passe incorrect." msgstr "Nom d'utilisateur ou mot de passe incorrect."
#: partitioncloud/modules/groupe.py:120 #: partitioncloud/modules/groupe.py:121
msgid "Unknown group." msgid "Unknown group."
msgstr "Ce groupe n'existe pas." msgstr "Ce groupe n'existe pas."
#: partitioncloud/modules/groupe.py:123 #: partitioncloud/modules/groupe.py:124
msgid "Group added to collection." msgid "Group added to collection."
msgstr "Groupe ajouté à la collection." msgstr "Groupe ajouté à la collection."
#: partitioncloud/modules/groupe.py:134 #: partitioncloud/modules/groupe.py:135
msgid "You are not a member of this group." msgid "You are not a member of this group."
msgstr "Vous ne faites pas partie de ce groupe" msgstr "Vous ne faites pas partie de ce groupe"
#: partitioncloud/modules/groupe.py:138 #: partitioncloud/modules/groupe.py:139
msgid "You are alone here, quitting means deleting this group." msgid "You are alone here, quitting means deleting this group."
msgstr "Vous êtes seul dans ce groupe, le quitter entraînera sa suppression." msgstr "Vous êtes seul dans ce groupe, le quitter entraînera sa suppression."
#: partitioncloud/modules/groupe.py:142 #: partitioncloud/modules/groupe.py:143
msgid "Group quitted." msgid "Group quitted."
msgstr "Groupe quitté." msgstr "Groupe quitté."
#: partitioncloud/modules/groupe.py:155 #: partitioncloud/modules/groupe.py:156
msgid "You are not alone in this group." msgid "You are not alone in this group."
msgstr "Vous n'êtes pas seul dans ce groupe." msgstr "Vous n'êtes pas seul dans ce groupe."
#: partitioncloud/modules/groupe.py:166 #: partitioncloud/modules/groupe.py:167
msgid "Group deleted." msgid "Group deleted."
msgstr "Groupe supprimé." msgstr "Groupe supprimé."
#: partitioncloud/modules/groupe.py:188 #: partitioncloud/modules/groupe.py:189
msgid "You are not admin of this group." msgid "You are not admin of this group."
msgstr "Vous n'êtes pas administrateur de ce groupe" msgstr "Vous n'êtes pas administrateur de ce groupe"
@ -393,7 +394,7 @@ msgid "Scores list"
msgstr "Liste des partitions" msgstr "Liste des partitions"
#: partitioncloud/templates/admin/partitions.html:31 #: partitioncloud/templates/admin/partitions.html:31
#: partitioncloud/templates/albums/album.html:94 #: partitioncloud/templates/albums/album.html:97
msgid "No available scores" msgid "No available scores"
msgstr "Aucune partition disponible" msgstr "Aucune partition disponible"
@ -411,10 +412,10 @@ msgid "Do you really want to delete this album?"
msgstr "Êtes vous sûr de vouloir supprimer cet album ?" msgstr "Êtes vous sûr de vouloir supprimer cet album ?"
#: partitioncloud/templates/albums/album.html:16 #: partitioncloud/templates/albums/album.html:16
#: partitioncloud/templates/albums/album.html:60 #: partitioncloud/templates/albums/album.html:64
#: partitioncloud/templates/albums/delete-album.html:8 #: partitioncloud/templates/albums/delete-album.html:8
#: partitioncloud/templates/groupe/index.html:20 #: partitioncloud/templates/groupe/index.html:20
#: partitioncloud/templates/groupe/index.html:53 #: partitioncloud/templates/groupe/index.html:57
#: partitioncloud/templates/partition/delete.html:10 #: partitioncloud/templates/partition/delete.html:10
#: partitioncloud/templates/partition/details.html:86 #: partitioncloud/templates/partition/details.html:86
#: partitioncloud/templates/partition/edit.html:57 #: partitioncloud/templates/partition/edit.html:57
@ -422,25 +423,30 @@ msgstr "Êtes vous sûr de vouloir supprimer cet album ?"
msgid "Delete" msgid "Delete"
msgstr "Supprimer" msgstr "Supprimer"
#: partitioncloud/templates/albums/album.html:51 #: partitioncloud/templates/albums/album.html:52
msgid "Add a score" msgid "Add a score"
msgstr "Ajouter une partition" msgstr "Ajouter une partition"
#: partitioncloud/templates/albums/album.html:54 #: partitioncloud/templates/albums/album.html:55
#: partitioncloud/templates/groupe/index.html:46 #: partitioncloud/templates/groupe/index.html:47
msgid "Join" msgid "Join"
msgstr "Rejoindre" msgstr "Rejoindre"
#: partitioncloud/templates/albums/album.html:56 #: partitioncloud/templates/albums/album.html:57
#: partitioncloud/templates/groupe/index.html:48 #: partitioncloud/templates/groupe/index.html:49
msgid "Quit" msgid "Quit"
msgstr "Quitter" msgstr "Quitter"
#: partitioncloud/templates/albums/album.html:58 #: partitioncloud/templates/albums/album.html:59
#: partitioncloud/templates/groupe/index.html:50 #: partitioncloud/templates/groupe/index.html:51
msgid "Share" msgid "Share"
msgstr "Partager" msgstr "Partager"
#: partitioncloud/templates/albums/album.html:61
#: partitioncloud/templates/groupe/index.html:53
msgid "Download as zip"
msgstr "Télécharger le zip"
#: partitioncloud/templates/albums/delete-album.html:3 #: partitioncloud/templates/albums/delete-album.html:3
#: partitioncloud/templates/partition/delete.html:4 #: partitioncloud/templates/partition/delete.html:4
#, python-format #, python-format
@ -548,15 +554,15 @@ msgstr ""
" sous-jacents et leurs partitions si personne ne les a rejoints " " sous-jacents et leurs partitions si personne ne les a rejoints "
"(indépendamment du groupe)." "(indépendamment du groupe)."
#: partitioncloud/templates/groupe/index.html:52 #: partitioncloud/templates/groupe/index.html:56
msgid "Add an album" msgid "Add an album"
msgstr "Ajouter un album" msgstr "Ajouter un album"
#: partitioncloud/templates/groupe/index.html:74 #: partitioncloud/templates/groupe/index.html:77
msgid "Create one" msgid "Create one"
msgstr "En créer un" msgstr "En créer un"
#: partitioncloud/templates/groupe/index.html:77 #: partitioncloud/templates/groupe/index.html:80
#, python-format #, python-format
msgid "No available album. %(create)s" msgid "No available album. %(create)s"
msgstr "Aucun album disponible. %(create)s" msgstr "Aucun album disponible. %(create)s"

View File

@ -201,11 +201,18 @@ if __name__ == "__main__":
"--restore", "--restore",
help="restore from specific version backup, will not apply any hook (vx.y.z)", help="restore from specific version backup, will not apply any hook (vx.y.z)",
) )
parser.add_argument(
"-b",
"--backup",
help="backup current version, without running any hooks",
)
args = parser.parse_args() args = parser.parse_args()
config.instance = os.path.abspath(args.instance) config.instance = os.path.abspath(args.instance)
if args.restore is None: if args.restore is not None:
migrate(args.current, args.target, skip_backup=args.skip_backup)
else:
restore(args.restore) restore(args.restore)
elif args.backup is not None:
backup_instance(args.backup, verbose=True)
else:
migrate(args.current, args.target, skip_backup=args.skip_backup)