Skip to content

Commit a80d552

Browse files
Merge pull request #122 from Nathan-Etave/feat/utilisateur
Fusion de la page d'accueil et de recherche
2 parents 7cf7217 + fe5e479 commit a80d552

File tree

9 files changed

+514
-98
lines changed

9 files changed

+514
-98
lines changed

app/forms/edit_profil_form.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ class Edit_profil_form(FlaskForm) :
77
last_name = StringField("Nom", validators=[DataRequired()])
88
first_name = StringField("Prénom", validators=[DataRequired()])
99
email = EmailField("Email", validators=[DataRequired(), Email()])
10-
telephone = StringField("Téléphone", validators=[DataRequired()])
10+
telephone = StringField("Téléphone")
1111
password = PasswordField("Mot de passe", validators=[DataRequired()])
1212
submit = SubmitField("Modifier")

app/home/routes.py

Lines changed: 109 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
from app.home import bp
22
from flask_login import login_required, current_user
3-
from flask import render_template, jsonify, redirect, url_for
3+
from flask import render_template, jsonify, redirect, url_for, request, current_app
44
from app.extensions import db
55
from app.models.favoris import FAVORIS
66
from app.models.fichier import FICHIER
77
from app.models.a_recherche import A_RECHERCHE
88
from app.forms.search_form import SearchForm
99
from datetime import datetime
1010
from app.utils import check_notitications
11+
from app.models.dossier import DOSSIER
12+
from app.utils import Whoosh
13+
from app import socketio
14+
from fasteners import InterProcessLock
1115

1216

1317
@bp.route("/", methods=["GET", "POST"])
@@ -25,28 +29,57 @@ def home():
2529
Returns:
2630
The rendered home page template.
2731
"""
28-
favorite_files = get_files_favoris(current_user.id_Utilisateur)
29-
researches = get_user_researches(current_user.id_Utilisateur)
32+
form = SearchForm()
33+
34+
query = ""
35+
whoosh = Whoosh()
3036
form = SearchForm()
3137
if form.validate_on_submit():
3238
add_research(current_user.id_Utilisateur, form.search.data)
33-
return redirect(url_for("search.search", query=form.search.data))
39+
query = form.search.data
40+
results = whoosh.search(query)
41+
results = create_rendered_list(results)
42+
favorite_files = get_files_favoris(current_user.id_Utilisateur)
43+
researches = get_user_researches(current_user.id_Utilisateur)
3444
return render_template(
3545
"home/index.html",
3646
is_authenticated=True,
3747
is_admin=current_user.is_admin(),
3848
has_notifications=check_notitications(),
3949
favorite_files=favorite_files,
4050
researches=researches,
51+
folders=results,
52+
query=query,
4153
form=form,
4254
)
4355

4456

45-
@bp.route("/favori/<int:id_file>", methods=["DELETE"])
57+
@bp.route("/favori/<int:id_file>", methods=["POST", "DELETE"])
4658
@login_required
47-
def unfavorize(id_file):
48-
unfavorite_file(id_file, current_user.get_id())
49-
return jsonify({"status": "ok"})
59+
def favorize(id_file):
60+
"""
61+
Favorize or unfavorize a file for the current user.
62+
63+
Args:
64+
id_file (int): The ID of the file to favorize or unfavorize.
65+
66+
Returns:
67+
dict: A JSON response indicating the status of the operation.
68+
The response will have a 'status' key with the value 'ok'.
69+
"""
70+
if request.method == "POST":
71+
db.session.execute(
72+
FAVORIS.insert().values(
73+
id_Fichier=id_file, id_Utilisateur=current_user.id_Utilisateur
74+
)
75+
)
76+
else:
77+
db.session.query(FAVORIS).filter(
78+
FAVORIS.c.id_Fichier == id_file,
79+
FAVORIS.c.id_Utilisateur == current_user.id_Utilisateur,
80+
).delete()
81+
db.session.commit()
82+
return jsonify({"file": id_file}), 200
5083

5184

5285
def get_files_favoris(user_id):
@@ -111,16 +144,76 @@ def add_research(user_id, search):
111144
db.session.commit()
112145
db.session.commit()
113146

147+
#--------------------------------------------------------------------------
114148

115-
def unfavorite_file(file_id, user_id):
149+
def create_folder_dict(folder, files):
116150
"""
117-
Remove a file from the favorites of a user.
151+
Create a dictionary representation of a folder.
118152
119153
Args:
120-
file_id (int): The ID of the file.
121-
user_id (int): The ID of the user.
154+
folder (Folder): The folder object.
155+
files (list): A list of file objects.
156+
157+
Returns:
158+
dict: A dictionary representation of the folder, including its name, files, color, id, and subfolders.
122159
"""
123-
db.session.query(FAVORIS).filter(
124-
FAVORIS.c.id_Fichier == file_id, FAVORIS.c.id_Utilisateur == user_id
125-
).delete()
126-
db.session.commit()
160+
files_in_folder = [
161+
result for result in files if result["path"] == (str(folder.id_Dossier))
162+
]
163+
subfolders = recursive_subfolder(folder, files)
164+
return {
165+
"name": folder.nom_Dossier,
166+
"files": files_in_folder,
167+
"color": folder.couleur_Dossier,
168+
"id": folder.id_Dossier,
169+
"subfolder": subfolders
170+
}
171+
172+
def create_rendered_list(results):
173+
"""
174+
Create a rendered list of folders and their associated results.
175+
176+
Args:
177+
results (list): A list of results.
178+
179+
Returns:
180+
list: A list of dictionaries representing folders and their associated results.
181+
"""
182+
folders = db.session.query(DOSSIER).order_by(DOSSIER.priorite_Dossier).all()
183+
folders_root = [folder for folder in folders if folder.DOSSIER == [] and is_accessible(folder)]
184+
return [create_folder_dict(folder, results) for folder in folders_root]
185+
186+
187+
def recursive_subfolder(folder, files):
188+
"""
189+
Recursively searches for subfolders in the given folder and creates a list of dictionaries
190+
containing information about each subfolder.
191+
192+
Args:
193+
folder (str): The path of the folder to search for subfolders.
194+
files (list): A list of files to include in the dictionaries.
195+
196+
Returns:
197+
list: A list of dictionaries containing information about each subfolder.
198+
"""
199+
return [create_folder_dict(subfolder, files) for subfolder in folder.DOSSIER_ if is_accessible(subfolder)]
200+
201+
def is_accessible(folder):
202+
"""
203+
Check if the current user has access to the given folder.
204+
205+
Args:
206+
folder (Folder): The folder to check.
207+
208+
Returns:
209+
bool: True if the user has access to the folder, False otherwise.
210+
"""
211+
return any(current_user.id_Role == role.id_Role for role in folder.ROLE)
212+
213+
@socketio.on('search_files', namespace='/home')
214+
def search_files(data):
215+
search_query = data.get("query")
216+
with InterProcessLock(f"{current_app.root_path}/whoosh.lock"):
217+
search_results = Whoosh().search(search_query, path=f'{data.get("folderId")}')
218+
search_results = [result["id"] for result in search_results]
219+
socketio.emit("search_results", {'query': search_query, 'results': search_results, 'folderId': data.get("folderId")}, namespace="/home")

app/profil/routes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from flask_bcrypt import check_password_hash, generate_password_hash
99
from app.models.utilisateur import UTILISATEUR
1010
from app.utils import check_notitications
11+
from app.models.role import ROLE
1112

1213

1314
@bp.route("/", methods=["GET", "POST"])
@@ -24,6 +25,7 @@ def profil():
2425
is_admin=current_user.is_admin(),
2526
has_notifications=check_notitications(),
2627
user=current_user,
28+
user_role= db.session.query(ROLE.nom_Role).filter(ROLE.id_Role == current_user.id_Role).first()[0],
2729
edit_mode=False,
2830
)
2931

app/search/routes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def search():
2020
Returns:
2121
A rendered template with the search results, query, and search form.
2222
"""
23-
query = request.args.get("query")
23+
query = request.args.get("q")
2424
whoosh = Whoosh()
2525
results = whoosh.search(query)
2626
results = create_rendered_list(results)
@@ -76,7 +76,7 @@ def create_folder_dict(folder, files):
7676
dict: A dictionary representation of the folder, including its name, files, color, id, and subfolders.
7777
"""
7878
files_in_folder = [
79-
result for result in files if result["path"].startswith(str(folder.id_Dossier))
79+
result for result in files if result["path"] == (str(folder.id_Dossier))
8080
]
8181
subfolders = recursive_subfolder(folder, files)
8282
return {

app/static/js/desktop.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ document.addEventListener('DOMContentLoaded', function () {
1212
const socket = io.connect('/file_handler');
1313
socket.emit('get_files_details', { 'files': deskList });
1414

15-
let currentFile = 1;
15+
let currentFile = 0;
1616
let desktop = document.getElementById('desk-section');
1717

1818
socket.on('files_details', function (data) {
@@ -35,7 +35,7 @@ document.addEventListener('DOMContentLoaded', function () {
3535
card.style.border = '3px solid #004F8A';
3636

3737
let fileDiv = document.createElement('div');
38-
fileDiv.className = 'card-body file-' + deskFileNumber;
38+
fileDiv.className = 'card-body d-flex flex-column file-' + deskFileNumber;
3939
fileDiv.setAttribute('data-file', file.id_Fichier);
4040
fileDiv.setAttribute('data-folder', file.id_Dossier);
4141
fileDiv.setAttribute('data-type', file.extension_Fichier);
@@ -47,18 +47,23 @@ document.addEventListener('DOMContentLoaded', function () {
4747
<div>
4848
<p class="card-title h5" style="font-size: 1.5em; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;">${file.nom_Fichier}<p>
4949
</div>
50-
<div class="desktop-element">
50+
<div class="desktop-element mt-auto d-flex justify-content-center">
5151
<a href="#" id="${ file.id_Fichier }" class="favori" is-fav="${ file.is_favorite }" onclick="event.stopPropagation();">
5252
<i class="fa-solid fa-star fa-lg me-2" style="color: #FFD43B;"
5353
id="fav-${ file.id_Fichier }"></i>
5454
</a>
5555
<a href="#" id="${ file.id_Fichier }" class="desktop-btn" onclick="event.stopPropagation();">
56-
<i class="fa-regular fa-square-minus fa-lg" id="desk-${ file.id_Fichier }"></i>
56+
<i class="fa-regular fa-square-minus fa-lg me-2" id="desk-${ file.id_Fichier }"></i>
57+
</a>
58+
<a href="/dossier/${ file.id_Dossier }/fichier/${ file.id_Fichier }?as_attachment=true"
59+
style="display: inherit;">
60+
<i class="fa fa-download mt-1" aria-hidden="true" style="cursor: pointer;"
61+
data-file="${ file.id_Fichier }" data-folder="${ file.id_Dossier }"></i>
5762
</a>
5863
</div>`;
5964

6065
fileDiv.addEventListener('click', function () {
61-
let fileNumber = parseInt(fileDiv.className.split(' ')[1].split('-')[1], 10);
66+
let fileNumber = parseInt(fileDiv.className.split('-')[4]);
6267
let nav = document.querySelector('.nav-' + fileNumber);
6368
nav.classList.add('active');
6469
currentFile = fileNumber;
@@ -177,9 +182,9 @@ document.addEventListener('DOMContentLoaded', function () {
177182

178183
window.addEventListener('keydown', function (event) {
179184
let nbFiles = document.querySelectorAll('#file').length;
180-
let nav = document.querySelector('.nav-' + currentFile);
181-
nav.classList.remove('active');
182185
if (currentFile !== 0) {
186+
let nav = document.querySelector('.nav-' + currentFile);
187+
nav.classList.remove('active');
183188
if (event.key === 'ArrowRight') {
184189
currentFile++;
185190
if (currentFile > nbFiles) {

0 commit comments

Comments
 (0)