mirror of
https://github.com/partitioncloud/partitioncloud-server.git
synced 2025-01-23 17:26:26 +01:00
Compare commits
6 Commits
4fff0e49e2
...
972231e4b2
Author | SHA1 | Date | |
---|---|---|---|
972231e4b2 | |||
8ff2f29617 | |||
d35fd063bd | |||
3f68ac0419 | |||
a65a80cd8b | |||
3e2569222a |
@ -9,7 +9,7 @@ from flask import Flask, g, redirect, render_template, request, send_file, flash
|
||||
from werkzeug.security import generate_password_hash
|
||||
|
||||
from .modules.utils import User, Album, get_all_albums
|
||||
from .modules import albums, auth, partition, admin
|
||||
from .modules import albums, auth, partition, admin, groupe
|
||||
from .modules.auth import admin_required, login_required
|
||||
from .modules.db import get_db
|
||||
|
||||
@ -26,6 +26,7 @@ else:
|
||||
|
||||
app.register_blueprint(auth.bp)
|
||||
app.register_blueprint(admin.bp)
|
||||
app.register_blueprint(groupe.bp)
|
||||
app.register_blueprint(albums.bp)
|
||||
app.register_blueprint(partition.bp)
|
||||
|
||||
|
@ -27,7 +27,6 @@ def index():
|
||||
for u in users:
|
||||
u.albums = u.get_albums()
|
||||
u.partitions = u.get_partitions()
|
||||
db.close()
|
||||
|
||||
return render_template(
|
||||
"admin/index.html",
|
||||
|
@ -171,10 +171,10 @@ def join_album(uuid):
|
||||
user.join_album(uuid)
|
||||
except LookupError:
|
||||
flash("Cet album n'existe pas.")
|
||||
return redirect(f"/albums/{uuid}")
|
||||
return redirect(request.referrer)
|
||||
|
||||
flash("Album ajouté à la collection.")
|
||||
return redirect(f"/albums/{uuid}")
|
||||
return redirect(request.referrer)
|
||||
|
||||
|
||||
@bp.route("/<uuid>/quit")
|
||||
@ -185,7 +185,7 @@ def quit_album(uuid):
|
||||
users = album.get_users()
|
||||
if user.id not in [u["id"] for u in users]:
|
||||
flash("Vous ne faites pas partie de cet album")
|
||||
return redirect(f"/albums/{uuid}")
|
||||
return redirect(request.referrer)
|
||||
|
||||
if len(users) == 1:
|
||||
flash("Vous êtes seul dans cet album, le quitter entraînera sa suppression.")
|
||||
@ -218,7 +218,7 @@ def delete_album(uuid):
|
||||
|
||||
if error is not None:
|
||||
flash(error)
|
||||
return redirect(f"/albums/{uuid}")
|
||||
return redirect(request.referrer)
|
||||
|
||||
album.delete()
|
||||
|
||||
@ -236,7 +236,7 @@ def add_partition(album_uuid):
|
||||
|
||||
if (not user.is_participant(album.uuid)) and (user.access_level != 1):
|
||||
flash("Vous ne participez pas à cet album.")
|
||||
return redirect(f"/albums/{album.uuid}")
|
||||
return redirect(request.referrer)
|
||||
|
||||
error = None
|
||||
|
||||
@ -264,7 +264,7 @@ def add_partition(album_uuid):
|
||||
|
||||
if error is not None:
|
||||
flash(error)
|
||||
return redirect(f"/albums/{album.uuid}")
|
||||
return redirect(request.referrer)
|
||||
|
||||
if "author" in request.form:
|
||||
author = request.form["author"]
|
||||
|
@ -123,7 +123,6 @@ def register():
|
||||
return redirect(url_for("auth.login"))
|
||||
|
||||
flash(error)
|
||||
db.close()
|
||||
|
||||
return render_template("auth/register.html")
|
||||
|
||||
|
146
partitioncloud/modules/classes/album.py
Normal file
146
partitioncloud/modules/classes/album.py
Normal file
@ -0,0 +1,146 @@
|
||||
import os
|
||||
|
||||
from ..db import get_db
|
||||
|
||||
|
||||
|
||||
class Album():
|
||||
def __init__(self, uuid=None, id=None):
|
||||
db = get_db()
|
||||
if uuid is not None:
|
||||
self.uuid = uuid
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT id, name FROM album
|
||||
WHERE uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
).fetchone()
|
||||
if data is None:
|
||||
raise LookupError
|
||||
self.id = data["id"]
|
||||
self.name = data["name"]
|
||||
|
||||
elif id is not None:
|
||||
self.id = id
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT uuid, name FROM album
|
||||
WHERE id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
).fetchone()
|
||||
if data is None:
|
||||
raise LookupError
|
||||
self.uuid = data["uuid"]
|
||||
self.name = data["name"]
|
||||
|
||||
else:
|
||||
raise LookupError
|
||||
|
||||
self.users = None
|
||||
|
||||
|
||||
def get_users(self, force_reload=False):
|
||||
"""
|
||||
Renvoie les utilisateurs liés à l'album
|
||||
"""
|
||||
if self.users is None or force_reload:
|
||||
db = get_db()
|
||||
self.users = db.execute(
|
||||
"""
|
||||
SELECT * FROM user
|
||||
JOIN contient_user ON user_id = user.id
|
||||
JOIN album ON album.id = album_id
|
||||
WHERE album.uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
).fetchall()
|
||||
return self.users
|
||||
|
||||
def get_partitions(self):
|
||||
"""
|
||||
Renvoie les partitions liées à l'album
|
||||
"""
|
||||
db = get_db()
|
||||
return db.execute(
|
||||
"""
|
||||
SELECT partition.uuid, partition.name, partition.author, partition.user_id FROM partition
|
||||
JOIN contient_partition ON partition_uuid = partition.uuid
|
||||
JOIN album ON album.id = album_id
|
||||
WHERE album.uuid = ?
|
||||
""",
|
||||
(self.uuid,),
|
||||
).fetchall()
|
||||
|
||||
|
||||
def delete(self):
|
||||
"""
|
||||
Supprimer l'album
|
||||
"""
|
||||
db = get_db()
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM album
|
||||
WHERE uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
)
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM contient_user
|
||||
WHERE album_id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
)
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM contient_partition
|
||||
WHERE album_id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
)
|
||||
db.commit()
|
||||
# Delete orphan partitions
|
||||
partitions = db.execute(
|
||||
"""
|
||||
SELECT partition.uuid FROM partition
|
||||
WHERE NOT EXISTS (
|
||||
SELECT NULL FROM contient_partition
|
||||
WHERE partition.uuid = partition_uuid
|
||||
)
|
||||
"""
|
||||
)
|
||||
for partition in partitions.fetchall():
|
||||
os.remove(f"partitioncloud/partitions/{partition['uuid']}.pdf")
|
||||
if os.path.exists(f"partitioncloud/static/thumbnails/{partition['uuid']}.jpg"):
|
||||
os.remove(f"partitioncloud/static/thumbnails/{partition['uuid']}.jpg")
|
||||
|
||||
partitions = db.execute(
|
||||
"""
|
||||
DELETE FROM partition
|
||||
WHERE uuid IN (
|
||||
SELECT partition.uuid FROM partition
|
||||
WHERE NOT EXISTS (
|
||||
SELECT NULL FROM contient_partition
|
||||
WHERE partition.uuid = partition_uuid
|
||||
)
|
||||
)
|
||||
"""
|
||||
)
|
||||
db.commit()
|
||||
|
||||
|
||||
def add_partition(self, partition_uuid):
|
||||
"""
|
||||
Ajoute une partition à l'album à partir de son uuid
|
||||
"""
|
||||
db = get_db()
|
||||
db.execute(
|
||||
"""
|
||||
INSERT INTO contient_partition (partition_uuid, album_id)
|
||||
VALUES (?, ?)
|
||||
""",
|
||||
(partition_uuid, self.id),
|
||||
)
|
||||
db.commit()
|
118
partitioncloud/modules/classes/groupe.py
Normal file
118
partitioncloud/modules/classes/groupe.py
Normal file
@ -0,0 +1,118 @@
|
||||
from ..db import get_db
|
||||
from .album import Album
|
||||
|
||||
class Groupe():
|
||||
def __init__(self, uuid):
|
||||
db=get_db()
|
||||
|
||||
self.uuid = uuid
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT * FROM groupe
|
||||
WHERE uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
).fetchone()
|
||||
if data is None:
|
||||
raise LookupError
|
||||
self.name = data["name"]
|
||||
self.id = data["id"]
|
||||
self.users = None
|
||||
self.albums = None
|
||||
self.admins = None
|
||||
|
||||
def delete(self):
|
||||
"""
|
||||
Supprime le groupe, et les albums laissés orphelins (sans utilisateur)
|
||||
"""
|
||||
db = get_db()
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM groupe
|
||||
WHERE id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
)
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM groupe_contient_user
|
||||
WHERE groupe_id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
)
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM groupe_contient_album
|
||||
WHERE groupe_id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
# Supprime tous les albums laissés orphelins (maintenant ou plus tôt)
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT id FROM album
|
||||
LEFT JOIN groupe_contient_album
|
||||
LEFT JOIN contient_user
|
||||
ON groupe_contient_album.album_id=album.id
|
||||
AND contient_user.album_id=album.id
|
||||
WHERE user_id IS NULL AND groupe_id IS NULL
|
||||
"""
|
||||
).fetchall()
|
||||
|
||||
for i in data:
|
||||
album = Album(id=i["id"])
|
||||
album.delete()
|
||||
|
||||
|
||||
def get_users(self):
|
||||
"""
|
||||
Renvoie les data["id"] des utilisateurs liés au groupe
|
||||
TODO: uniformiser le tout
|
||||
"""
|
||||
db = get_db()
|
||||
return db.execute(
|
||||
"""
|
||||
SELECT * FROM user
|
||||
JOIN groupe_contient_user ON user_id = user.id
|
||||
JOIN groupe ON groupe.id = groupe_id
|
||||
WHERE groupe.id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
).fetchall()
|
||||
|
||||
def get_albums(self, force_reload=False):
|
||||
"""
|
||||
Renvoie les uuids des albums liés au groupe
|
||||
"""
|
||||
if self.albums is None or force_reload:
|
||||
db = get_db()
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT * FROM album
|
||||
JOIN groupe_contient_album ON album_id = album.id
|
||||
JOIN groupe ON groupe.id = groupe_id
|
||||
WHERE groupe.id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
).fetchall()
|
||||
self.albums = [Album(uuid=i["uuid"]) for i in data]
|
||||
|
||||
return self.albums
|
||||
|
||||
def get_admins(self):
|
||||
"""
|
||||
Renvoie les ids utilisateurs administrateurs liés au groupe
|
||||
"""
|
||||
db = get_db()
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT user.id FROM user
|
||||
JOIN groupe_contient_user ON user_id = user.id
|
||||
JOIN groupe ON groupe.id = groupe_id
|
||||
WHERE is_admin=1 AND groupe.id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
).fetchall()
|
||||
return [i["id"] for i in data]
|
97
partitioncloud/modules/classes/partition.py
Normal file
97
partitioncloud/modules/classes/partition.py
Normal file
@ -0,0 +1,97 @@
|
||||
import os
|
||||
from flask import current_app
|
||||
|
||||
from ..db import get_db
|
||||
from .user import User
|
||||
|
||||
|
||||
|
||||
class Partition():
|
||||
def __init__(self, uuid=None):
|
||||
db = get_db()
|
||||
if uuid is not None:
|
||||
self.uuid = uuid
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT * FROM partition
|
||||
WHERE uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
).fetchone()
|
||||
if data is None:
|
||||
raise LookupError
|
||||
self.name = data["name"]
|
||||
self.author = data["author"]
|
||||
self.body = data["body"]
|
||||
self.user_id = data["user_id"]
|
||||
self.source = data["source"]
|
||||
else:
|
||||
raise LookupError
|
||||
|
||||
def delete(self):
|
||||
db = get_db()
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM contient_partition
|
||||
WHERE partition_uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
os.remove(f"partitioncloud/partitions/{self.uuid}.pdf")
|
||||
if os.path.exists(f"partitioncloud/static/thumbnails/{self.uuid}.jpg"):
|
||||
os.remove(f"partitioncloud/static/thumbnails/{self.uuid}.jpg")
|
||||
|
||||
partitions = db.execute(
|
||||
"""
|
||||
DELETE FROM partition
|
||||
WHERE uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
def update(self, name=None, author="", body=""):
|
||||
if name is None:
|
||||
return Exception("name cannot be None")
|
||||
|
||||
db = get_db()
|
||||
db.execute(
|
||||
"""
|
||||
UPDATE partition
|
||||
SET name = ?,
|
||||
author = ?,
|
||||
body = ?
|
||||
WHERE uuid = ?
|
||||
""",
|
||||
(name, author, body, self.uuid)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
def get_user(self):
|
||||
db = get_db()
|
||||
user = db.execute(
|
||||
"""
|
||||
SELECT * FROM user
|
||||
JOIN partition ON user_id = user.id
|
||||
WHERE partition.uuid = ?
|
||||
""",
|
||||
(self.uuid,),
|
||||
).fetchone()
|
||||
|
||||
if user is None:
|
||||
raise LookupError
|
||||
|
||||
return User(user_id=user["id"])
|
||||
|
||||
def get_albums(self):
|
||||
db = get_db()
|
||||
return db.execute(
|
||||
"""
|
||||
SELECT * FROM album
|
||||
JOIN contient_partition ON album.id = album_id
|
||||
WHERE partition_uuid = ?
|
||||
""",
|
||||
(self.uuid,),
|
||||
).fetchall()
|
229
partitioncloud/modules/classes/user.py
Normal file
229
partitioncloud/modules/classes/user.py
Normal file
@ -0,0 +1,229 @@
|
||||
from flask import current_app
|
||||
|
||||
from ..db import get_db
|
||||
from .album import Album
|
||||
from .groupe import Groupe
|
||||
|
||||
|
||||
# Variables defined in the CSS
|
||||
colors = [
|
||||
"--color-rosewater",
|
||||
"--color-flamingo",
|
||||
"--color-pink",
|
||||
"--color-mauve",
|
||||
"--color-red",
|
||||
"--color-maroon",
|
||||
"--color-peach",
|
||||
"--color-yellow",
|
||||
"--color-green",
|
||||
"--color-teal",
|
||||
"--color-sky",
|
||||
"--color-sapphire",
|
||||
"--color-blue",
|
||||
"--color-lavender"
|
||||
]
|
||||
|
||||
|
||||
class User():
|
||||
def __init__(self, user_id=None, name=None):
|
||||
self.id = user_id
|
||||
self.username = name
|
||||
self.albums = None
|
||||
self.groupes = None
|
||||
self.partitions = None
|
||||
self.max_queries = 0
|
||||
|
||||
db = get_db()
|
||||
if self.id is None and self.username is None:
|
||||
self.username = ""
|
||||
self.access_level = -1
|
||||
|
||||
else:
|
||||
if self.id is not None:
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT * FROM user
|
||||
WHERE id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
).fetchone()
|
||||
elif self.username is not None:
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT * FROM user
|
||||
WHERE username = ?
|
||||
""",
|
||||
(self.username,)
|
||||
).fetchone()
|
||||
|
||||
self.id = data["id"]
|
||||
self.username = data["username"]
|
||||
self.access_level = data["access_level"]
|
||||
self.color = self.get_color()
|
||||
if self.access_level == 1:
|
||||
self.max_queries = 10
|
||||
else:
|
||||
self.max_queries = current_app.config["MAX_ONLINE_QUERIES"]
|
||||
|
||||
|
||||
def is_participant(self, album_uuid, exclude_groupe=False):
|
||||
db = get_db()
|
||||
|
||||
return (len(db.execute( # Is participant directly in the album
|
||||
"""
|
||||
SELECT album.id FROM album
|
||||
JOIN contient_user ON album_id = album.id
|
||||
JOIN user ON user_id = user.id
|
||||
WHERE user.id = ? AND album.uuid = ?
|
||||
""",
|
||||
(self.id, album_uuid)
|
||||
).fetchall()) == 1 or
|
||||
# Is participant in a group that has this album
|
||||
((not exclude_groupe) and (len(db.execute(
|
||||
"""
|
||||
SELECT album.id FROM album
|
||||
JOIN groupe_contient_album
|
||||
JOIN groupe_contient_user
|
||||
JOIN user
|
||||
ON user_id = user.id
|
||||
AND groupe_contient_user.groupe_id = groupe_contient_album.groupe_id
|
||||
AND album.id = album_id
|
||||
WHERE user.id = ? AND album.uuid = ?
|
||||
""",
|
||||
(self.id, album_uuid)
|
||||
).fetchall()) >= 1))
|
||||
)
|
||||
|
||||
|
||||
def get_albums(self, force_reload=False):
|
||||
if self.albums is None or force_reload:
|
||||
db = get_db()
|
||||
if self.access_level == 1:
|
||||
# On récupère tous les albums qui ne sont pas dans un groupe
|
||||
self.albums = db.execute(
|
||||
"""
|
||||
SELECT * FROM album
|
||||
LEFT JOIN groupe_contient_album
|
||||
ON album_id=album.id
|
||||
WHERE album_id IS NULL
|
||||
"""
|
||||
).fetchall()
|
||||
else:
|
||||
self.albums = db.execute(
|
||||
"""
|
||||
SELECT album.id, name, uuid FROM album
|
||||
JOIN contient_user ON album_id = album.id
|
||||
JOIN user ON user_id = user.id
|
||||
WHERE user.id = ?
|
||||
""",
|
||||
(self.id,),
|
||||
).fetchall()
|
||||
return self.albums
|
||||
|
||||
|
||||
def get_groupes(self, force_reload=False):
|
||||
if self.groupes is None or force_reload:
|
||||
db = get_db()
|
||||
if self.access_level == 1:
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT uuid FROM groupe
|
||||
"""
|
||||
).fetchall()
|
||||
else:
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT uuid FROM groupe
|
||||
JOIN groupe_contient_user ON groupe.id = groupe_id
|
||||
JOIN user ON user_id = user.id
|
||||
WHERE user.id = ?
|
||||
""",
|
||||
(self.id,),
|
||||
).fetchall()
|
||||
|
||||
self.groupes = [Groupe(i["uuid"]) for i in data]
|
||||
|
||||
return self.groupes
|
||||
|
||||
|
||||
def get_partitions(self, force_reload=False):
|
||||
if self.partitions is None or force_reload:
|
||||
db = get_db()
|
||||
if self.access_level == 1:
|
||||
self.partitions = db.execute(
|
||||
"""
|
||||
SELECT * FROM partition
|
||||
"""
|
||||
).fetchall()
|
||||
else:
|
||||
self.partitions = db.execute(
|
||||
"""
|
||||
SELECT * FROM partition
|
||||
JOIN user ON user_id = user.id
|
||||
WHERE user.id = ?
|
||||
""",
|
||||
(self.id,),
|
||||
).fetchall()
|
||||
return self.partitions
|
||||
|
||||
def join_album(self, album_uuid):
|
||||
db = get_db()
|
||||
album = Album(uuid=album_uuid)
|
||||
|
||||
db.execute(
|
||||
"""
|
||||
INSERT INTO contient_user (user_id, album_id)
|
||||
VALUES (?, ?)
|
||||
""",
|
||||
(self.id, album.id)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
def join_groupe(self, groupe_uuid):
|
||||
db = get_db()
|
||||
groupe = Groupe(uuid=groupe_uuid)
|
||||
|
||||
db.execute(
|
||||
"""
|
||||
INSERT INTO groupe_contient_user (groupe_id, user_id)
|
||||
VALUES (?, ?)
|
||||
""",
|
||||
(groupe.id, self.id)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
def quit_album(self, album_uuid):
|
||||
db = get_db()
|
||||
album = Album(uuid=album_uuid)
|
||||
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM contient_user
|
||||
WHERE user_id = ?
|
||||
AND album_id = ?
|
||||
""",
|
||||
(self.id, album.id)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
def quit_groupe(self, groupe_uuid):
|
||||
db = get_db()
|
||||
groupe = Groupe(uuid=groupe_uuid)
|
||||
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM groupe_contient_user
|
||||
WHERE user_id = ?
|
||||
AND groupe_id = ?
|
||||
""",
|
||||
(self.id, groupe.id)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
|
||||
def get_color(self):
|
||||
if len(colors) == 0:
|
||||
integer = hash(self.username) % 16777215
|
||||
return "#" + str(hex(integer))[2:]
|
||||
else:
|
||||
return f"var({colors[hash(self.username) %len(colors)]})"
|
247
partitioncloud/modules/groupe.py
Normal file
247
partitioncloud/modules/groupe.py
Normal file
@ -0,0 +1,247 @@
|
||||
#!/usr/bin/python3
|
||||
"""
|
||||
Groupe module
|
||||
"""
|
||||
import os
|
||||
from uuid import uuid4
|
||||
|
||||
from flask import (Blueprint, abort, flash, redirect, render_template, request,
|
||||
send_file, session, current_app)
|
||||
|
||||
from .auth import login_required
|
||||
from .db import get_db
|
||||
from .utils import User, Album, get_all_partitions, Groupe
|
||||
from . import search
|
||||
|
||||
bp = Blueprint("groupe", __name__, url_prefix="/groupe")
|
||||
|
||||
|
||||
@bp.route("/")
|
||||
def index():
|
||||
return redirect("/")
|
||||
|
||||
|
||||
@bp.route("/<uuid>")
|
||||
def groupe(uuid):
|
||||
"""
|
||||
Groupe page
|
||||
"""
|
||||
try:
|
||||
groupe = Groupe(uuid=uuid)
|
||||
groupe.users = [User(user_id=i["id"]) for i in groupe.get_users()]
|
||||
groupe.get_albums()
|
||||
user = User(user_id=session.get("user_id"))
|
||||
|
||||
if user.id is None:
|
||||
# On ne propose pas aux gens non connectés de rejoindre l'album
|
||||
not_participant = False
|
||||
else:
|
||||
not_participant = not user.id in [i.id for i in groupe.users]
|
||||
|
||||
return render_template(
|
||||
"groupe/index.html",
|
||||
groupe=groupe,
|
||||
not_participant=not_participant,
|
||||
user=user
|
||||
)
|
||||
|
||||
except LookupError:
|
||||
return abort(404)
|
||||
|
||||
|
||||
|
||||
@bp.route("/create-groupe", methods=["POST"])
|
||||
@login_required
|
||||
def create_groupe():
|
||||
current_user = User(user_id=session.get("user_id"))
|
||||
|
||||
name = request.form["name"]
|
||||
db = get_db()
|
||||
error = None
|
||||
|
||||
if not name or name.strip() == "":
|
||||
error = "Un nom est requis. Le groupe n'a pas été créé"
|
||||
|
||||
if error is None:
|
||||
while True:
|
||||
try:
|
||||
uuid = str(uuid4())
|
||||
|
||||
db.execute(
|
||||
"""
|
||||
INSERT INTO groupe (uuid, name)
|
||||
VALUES (?, ?)
|
||||
""",
|
||||
(uuid, name),
|
||||
)
|
||||
db.commit()
|
||||
groupe = Groupe(uuid=uuid)
|
||||
db.execute(
|
||||
"""
|
||||
INSERT INTO groupe_contient_user (user_id, groupe_id, is_admin)
|
||||
VALUES (?, ?, 1)
|
||||
""",
|
||||
(session.get("user_id"), groupe.id),
|
||||
)
|
||||
db.commit()
|
||||
|
||||
break
|
||||
except db.IntegrityError:
|
||||
pass
|
||||
|
||||
return redirect(f"/groupe/{uuid}")
|
||||
|
||||
flash(error)
|
||||
return redirect(request.referrer)
|
||||
|
||||
|
||||
@bp.route("/<uuid>/join")
|
||||
@login_required
|
||||
def join_groupe(uuid):
|
||||
user = User(user_id=session.get("user_id"))
|
||||
try:
|
||||
user.join_groupe(uuid)
|
||||
except LookupError:
|
||||
flash("Ce groupe n'existe pas.")
|
||||
return redirect(f"/groupe/{uuid}")
|
||||
|
||||
flash("Groupe ajouté à la collection.")
|
||||
return redirect(f"/groupe/{uuid}")
|
||||
|
||||
|
||||
@bp.route("/<uuid>/quit")
|
||||
@login_required
|
||||
def quit_groupe(uuid):
|
||||
user = User(user_id=session.get("user_id"))
|
||||
groupe = Groupe(uuid=uuid)
|
||||
users = groupe.get_users()
|
||||
if user.id not in [u["id"] for u in users]:
|
||||
flash("Vous ne faites pas partie de ce groupe")
|
||||
return redirect(f"/groupe/{uuid}")
|
||||
|
||||
if len(users) == 1:
|
||||
flash("Vous êtes seul dans ce groupe, le quitter entraînera sa suppression.")
|
||||
return redirect(f"/groupe/{uuid}#delete")
|
||||
|
||||
user.quit_groupe(groupe.uuid)
|
||||
flash("Groupe quitté.")
|
||||
return redirect(f"/albums")
|
||||
|
||||
|
||||
@bp.route("/<uuid>/delete", methods=["POST"])
|
||||
@login_required
|
||||
def delete_groupe(uuid):
|
||||
db = get_db()
|
||||
groupe = Groupe(uuid=uuid)
|
||||
user = User(user_id=session.get("user_id"))
|
||||
|
||||
error = None
|
||||
users = groupe.get_users()
|
||||
if len(users) > 1:
|
||||
error = "Vous n'êtes pas seul dans ce groupe."
|
||||
|
||||
if user.access_level == 1 or user.id not in groupe.get_admins():
|
||||
error = None
|
||||
|
||||
if error is not None:
|
||||
flash(error)
|
||||
return redirect(request.referrer)
|
||||
|
||||
groupe.delete()
|
||||
|
||||
flash("Groupe supprimé.")
|
||||
return redirect("/albums")
|
||||
|
||||
|
||||
@bp.route("/<groupe_uuid>/create-album", methods=["POST"])
|
||||
@login_required
|
||||
def create_album(groupe_uuid):
|
||||
try:
|
||||
groupe = Groupe(uuid=groupe_uuid)
|
||||
except LookupError:
|
||||
abort(404)
|
||||
|
||||
user = User(user_id=session.get("user_id"))
|
||||
|
||||
name = request.form["name"]
|
||||
db = get_db()
|
||||
error = None
|
||||
|
||||
if not name or name.strip() == "":
|
||||
error = "Un nom est requis. L'album n'a pas été créé"
|
||||
|
||||
if user.id not in groupe.get_admins():
|
||||
error ="Vous n'êtes pas administrateur de ce groupe"
|
||||
|
||||
if error is None:
|
||||
while True:
|
||||
try:
|
||||
uuid = str(uuid4())
|
||||
|
||||
db.execute(
|
||||
"""
|
||||
INSERT INTO album (uuid, name)
|
||||
VALUES (?, ?)
|
||||
""",
|
||||
(uuid, name),
|
||||
)
|
||||
db.commit()
|
||||
album = Album(uuid=uuid)
|
||||
|
||||
db.execute(
|
||||
"""
|
||||
INSERT INTO groupe_contient_album (groupe_id, album_id)
|
||||
VALUES (?, ?)
|
||||
""",
|
||||
(groupe.id, album.id)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
break
|
||||
except db.IntegrityError:
|
||||
pass
|
||||
|
||||
return redirect(f"/groupe/{groupe.uuid}/{uuid}")
|
||||
|
||||
flash(error)
|
||||
return redirect(request.referrer)
|
||||
|
||||
|
||||
|
||||
@bp.route("/<groupe_uuid>/<album_uuid>")
|
||||
def album(groupe_uuid, album_uuid):
|
||||
"""
|
||||
Album page
|
||||
"""
|
||||
try:
|
||||
groupe = Groupe(uuid=groupe_uuid)
|
||||
except LookupError:
|
||||
abort(404)
|
||||
|
||||
album_list = [a for a in groupe.get_albums() if a.uuid == album_uuid]
|
||||
if len(album_list) == 0:
|
||||
abort(404)
|
||||
|
||||
album = album_list[0]
|
||||
user = User(user_id=session.get("user_id"))
|
||||
|
||||
# List of users without duplicate
|
||||
users_id = list(set([i["id"] for i in album.get_users()+groupe.get_users()]))
|
||||
album.users = [User(user_id=id) for id in users_id]
|
||||
|
||||
partitions = album.get_partitions()
|
||||
|
||||
if user.id is None:
|
||||
# On ne propose pas aux gens non connectés de rejoindre l'album
|
||||
not_participant = False
|
||||
else:
|
||||
not_participant = not user.is_participant(album.uuid, exclude_groupe=True)
|
||||
|
||||
return render_template(
|
||||
"albums/album.html",
|
||||
album=album,
|
||||
groupe=groupe,
|
||||
partitions=partitions,
|
||||
not_participant=not_participant,
|
||||
user=user
|
||||
)
|
@ -1,391 +1,12 @@
|
||||
#!/usr/bin/python3
|
||||
import os
|
||||
|
||||
from .db import get_db
|
||||
|
||||
from flask import current_app
|
||||
|
||||
# Variables defined in the CSS
|
||||
colors = [
|
||||
"--color-rosewater",
|
||||
"--color-flamingo",
|
||||
"--color-pink",
|
||||
"--color-mauve",
|
||||
"--color-red",
|
||||
"--color-maroon",
|
||||
"--color-peach",
|
||||
"--color-yellow",
|
||||
"--color-green",
|
||||
"--color-teal",
|
||||
"--color-sky",
|
||||
"--color-sapphire",
|
||||
"--color-blue",
|
||||
"--color-lavender"
|
||||
]
|
||||
|
||||
class User():
|
||||
def __init__(self, user_id=None, name=None):
|
||||
self.id = user_id
|
||||
self.username = name
|
||||
self.albums = None
|
||||
self.partitions = None
|
||||
self.max_queries = 0
|
||||
|
||||
db = get_db()
|
||||
if self.id is None and self.username is None:
|
||||
self.username = ""
|
||||
self.access_level = -1
|
||||
|
||||
else:
|
||||
if self.id is not None:
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT * FROM user
|
||||
WHERE id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
).fetchone()
|
||||
elif self.username is not None:
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT * FROM user
|
||||
WHERE username = ?
|
||||
""",
|
||||
(self.username,)
|
||||
).fetchone()
|
||||
|
||||
self.id = data["id"]
|
||||
self.username = data["username"]
|
||||
self.access_level = data["access_level"]
|
||||
self.color = self.get_color()
|
||||
if self.access_level == 1:
|
||||
self.max_queries = 10
|
||||
else:
|
||||
self.max_queries = current_app.config["MAX_ONLINE_QUERIES"]
|
||||
|
||||
|
||||
def is_participant(self, album_uuid):
|
||||
db = get_db()
|
||||
|
||||
return len(db.execute(
|
||||
"""
|
||||
SELECT album.id FROM album
|
||||
JOIN contient_user ON album_id = album.id
|
||||
JOIN user ON user_id = user.id
|
||||
WHERE user.id = ? AND album.uuid = ?
|
||||
""",
|
||||
(self.id, album_uuid)
|
||||
).fetchall()) == 1
|
||||
|
||||
|
||||
def get_albums(self, force_reload=False):
|
||||
if self.albums is None or force_reload:
|
||||
db = get_db()
|
||||
if self.access_level == 1:
|
||||
self.albums = db.execute(
|
||||
"""
|
||||
SELECT * FROM album
|
||||
"""
|
||||
).fetchall()
|
||||
else:
|
||||
self.albums = db.execute(
|
||||
"""
|
||||
SELECT album.id, name, uuid FROM album
|
||||
JOIN contient_user ON album_id = album.id
|
||||
JOIN user ON user_id = user.id
|
||||
WHERE user.id = ?
|
||||
""",
|
||||
(self.id,),
|
||||
).fetchall()
|
||||
return self.albums
|
||||
|
||||
|
||||
def get_partitions(self, force_reload=False):
|
||||
if self.partitions is None or force_reload:
|
||||
db = get_db()
|
||||
if self.access_level == 1:
|
||||
self.partitions = db.execute(
|
||||
"""
|
||||
SELECT * FROM partition
|
||||
"""
|
||||
).fetchall()
|
||||
else:
|
||||
self.partitions = db.execute(
|
||||
"""
|
||||
SELECT * FROM partition
|
||||
JOIN user ON user_id = user.id
|
||||
WHERE user.id = ?
|
||||
""",
|
||||
(self.id,),
|
||||
).fetchall()
|
||||
return self.partitions
|
||||
|
||||
def join_album(self, album_uuid):
|
||||
db = get_db()
|
||||
album = Album(uuid=album_uuid)
|
||||
|
||||
db.execute(
|
||||
"""
|
||||
INSERT INTO contient_user (user_id, album_id)
|
||||
VALUES (?, ?)
|
||||
""",
|
||||
(self.id, album.id)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
def quit_album(self, album_uuid):
|
||||
db = get_db()
|
||||
album = Album(uuid=album_uuid)
|
||||
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM contient_user
|
||||
WHERE user_id = ?
|
||||
AND album_id = ?
|
||||
""",
|
||||
(self.id, album.id)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
|
||||
def get_color(self):
|
||||
if len(colors) == 0:
|
||||
integer = hash(self.username) % 16777215
|
||||
return "#" + str(hex(integer))[2:]
|
||||
else:
|
||||
return f"var({colors[hash(self.username) %len(colors)]})"
|
||||
|
||||
|
||||
|
||||
class Album():
|
||||
def __init__(self, uuid=None, id=None):
|
||||
db = get_db()
|
||||
if uuid is not None:
|
||||
self.uuid = uuid
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT id, name FROM album
|
||||
WHERE uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
).fetchone()
|
||||
if data is None:
|
||||
raise LookupError
|
||||
self.id = data["id"]
|
||||
self.name = data["name"]
|
||||
|
||||
elif id is not None:
|
||||
self.id = id
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT uuid, name FROM album
|
||||
WHERE id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
).fetchone()
|
||||
if data is None:
|
||||
raise LookupError
|
||||
self.uuid = data["uuid"]
|
||||
self.name = data["name"]
|
||||
|
||||
else:
|
||||
raise LookupError
|
||||
|
||||
self.users = None
|
||||
|
||||
|
||||
def get_users(self):
|
||||
"""
|
||||
Renvoie les utilisateurs liés à l'album
|
||||
"""
|
||||
db = get_db()
|
||||
return db.execute(
|
||||
"""
|
||||
SELECT * FROM user
|
||||
JOIN contient_user ON user_id = user.id
|
||||
JOIN album ON album.id = album_id
|
||||
WHERE album.uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
).fetchall()
|
||||
|
||||
def get_partitions(self):
|
||||
"""
|
||||
Renvoie les partitions liées à l'album
|
||||
"""
|
||||
db = get_db()
|
||||
return db.execute(
|
||||
"""
|
||||
SELECT partition.uuid, partition.name, partition.author, partition.user_id FROM partition
|
||||
JOIN contient_partition ON partition_uuid = partition.uuid
|
||||
JOIN album ON album.id = album_id
|
||||
WHERE album.uuid = ?
|
||||
""",
|
||||
(self.uuid,),
|
||||
).fetchall()
|
||||
|
||||
|
||||
def delete(self):
|
||||
"""
|
||||
Supprimer l'album
|
||||
"""
|
||||
db = get_db()
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM album
|
||||
WHERE uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
)
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM contient_user
|
||||
WHERE album_id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
)
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM contient_partition
|
||||
WHERE album_id = ?
|
||||
""",
|
||||
(self.id,)
|
||||
)
|
||||
db.commit()
|
||||
# Delete orphan partitions
|
||||
partitions = db.execute(
|
||||
"""
|
||||
SELECT partition.uuid FROM partition
|
||||
WHERE NOT EXISTS (
|
||||
SELECT NULL FROM contient_partition
|
||||
WHERE partition.uuid = partition_uuid
|
||||
)
|
||||
"""
|
||||
)
|
||||
for partition in partitions.fetchall():
|
||||
os.remove(f"partitioncloud/partitions/{partition['uuid']}.pdf")
|
||||
if os.path.exists(f"partitioncloud/static/thumbnails/{partition['uuid']}.jpg"):
|
||||
os.remove(f"partitioncloud/static/thumbnails/{partition['uuid']}.jpg")
|
||||
|
||||
partitions = db.execute(
|
||||
"""
|
||||
DELETE FROM partition
|
||||
WHERE uuid IN (
|
||||
SELECT partition.uuid FROM partition
|
||||
WHERE NOT EXISTS (
|
||||
SELECT NULL FROM contient_partition
|
||||
WHERE partition.uuid = partition_uuid
|
||||
)
|
||||
)
|
||||
"""
|
||||
)
|
||||
db.commit()
|
||||
|
||||
|
||||
def add_partition(self, partition_uuid):
|
||||
"""
|
||||
Ajoute une partition à l'album à partir de son uuid
|
||||
"""
|
||||
db = get_db()
|
||||
db.execute(
|
||||
"""
|
||||
INSERT INTO contient_partition (partition_uuid, album_id)
|
||||
VALUES (?, ?)
|
||||
""",
|
||||
(partition_uuid, self.id),
|
||||
)
|
||||
db.commit()
|
||||
|
||||
|
||||
class Partition():
|
||||
def __init__(self, uuid=None):
|
||||
db = get_db()
|
||||
if uuid is not None:
|
||||
self.uuid = uuid
|
||||
data = db.execute(
|
||||
"""
|
||||
SELECT * FROM partition
|
||||
WHERE uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
).fetchone()
|
||||
if data is None:
|
||||
raise LookupError
|
||||
self.name = data["name"]
|
||||
self.author = data["author"]
|
||||
self.body = data["body"]
|
||||
self.user_id = data["user_id"]
|
||||
self.source = data["source"]
|
||||
else:
|
||||
raise LookupError
|
||||
|
||||
def delete(self):
|
||||
db = get_db()
|
||||
db.execute(
|
||||
"""
|
||||
DELETE FROM contient_partition
|
||||
WHERE partition_uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
os.remove(f"partitioncloud/partitions/{self.uuid}.pdf")
|
||||
if os.path.exists(f"partitioncloud/static/thumbnails/{self.uuid}.jpg"):
|
||||
os.remove(f"partitioncloud/static/thumbnails/{self.uuid}.jpg")
|
||||
|
||||
partitions = db.execute(
|
||||
"""
|
||||
DELETE FROM partition
|
||||
WHERE uuid = ?
|
||||
""",
|
||||
(self.uuid,)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
def update(self, name=None, author="", body=""):
|
||||
if name is None:
|
||||
return Exception("name cannot be None")
|
||||
|
||||
db = get_db()
|
||||
db.execute(
|
||||
"""
|
||||
UPDATE partition
|
||||
SET name = ?,
|
||||
author = ?,
|
||||
body = ?
|
||||
WHERE uuid = ?
|
||||
""",
|
||||
(name, author, body, self.uuid)
|
||||
)
|
||||
db.commit()
|
||||
|
||||
def get_user(self):
|
||||
db = get_db()
|
||||
user = db.execute(
|
||||
"""
|
||||
SELECT * FROM user
|
||||
JOIN partition ON user_id = user.id
|
||||
WHERE partition.uuid = ?
|
||||
""",
|
||||
(self.uuid,),
|
||||
).fetchone()
|
||||
|
||||
if user is None:
|
||||
raise LookupError
|
||||
|
||||
return User(user_id=user["id"])
|
||||
|
||||
def get_albums(self):
|
||||
db = get_db()
|
||||
return db.execute(
|
||||
"""
|
||||
SELECT * FROM album
|
||||
JOIN contient_partition ON album.id = album_id
|
||||
WHERE partition_uuid = ?
|
||||
""",
|
||||
(self.uuid,),
|
||||
).fetchall()
|
||||
|
||||
from .classes.user import User
|
||||
from .classes.album import Album
|
||||
from .classes.groupe import Groupe
|
||||
from .classes.partition import Partition
|
||||
|
||||
|
||||
def get_all_partitions():
|
||||
|
@ -4,6 +4,9 @@ DROP TABLE IF EXISTS album;
|
||||
DROP TABLE IF EXISTS contient_partition;
|
||||
DROP TABLE IF EXISTS contient_user;
|
||||
DROP TABLE IF EXISTS search_results;
|
||||
DROP TABLE IF EXISTS groupe;
|
||||
DROP TABLE IF EXISTS groupe_contient_user;
|
||||
DROP TABLE IF EXISTS groupe_contient_album;
|
||||
|
||||
CREATE TABLE user (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@ -43,4 +46,23 @@ CREATE TABLE search_results (
|
||||
uuid TEXT(36) PRIMARY KEY,
|
||||
url TEXT,
|
||||
creation_time TEXT NULL DEFAULT (datetime('now', 'localtime'))
|
||||
);
|
||||
|
||||
CREATE TABLE groupe (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
uuid TEXT(36) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE groupe_contient_user (
|
||||
groupe_id INTEGER NOT NULL,
|
||||
user_id INTEGER NOT NULL,
|
||||
is_admin INTEGER NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (groupe_id, user_id)
|
||||
);
|
||||
|
||||
CREATE TABLE groupe_contient_album (
|
||||
groupe_id INTEGER NOT NULL,
|
||||
album_id INTEGER NOT NULL,
|
||||
PRIMARY KEY (groupe_id, album_id)
|
||||
);
|
@ -1,4 +1,4 @@
|
||||
//* Add a listener to close pop-ups on Esc key pressed
|
||||
//* 1st fix: Add a listener to close pop-ups on Esc key pressed */
|
||||
document.addEventListener('keyup', function(e) {
|
||||
if (e.key == "Escape") {
|
||||
location.hash="!";
|
||||
@ -6,14 +6,45 @@ document.addEventListener('keyup', function(e) {
|
||||
});
|
||||
|
||||
|
||||
//* Save sidebar toggling preference to localStorage
|
||||
if (!("isSidebarToggled" in localStorage)) {
|
||||
localStorage["isSidebarToggled"] = window.innerWidth > 750; // Disable by default on mobile devices
|
||||
}
|
||||
document.getElementById("slide-sidebar").checked = !(JSON.parse(localStorage["isSidebarToggled"])); // localStorage cannot contain booleans
|
||||
|
||||
// Triggered on sidebar open/ close
|
||||
function updateSidebarToggle () {
|
||||
localStorage["isSidebarToggled"] = !(document.getElementById("slide-sidebar").checked);
|
||||
//* 2nd fix: Save sidebar toggling preference to localStorage */
|
||||
const sidebar_toggle = document.getElementById("slide-sidebar");
|
||||
|
||||
async function hideSidebarNoAnim () {
|
||||
const content_container = document.getElementById("content-container");
|
||||
const sidebar_indicator = sidebar_toggle.labels[0];
|
||||
|
||||
/* The transition needs to be invisible as if it was loaded that way */
|
||||
content_container.style.transitionDuration = "0s";
|
||||
sidebar_indicator.style.transitionDuration = "0s";
|
||||
|
||||
sidebar_toggle.checked = true;
|
||||
|
||||
/* We need to set a sleep because we want to reset the transition duration only once it ended*/
|
||||
await new Promise(r => setTimeout(r, 10));
|
||||
|
||||
content_container.style.transitionDuration = "";
|
||||
sidebar_indicator.style.transitionDuration = "";
|
||||
}
|
||||
document.getElementById("slide-sidebar").addEventListener("change", updateSidebarToggle, false);
|
||||
|
||||
|
||||
//* Save sidebar toggling preference to localStorage
|
||||
let isMobile = window.innerWidth <= 750;
|
||||
|
||||
if (!("isSidebarToggled" in localStorage)) {
|
||||
localStorage["isSidebarToggled"] = !isMobile; // Disable by default on mobile devices
|
||||
}
|
||||
|
||||
if (JSON.parse(localStorage["isSidebarToggled"]) && !isMobile) {
|
||||
sidebar_toggle.checked = false; // hidden sidebar
|
||||
} else if (!isMobile) {
|
||||
hideSidebarNoAnim(); // hide on desktop (no animation)
|
||||
} else {
|
||||
sidebar_toggle.checked = true; // hide on mobile (animation)
|
||||
}
|
||||
|
||||
//* Triggered localStorage save on open/ close
|
||||
function updateSidebarToggle () {
|
||||
localStorage["isSidebarToggled"] = !(sidebar_toggle.checked);
|
||||
}
|
||||
sidebar_toggle.addEventListener("change", updateSidebarToggle, false);
|
||||
|
@ -164,7 +164,7 @@ body {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.album-cover {
|
||||
.album-cover, .groupe-cover {
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
border-radius: 3px;
|
||||
@ -172,10 +172,21 @@ body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.album-cover:hover {
|
||||
.album-cover:hover, .groupe-album-cover:hover {
|
||||
background-color: var(--color-base);
|
||||
}
|
||||
|
||||
.groupe-cover {
|
||||
background-color: var(--color-crust);
|
||||
}
|
||||
|
||||
.groupe-albums-cover {
|
||||
background-color: var(--color-mantle);
|
||||
border-radius: 3px;
|
||||
margin: -1px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
|
||||
/** Sidebar toggle */
|
||||
#sidebar {
|
||||
@ -341,8 +352,19 @@ img.partition-thumbnail {
|
||||
}
|
||||
|
||||
|
||||
/** Albums grid in groupe view */
|
||||
#albums-grid > a > .album {
|
||||
padding: 10px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#albums-grid > a > .album:hover {
|
||||
background-color: var(--color-surface0);
|
||||
}
|
||||
|
||||
|
||||
/** Sidebar content */
|
||||
#new-album-button {
|
||||
.create-button {
|
||||
text-align: center;
|
||||
margin: 10px;
|
||||
background-color: var(--color-surface1);
|
||||
@ -352,18 +374,18 @@ img.partition-thumbnail {
|
||||
border: 2px solid var(--color-overlay0);
|
||||
}
|
||||
|
||||
#new-album-button:hover {
|
||||
.create-button:hover {
|
||||
border-color: var(--color-blue);
|
||||
background-color: var(--color-surface0);
|
||||
}
|
||||
|
||||
#albums {
|
||||
#sidebar-navigation {
|
||||
overflow: scroll;
|
||||
height: calc(100% - 375px); /* we don't want it hidden behind settings */
|
||||
height: calc(100% - 400px); /* we don't want it hidden behind settings */
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
#albums div {
|
||||
#albums div, #groupes div {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,11 @@
|
||||
|
||||
{% block content %}
|
||||
<header id="album-header">
|
||||
<h2 id="album-title">{{ album.name }}</h2>
|
||||
<h2 id="album-title">
|
||||
{% if groupe %}<a href="/groupe/{{ groupe.uuid }}">{{ groupe.name}}</a> /
|
||||
{% endif %}
|
||||
{{ album.name }}
|
||||
</h2>
|
||||
{% if g.user %}
|
||||
<div id="header-actions">
|
||||
<section id="users">
|
||||
|
@ -22,6 +22,11 @@
|
||||
{% for album in user.albums %}
|
||||
<option value="{{ album['uuid'] }}">{{ album["name"] }}</option>
|
||||
{% endfor %}
|
||||
{% for groupe in user.get_groupes() %}
|
||||
{% for album in groupe.get_albums() %}
|
||||
<option value="{{ album['uuid'] }}">{{ groupe.name }}/{{ album["name"] }}</option>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
<input type="hidden" value="{{ partition['uuid'] }}" name="partition-uuid">
|
||||
<input type="hidden" value="local_file" name="partition-type">
|
||||
|
@ -27,6 +27,14 @@
|
||||
</form>
|
||||
<a href="#!" class="close-dialog">Close</a>
|
||||
</dialog>
|
||||
<dialog id="create-groupe">
|
||||
<h2>Créer un nouveau groupe</h2>
|
||||
<form action="/groupe/create-groupe" method="post">
|
||||
<input type="text" name="name" id="name" placeholder="Nom" required><br/>
|
||||
<input type="submit" value="Créer">
|
||||
</form>
|
||||
<a href="#!" class="close-dialog">Close</a>
|
||||
</dialog>
|
||||
{% endif %}
|
||||
<div class="mask" id="!"></div>
|
||||
</div>
|
||||
@ -60,26 +68,65 @@
|
||||
<h2>Albums</h2>
|
||||
{% if g.user %}
|
||||
<a href="#create-album">
|
||||
<div id="new-album-button">
|
||||
<div class="create-button">
|
||||
Créer un album
|
||||
</div>
|
||||
</a>
|
||||
<a href="#create-groupe">
|
||||
<div class="create-button">
|
||||
Créer un groupe
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
<section id="albums">
|
||||
{% if not g.user %}
|
||||
<div style="text-align: center;"><i>Connectez vous pour avoir accès à vos albums</i></div>
|
||||
{% elif user.get_albums() | length == 0 %}
|
||||
|
||||
{% if g.user %}
|
||||
<section id="sidebar-navigation">
|
||||
<section id="groupes">
|
||||
{% if user.get_groupes() | length > 0 %}
|
||||
{% for groupe in user.groupes %}
|
||||
<div class="groupe-cover">
|
||||
<details>
|
||||
<summary>
|
||||
<a href="/groupe/{{ groupe.uuid }}">{{ groupe.name }}</a>
|
||||
</summary>
|
||||
<div class="groupe-albums-cover">
|
||||
{% if groupe.get_albums() | length == 0 %}
|
||||
Aucun album
|
||||
{% else %}
|
||||
{% for album in groupe.get_albums() %}
|
||||
<a href="/groupe/{{ groupe.uuid }}/{{ album["uuid"] }}">
|
||||
<div class="groupe-album-cover">
|
||||
{{ album["name"] }}
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
<section id="albums">
|
||||
{% if user.get_albums() | length == 0 %}
|
||||
<div style="text-align: center;"><i>Aucun album disponible</i></div>
|
||||
{% else %}
|
||||
{% else %}
|
||||
{% for album in user.albums %}
|
||||
<a href="/albums/{{ album['uuid'] }}">
|
||||
<div class="album-cover" id="album-1">
|
||||
<div class="album-cover">
|
||||
{{ album["name"] }}
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</section>
|
||||
</section>
|
||||
{% else %}
|
||||
<section id="sidebar-navigation">
|
||||
<div style="text-align: center;"><i>Connectez vous pour avoir accès à vos albums</i></div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
<div id="settings-container">
|
||||
{% if g.user %}
|
||||
|
71
partitioncloud/templates/groupe/index.html
Normal file
71
partitioncloud/templates/groupe/index.html
Normal file
@ -0,0 +1,71 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}{{ groupe.name }}{% endblock %}
|
||||
|
||||
|
||||
{% block dialogs %}
|
||||
<dialog id="create-groupe-album">
|
||||
<h2>Créer un nouvel album dans le groupe {{ groupe.name }}</h2>
|
||||
<form action="/groupe/{{ groupe.uuid }}/create-album" method="post">
|
||||
<input type="text" name="name" id="name" placeholder="Nom" required><br/>
|
||||
<input type="submit" value="Ajouter">
|
||||
</form>
|
||||
<a href="#!" class="close-dialog">Close</a>
|
||||
</dialog>
|
||||
<dialog id="delete">
|
||||
<h2>Supprimer le groupe</h2>
|
||||
Êtes vous sûr de vouloir supprimer ce groupe ? Cela supprimera les albums
|
||||
sous-jacents et leurs partitions si personne ne les a rejoints (indépendamment du groupe).
|
||||
<br/><br/>
|
||||
<form method="post" action="/groupe/{{ groupe.uuid }}/delete">
|
||||
<input type="submit" style="background-color: var(--color-red);" value="Supprimer">
|
||||
</form>
|
||||
<a href="#!" class="close-dialog">Close</a>
|
||||
</dialog>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<header id="album-header">
|
||||
<h2 id="groupe-title">{{ groupe.name }}</h2>
|
||||
{% if g.user %}
|
||||
<div id="header-actions">
|
||||
<section id="users">
|
||||
{% for groupe_user in groupe.users %}
|
||||
<div class="user-profile-picture" style="background-color:{{ groupe_user.color }};" title="{{ groupe_user.username }}">
|
||||
{{ groupe_user.username[0] | upper }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</section>
|
||||
<div class="dropdown dp1">
|
||||
+
|
||||
<div class="dropdown-content dp1">
|
||||
{% if not_participant %}
|
||||
<a href="/groupe/{{ groupe.uuid }}/join">Rejoindre</a>
|
||||
{% elif groupe.users | length > 1 %}
|
||||
<a href="/groupe/{{ groupe.uuid }}/quit">Quitter</a>
|
||||
{% endif %}
|
||||
{% if g.user.access_level == 1 or user.id in groupe.get_admins() %}
|
||||
<a href="#create-groupe-album">Ajouter un album</a>
|
||||
<a id="delete-album" href="#delete">Supprimer</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</header>
|
||||
<hr/>
|
||||
{% if groupe.albums|length != 0 %}
|
||||
<section id="albums-grid">
|
||||
{% for album in groupe.albums | reverse %}
|
||||
<a href="/groupe/{{ groupe.uuid }}/{{ album.uuid }}">
|
||||
<div class="album">
|
||||
{{ album.name }}
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</section>
|
||||
{% else %}
|
||||
<br/>
|
||||
<div id="albums-grid" style="display: inline;">Aucun album disponible. <a href="#create-groupe-album">En créer un</a></div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
@ -1,3 +1,2 @@
|
||||
flask
|
||||
urllib
|
||||
google
|
Loading…
Reference in New Issue
Block a user