Revert french translations but keep bug fixes

This commit is contained in:
simon987 2019-03-10 14:52:46 -04:00
parent f76c935c49
commit 2092239dc1
17 changed files with 183 additions and 224 deletions

View File

@ -1,6 +1,7 @@
# Simple incremental search tool # Simple incremental search tool
Work in progress! Shouldn't be used in production environnments.
Portable search tool for local files using Elasticsearch.
### Features ### Features
* Incremental search (Search as you type) * Incremental search (Search as you type)
@ -22,30 +23,14 @@ Work in progress! Shouldn't be used in production environnments.
Java and python3 are required. Java and python3 are required.
Once the web server is running, you can connect to the search interface by typing `localhost:8080` in your browser. Once the web server is running, you can connect to the search interface by typing `localhost:8080` in your browser.
## Setup on Windows ## Setup on Windows/Mac/linux (Python 3.5+)
* Download and install [Elasticsearch](https://www.elastic.co/downloads/elasticsearch)
```bash ```bash
git clone https://github.com/simon987/Simple-Incremental-Search-Tool git clone https://github.com/simon987/Simple-Incremental-Search-Tool
cd Projet-Web-2018
```
[Download latest elasticsearch version](https://www.elastic.co/downloads/elasticsearch) and extract to `Simple-Incremental-Search-Tool\elasticsearch`
```bash
sudo pip3 install -r requirements.txt
python3 run.py
```
## Setup on Mac/linux
```bash
git clone https://github.com/simon987/Simple-Incremental-Search-Tool
cd Projet-Web-2018
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.2.4.zip
unzip elasticsearch-6.2.4.zip
rm elasticsearch-6.2.4.zip
mv elasticsearch-6.2.4 elasticsearch
sudo pip3 install -r requirements.txt sudo pip3 install -r requirements.txt
python3 run.py python3 run.py
``` ```

View File

@ -144,9 +144,9 @@ class TaskManager:
TextFileParser(chksum_calcs, int(directory.get_option("TextFileContentLength")), directory.path), TextFileParser(chksum_calcs, int(directory.get_option("TextFileContentLength")), directory.path),
PictureFileParser(chksum_calcs, directory.path), PictureFileParser(chksum_calcs, directory.path),
FontParser(chksum_calcs, directory.path), FontParser(chksum_calcs, directory.path),
PdfFileParser(chksum_calcs, int(directory.get_option("TextFileContentLength")), directory.path), # todo get content len from other opt PdfFileParser(chksum_calcs, int(directory.get_option("PdfFileContentLength")), directory.path),
DocxParser(chksum_calcs, int(directory.get_option("TextFileContentLength")), directory.path), # todo get content len from other opt DocxParser(chksum_calcs, int(directory.get_option("SpreadsheetContentLength")), directory.path),
EbookParser(chksum_calcs, int(directory.get_option("TextFileContentLength")), directory.path)], # todo get content len from other opt EbookParser(chksum_calcs, int(directory.get_option("EbookContentLength")), directory.path)],
mime_guesser, self.indexer, directory.id) mime_guesser, self.indexer, directory.id)
c.crawl(directory.path, counter) c.crawl(directory.path, counter)

View File

@ -1,10 +1,9 @@
import json import json
import elasticsearch import elasticsearch
from threading import Thread
import subprocess
import requests import requests
import config import config
import platform
class Indexer: class Indexer:
@ -14,30 +13,12 @@ class Indexer:
self.index_name = index self.index_name = index
self.es = elasticsearch.Elasticsearch() self.es = elasticsearch.Elasticsearch()
try: requests.head("http://localhost:9200")
requests.head("http://localhost:9200") if self.es.indices.exists(self.index_name):
print("Index is already setup")
except requests.exceptions.ConnectionError:
import time
t = Thread(target=Indexer.run_elasticsearch)
t.daemon = True
t.start()
time.sleep(25)
if self.es.indices.exists(self.index_name):
print("Index is already setup")
else:
print("First time setup...")
self.init()
@staticmethod
def run_elasticsearch():
if platform.system() == "Windows":
subprocess.Popen(["elasticsearch\\bin\\elasticsearch.bat"])
else: else:
subprocess.Popen(["elasticsearch/bin/elasticsearch"]) print("First time setup...")
self.init()
@staticmethod @staticmethod
def create_bulk_index_string(docs: list, directory: int): def create_bulk_index_string(docs: list, directory: int):

View File

@ -272,7 +272,7 @@ class TextFileParser(GenericFileParser):
"text/x-bibtex", "text/x-tcl", "text/x-c++", "text/x-shellscript", "text/x-msdos-batch", "text/x-bibtex", "text/x-tcl", "text/x-c++", "text/x-shellscript", "text/x-msdos-batch",
"text/x-makefile", "text/rtf", "text/x-objective-c", "text/troff", "text/x-m4", "text/x-makefile", "text/rtf", "text/x-objective-c", "text/troff", "text/x-m4",
"text/x-lisp", "text/x-php", "text/x-gawk", "text/x-awk", "text/x-ruby", "text/x-po", "text/x-lisp", "text/x-php", "text/x-gawk", "text/x-awk", "text/x-ruby", "text/x-po",
"text/x-makefile", "application/javascript", "application/rtf" "text/x-makefile", "application/javascript", "application/rtf", "application/json",
] ]
def parse(self, full_path: str): def parse(self, full_path: str):

122
run.py
View File

@ -1,17 +1,18 @@
from flask import Flask, render_template, request, redirect, flash, session, abort, send_file
from storage import Directory, Option, Task, User
from storage import LocalStorage, DuplicateDirectoryException, DuplicateUserException
from crawler import RunningTask, TaskManager
import json import json
import os import os
import shutil import shutil
import bcrypt
import config
import humanfriendly
from search import Search
from PIL import Image
from io import BytesIO from io import BytesIO
import bcrypt
import humanfriendly
from PIL import Image
from flask import Flask, render_template, request, redirect, flash, session, abort, send_file
import config
from crawler import TaskManager
from search import Search
from storage import Directory, Option, Task, User
from storage import LocalStorage, DuplicateDirectoryException, DuplicateUserException
app = Flask(__name__) app = Flask(__name__)
app.secret_key = "A very secret key" app.secret_key = "A very secret key"
@ -22,12 +23,10 @@ search = Search("changeme")
def get_dir_size(path): def get_dir_size(path):
size = 0 size = 0
for root, dirs, files in os.walk(path): for root, dirs, files in os.walk(path):
for filename in files: for filename in files:
full_path = os.path.join(root, filename) full_path = os.path.join(root, filename)
size += os.path.getsize(full_path) size += os.path.getsize(full_path)
@ -36,18 +35,18 @@ def get_dir_size(path):
@app.route("/user/<user>") @app.route("/user/<user>")
def user_manage(user): def user_manage(user):
if "admin" in session and session["admin"]: if "admin" in session and session["admin"]:
return render_template("user_manage.html", directories=storage.dirs(), user=storage.users()[user]) return render_template("user_manage.html", directories=storage.dirs(), user=storage.users()[user])
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@app.route("/logout") @app.route("/logout")
def logout(): def logout():
session.pop("username") session.pop("username")
session.pop("admin") session.pop("admin")
flash("Déconnection réussie", "success") flash("Successfully logged out", "success")
return redirect("/") return redirect("/")
@ -60,16 +59,15 @@ def login():
session["username"] = username session["username"] = username
session["admin"] = storage.users()[username].admin session["admin"] = storage.users()[username].admin
flash("Connexion réussie", "success") flash("Successfully logged in", "success")
else: else:
flash("Nom d'utilisateur ou mot de passe invalide", "danger") flash("Invalid username or password", "danger")
return redirect("/") return redirect("/")
@app.route("/user") @app.route("/user")
def user_page(): def user_page():
admin_account_present = False admin_account_present = False
for user in storage.users(): for user in storage.users():
@ -80,13 +78,12 @@ def user_page():
if not admin_account_present or ("admin" in session and session["admin"]): if not admin_account_present or ("admin" in session and session["admin"]):
return render_template("user.html", users=storage.users(), admin_account_present=admin_account_present) return render_template("user.html", users=storage.users(), admin_account_present=admin_account_present)
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@app.route("/user/<username>/set_access") @app.route("/user/<username>/set_access")
def user_set_access(username): def user_set_access(username):
if "admin" in session and session["admin"]: if "admin" in session and session["admin"]:
dir_id = request.args["dir_id"] dir_id = request.args["dir_id"]
user = storage.users()[username] user = storage.users()[username]
@ -102,31 +99,29 @@ def user_set_access(username):
flash("Permissions mises à jour", "success") flash("Permissions mises à jour", "success")
return redirect("/user/" + username) return redirect("/user/" + username)
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@app.route("/user/<username>/set_admin") @app.route("/user/<username>/set_admin")
def user_set_admin(username): def user_set_admin(username):
if "admin" in session and session["admin"]: if "admin" in session and session["admin"]:
user = storage.users()[username] user = storage.users()[username]
if user.username == session["username"]: if user.username == session["username"]:
flash("Vous n'êtes pas autorisé à changer votre propre type de compte", "warning") flash("You cannot modifiy your own account", "warning")
else: else:
user.admin = request.args["admin"] == "1" user.admin = request.args["admin"] == "1"
storage.update_user(user) storage.update_user(user)
flash("Permissions mises à jour", "success") flash("Permissions updated", "success")
return redirect("/user/" + username) return redirect("/user/" + username)
@app.route("/user/add", methods=['POST']) @app.route("/user/add", methods=['POST'])
def user_add(): def user_add():
admin_account_present = False admin_account_present = False
for user in storage.users(): for user in storage.users():
@ -141,41 +136,40 @@ def user_add():
try: try:
storage.save_user(User(username, password, is_admin)) storage.save_user(User(username, password, is_admin))
flash("Nouvel utilisateur créé", "success") flash("Created new user", "success")
except DuplicateUserException: except DuplicateUserException:
flash("<strong>L'utilisateur n'as pas pu être créé</strong> Assurez vous que le nom d'utilisateur est unique", "danger") flash("<strong>Couldn't create user</strong> "
"Make sure that the username is unique", "danger")
return redirect("/user") return redirect("/user")
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@app.route("/user/<username>/del") @app.route("/user/<username>/del")
def user_del(username): def user_del(username):
if "admin" in session and session["admin"]: if "admin" in session and session["admin"]:
if session["username"] == username: if session["username"] == username:
flash("Vous ne pouvez pas supprimer votre propre compte", "warning") flash("You cannot delete your own account", "warning")
return redirect("/user/" + username) return redirect("/user/" + username)
else: else:
storage.remove_user(username) storage.remove_user(username)
flash("Utilisateur supprimé", "success") flash("User deleted", "success")
return redirect("/user") return redirect("/user")
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@app.route("/suggest") @app.route("/suggest")
def suggest(): def suggest():
return json.dumps(search.suggest(request.args.get("prefix"))) return json.dumps(search.suggest(request.args.get("prefix")))
@app.route("/document/<doc_id>") @app.route("/document/<doc_id>")
def document(doc_id): def document(doc_id):
doc = search.get_doc(doc_id)["_source"] doc = search.get_doc(doc_id)["_source"]
directory = storage.dirs()[doc["directory"]] directory = storage.dirs()[doc["directory"]]
@ -186,7 +180,6 @@ def document(doc_id):
@app.route("/dl/<doc_id>") @app.route("/dl/<doc_id>")
def file(doc_id): def file(doc_id):
doc = search.get_doc(doc_id)["_source"] doc = search.get_doc(doc_id)["_source"]
directory = storage.dirs()[doc["directory"]] directory = storage.dirs()[doc["directory"]]
@ -201,7 +194,6 @@ def file(doc_id):
@app.route("/file/<doc_id>") @app.route("/file/<doc_id>")
def download(doc_id): def download(doc_id):
doc = search.get_doc(doc_id)["_source"] doc = search.get_doc(doc_id)["_source"]
directory = storage.dirs()[doc["directory"]] directory = storage.dirs()[doc["directory"]]
extension = "" if doc["extension"] is None or doc["extension"] == "" else "." + doc["extension"] extension = "" if doc["extension"] is None or doc["extension"] == "" else "." + doc["extension"]
@ -215,7 +207,6 @@ def download(doc_id):
@app.route("/thumb/<doc_id>") @app.route("/thumb/<doc_id>")
def thumb(doc_id): def thumb(doc_id):
doc = search.get_doc(doc_id) doc = search.get_doc(doc_id)
if doc is not None: if doc is not None:
@ -239,9 +230,8 @@ def thumb(doc_id):
@app.route("/") @app.route("/")
def search_page(): def search_page():
mime_map = search.get_mime_map() mime_map = search.get_mime_map()
mime_map.append({"id": "any", "text": "Tous"}) mime_map.append({"id": "any", "text": "All"})
directories = [storage.dirs()[x] for x in get_allowed_dirs(session["username"] if "username" in session else None)] directories = [storage.dirs()[x] for x in get_allowed_dirs(session["username"] if "username" in session else None)]
@ -256,7 +246,6 @@ def search_liste_page():
def get_allowed_dirs(username): def get_allowed_dirs(username):
if config.allow_guests: if config.allow_guests:
return [x for x in storage.dirs() if x.enabled] return [x for x in storage.dirs() if x.enabled]
else: else:
@ -269,7 +258,6 @@ def get_allowed_dirs(username):
@app.route("/search", methods=['POST']) @app.route("/search", methods=['POST'])
def search_route(): def search_route():
query = request.json["q"] query = request.json["q"]
query = "" if query is None else query query = "" if query is None else query
@ -292,7 +280,6 @@ def search_route():
@app.route("/scroll") @app.route("/scroll")
def scroll_route(): def scroll_route():
scroll_id = request.args.get("scroll_id") scroll_id = request.args.get("scroll_id")
page = search.scroll(scroll_id) page = search.scroll(scroll_id)
@ -302,17 +289,15 @@ def scroll_route():
@app.route("/directory") @app.route("/directory")
def dir_list(): def dir_list():
if "admin" in session and session["admin"]: if "admin" in session and session["admin"]:
return render_template("directory.html", directories=storage.dirs()) return render_template("directory.html", directories=storage.dirs())
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@app.route("/directory/add") @app.route("/directory/add")
def directory_add(): def directory_add():
if "admin" in session and session["admin"]: if "admin" in session and session["admin"]:
path = request.args.get("path") path = request.args.get("path")
name = request.args.get("name") name = request.args.get("name")
@ -323,19 +308,19 @@ def directory_add():
try: try:
d.set_default_options() d.set_default_options()
storage.save_directory(d) storage.save_directory(d)
flash("<strong>Dossier créé</strong>", "success") flash("<strong>Directory created</strong>", "success")
except DuplicateDirectoryException: except DuplicateDirectoryException:
flash("<strong>Le dossier n'a pas pu être créé</strong> Assurer vous de choisir un nom unique", "danger") flash("<strong>The directory couldn't be created</strong> Make sure to chose a unique name",
"danger")
return redirect("/directory") return redirect("/directory")
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@app.route("/directory/<int:dir_id>") @app.route("/directory/<int:dir_id>")
def directory_manage(dir_id): def directory_manage(dir_id):
if "admin" in session and session["admin"]: if "admin" in session and session["admin"]:
directory = storage.dirs()[dir_id] directory = storage.dirs()[dir_id]
tn_size = get_dir_size("static/thumbnails/" + str(dir_id)) tn_size = get_dir_size("static/thumbnails/" + str(dir_id))
@ -344,13 +329,12 @@ def directory_manage(dir_id):
return render_template("directory_manage.html", directory=directory, tn_size=tn_size, return render_template("directory_manage.html", directory=directory, tn_size=tn_size,
tn_size_formatted=tn_size_formatted) tn_size_formatted=tn_size_formatted)
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@app.route("/directory/<int:dir_id>/update") @app.route("/directory/<int:dir_id>/update")
def directory_update(dir_id): def directory_update(dir_id):
if "admin" in session and session["admin"]: if "admin" in session and session["admin"]:
directory = storage.dirs()[dir_id] directory = storage.dirs()[dir_id]
@ -369,20 +353,20 @@ def directory_update(dir_id):
try: try:
storage.update_directory(updated_dir) storage.update_directory(updated_dir)
flash("<strong>Dossier mis à jour</strong>", "success") flash("<strong>Updated directory</strong>", "success")
except DuplicateDirectoryException: except DuplicateDirectoryException:
flash("<strong>Le dossier n'a pas pu être mis à jour</strong> Assurez vous que le chemin est unique", "danger") flash("<strong>The directory couldn't be updated</strong> Make the that the path is unique",
"danger")
return redirect("/directory/" + str(dir_id)) return redirect("/directory/" + str(dir_id))
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@app.route("/directory/<int:dir_id>/update_opt") @app.route("/directory/<int:dir_id>/update_opt")
def directory_update_opt(dir_id): def directory_update_opt(dir_id):
if "admin" in session and session["admin"]: if "admin" in session and session["admin"]:
opt_id = request.args.get("id") opt_id = request.args.get("id")
opt_key = request.args.get("key") opt_key = request.args.get("key")
@ -392,7 +376,7 @@ def directory_update_opt(dir_id):
return redirect("/directory/" + str(dir_id)) return redirect("/directory/" + str(dir_id))
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@ -404,17 +388,16 @@ def directory_del(dir_id):
shutil.rmtree("static/thumbnails/" + str(dir_id)) shutil.rmtree("static/thumbnails/" + str(dir_id))
storage.remove_directory(dir_id) storage.remove_directory(dir_id)
flash("<strong>Dossier supprimé</strong>", "success") flash("<strong>Deleted folder</strong>", "success")
return redirect("/directory") return redirect("/directory")
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@app.route("/directory/<int:dir_id>/reset") @app.route("/directory/<int:dir_id>/reset")
def directory_reset(dir_id): def directory_reset(dir_id):
if "admin" in session and session["admin"]: if "admin" in session and session["admin"]:
directory = storage.dirs()[dir_id] directory = storage.dirs()[dir_id]
@ -431,10 +414,10 @@ def directory_reset(dir_id):
search.delete_directory(dir_id) search.delete_directory(dir_id)
flash("<strong>Options du dossier réinitialisés</strong>", "success") flash("<strong>Reset directory options</strong>", "success")
return redirect("directory/" + str(dir_id)) return redirect("directory/" + str(dir_id))
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@ -444,7 +427,7 @@ def task():
return render_template("task.html", tasks=storage.tasks(), directories=storage.dirs(), return render_template("task.html", tasks=storage.tasks(), directories=storage.dirs(),
task_list=json.dumps(list(storage.tasks().keys()))) task_list=json.dumps(list(storage.tasks().keys())))
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@ -457,7 +440,7 @@ def get_current_task():
else: else:
return "" return ""
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@ -468,17 +451,17 @@ def task_add():
directory = request.args.get("directory") directory = request.args.get("directory")
if task_type not in ("1", "2"): if task_type not in ("1", "2"):
flash("Vous devez choisir un type de tâche", "danger") flash("Please choose a task type", "danger")
return redirect("/task") return redirect("/task")
if directory.isdigit() and int(directory) in storage.dirs(): if directory.isdigit() and int(directory) in storage.dirs():
storage.save_task(Task(task_type, directory)) storage.save_task(Task(task_type, directory))
else: else:
flash("Vous devez choisir un dossier", "danger") flash("You must choose a directory", "danger")
return redirect("/task") return redirect("/task")
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@ -492,14 +475,15 @@ def task_del(task_id):
return redirect("/task") return redirect("/task")
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@app.route("/reset_es") @app.route("/reset_es")
def reset_es(): def reset_es():
if "admin" in session and session["admin"]: if "admin" in session and session["admin"]:
flash("Elasticsearch a été réinitialisé, les changements dans <strong>config.py</strong> ont été appliqués", "success") flash("Elasticsearch index has been reset. Modifications made in <b>config.py</b> have been applied.",
"success")
tm.indexer.init() tm.indexer.init()
if os.path.exists("static/thumbnails"): if os.path.exists("static/thumbnails"):
@ -507,7 +491,7 @@ def reset_es():
return redirect("/dashboard") return redirect("/dashboard")
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")
@ -534,7 +518,7 @@ def dashboard():
index_size=humanfriendly.format_size(search.get_index_size())) index_size=humanfriendly.format_size(search.get_index_size()))
else: else:
flash("Vous n'êtes pas autorisé à accéder à cette page", "warning") flash("You are not authorized to access this page", "warning")
return redirect("/") return redirect("/")

View File

@ -73,7 +73,7 @@ function makeStatsCard(searchResult) {
statsCardBody.setAttribute("class", "card-body"); statsCardBody.setAttribute("class", "card-body");
let stat = document.createElement("p"); let stat = document.createElement("p");
stat.appendChild(document.createTextNode(searchResult["hits"]["total"] + " résultats en " + searchResult["took"] + "ms")); stat.appendChild(document.createTextNode(searchResult["hits"]["total"] + " results in " + searchResult["took"] + "ms"));
let sizeStat = document.createElement("span"); let sizeStat = document.createElement("span");
sizeStat.appendChild(document.createTextNode(humanFileSize(searchResult["aggregations"]["total_size"]["value"]))); sizeStat.appendChild(document.createTextNode(humanFileSize(searchResult["aggregations"]["total_size"]["value"])));
@ -267,7 +267,7 @@ function createDocCard(hit) {
} }
thumbnailOverlay.appendChild(resolutionBadge); thumbnailOverlay.appendChild(resolutionBadge);
var format = hit["_source"]["format_name"]; var format = hit["_source"]["format"];
//Hover //Hover
if(format === "GIF") { if(format === "GIF") {

View File

@ -7,6 +7,9 @@ import config
class CheckSumCalculator: class CheckSumCalculator:
def __init__(self):
pass
def checksum(self, string: str): def checksum(self, string: str):
return flask_bcrypt.generate_password_hash(string, config.bcrypt_rounds) return flask_bcrypt.generate_password_hash(string, config.bcrypt_rounds)

View File

@ -5,7 +5,7 @@
<div class="container"> <div class="container">
<div class="card"> <div class="card">
<div class="card-header">Information globale</div> <div class="card-header">Global information</div>
<div class="card-body"> <div class="card-body">
<table class="info-table table-hover table-striped"> <table class="info-table table-hover table-striped">
<tbody> <tbody>
@ -14,45 +14,45 @@
<td><pre>{{ version }}</pre></td> <td><pre>{{ version }}</pre></td>
</tr> </tr>
<tr> <tr>
<th>Taille totale des miniatures</th> <th>Total thumbnail cache size</th>
<td><pre>{{ tn_size_total }}</pre></td> <td><pre>{{ tn_size_total }}</pre></td>
</tr> </tr>
<tr> <tr>
<th>Nombre de documents totals</th> <th>Total document count</th>
<td><pre>{{ doc_count }}</pre></td> <td><pre>{{ doc_count }}</pre></td>
</tr> </tr>
<tr> <tr>
<th>Taille totale des documents indexés</th> <th>Total size of indexed documents</th>
<td><pre>{{ doc_size }}</pre></td> <td><pre>{{ doc_size }}</pre></td>
</tr> </tr>
<tr> <tr>
<th>Taille totale de l'index</th> <th>total index size</th>
<td><pre>{{ index_size }}</pre></td> <td><pre>{{ index_size }}</pre></td>
</tr> </tr>
<tr> <tr>
<th>Nombre d'utilisateurs</th> <th>User count</th>
<td><pre>1</pre></td> <td><pre>1</pre></td>
</tr> </tr>
<tr> <tr>
<th>Chemin de la base de donnée SQLite</th> <th>SQLite database path</th>
<td><pre>{{ db_path }}</pre></td> <td><pre>{{ db_path }}</pre></td>
</tr> </tr>
<tr> <tr>
<th>Adresse Elasticsearch</th> <th>Elasticsearch URL</th>
<td><pre>{{ elasticsearch_url }}</pre></td> <td><pre>{{ elasticsearch_url }}</pre></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="card-footer text-muted">Changez les paramètres dans <b>config.py</b></div> <div class="card-footer text-muted">Change global settings in <b>config.py</b></div>
</div> </div>
<div class="card"> <div class="card">
<div class="card-header">Actions</div> <div class="card-header">Actions</div>
<div class="card-body"> <div class="card-body">
<button class="btn btn-danger" onclick="resetAll()"> <button class="btn btn-danger" onclick="resetAll()">
<i class="fas fa-exclamation-triangle"></i> Réinitialiser l'index elasticsearch <i class="fas fa-exclamation-triangle"></i> Reset Elasticsearch
</button> </button>
</div> </div>
</div> </div>
@ -60,8 +60,8 @@
<script> <script>
function resetAll() { function resetAll() {
if (confirm("Cela va entièrement réinitialiser l'index et ses documents devrons être réindexés.\n\n" + if (confirm("This will entirely reset the index and documents will need to be re-indexed.\n\n" +
"Voulez-vous procéder?")) { "Do you want to proceed?")) {
window.location = "/reset_es" window.location = "/reset_es"
} }
} }

View File

@ -1,24 +1,24 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% set active_page = "directory" %} {% set active_page = "directory" %}
{% block title %}Liste des dossiers{% endblock title %} {% block title %}Directory list{% endblock title %}
{% block body %} {% block body %}
<div class="container"> <div class="container">
{# Add directory form #} {# Add directory form #}
<div class="card"> <div class="card">
<div class="card-header">Ajouter un dossier</div> <div class="card-header">Add a directory</div>
<div class="card-body"> <div class="card-body">
<form method="GET" action="/directory/add"> <form method="GET" action="/directory/add">
<div class="form-group"> <div class="form-group">
<input type="text" class="form-control" placeholder="Nom du dossier" name="name"> <input type="text" class="form-control" placeholder="Display name" name="name">
</div> </div>
<div class="form-group"> <div class="form-group">
<input type="text" class="form-control" placeholder="Chemin absolu" name="path"> <input type="text" class="form-control" placeholder="Absolute path" name="path">
</div> </div>
<button type="submit" class="btn btn-success"><i class="fas fa-plus"></i> Ajouter</button> <button type="submit" class="btn btn-success"><i class="fas fa-plus"></i> Add directory</button>
</form> </form>
</div> </div>
@ -26,7 +26,7 @@
{# List of directories #} {# List of directories #}
<div class="card"> <div class="card">
<div class="card-header">Liste des dossiers</div> <div class="card-header">Directory list</div>
<div class="card-body"> <div class="card-body">
<table class="info-table table-hover table-striped"> <table class="info-table table-hover table-striped">
@ -44,7 +44,7 @@
<td>{{ directories[dir].name }}</td> <td>{{ directories[dir].name }}</td>
<td style="word-break: break-all"><pre>{{ directories[dir].path }}</pre></td> <td style="word-break: break-all"><pre>{{ directories[dir].path }}</pre></td>
<td><i class="far {{ "fa-check-square" if directories[dir].enabled else "fa-square" }}"></i></td> <td><i class="far {{ "fa-check-square" if directories[dir].enabled else "fa-square" }}"></i></td>
<td><a href="directory/{{ dir }}" class="btn btn-primary"><i class="fas fa-cog"></i> Gérer</a> </td> <td><a href="directory/{{ dir }}" class="btn btn-primary"><i class="fas fa-cog"></i> </a> Manage</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@ -1,4 +1,4 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% set active_page = "directory" %} {% set active_page = "directory" %}
{% block title %}{{ directory.name }}{% endblock title %} {% block title %}{{ directory.name }}{% endblock title %}
@ -63,40 +63,43 @@
<div class="card"> <div class="card">
<div class="card-header">Sommaire</div> <div class="card-header">Summary</div>
<div class="card-body"> <div class="card-body">
<table class="info-table"> <table class="info-table">
<tr onclick="modifyDisplayName()"> <tr onclick="modifyDisplayName()">
<th style="width: 20%">Nom</th> <th style="width: 20%">Display name</th>
<td> <td>
<pre id="display-name" title="Cliquer pour mettre à jour">{{ directory.name }}</pre> <pre id="display-name" title="Click to update">{{ directory.name }}</pre>
</td> </td>
</tr> </tr>
<tr onclick="modifyPath()"> <tr onclick="modifyPath()">
<th style="width: 20%">Chemin</th> <th style="width: 20%">Path</th>
<td> <td>
<pre id="path" title="Cliquer pour mettre à jour">{{ directory.path }}</pre> <pre id="path" title="Click to update">{{ directory.path }}</pre>
</td> </td>
</tr> </tr>
<tr> <tr>
<th style="width: 20%">Activé</th> <th style="width: 20%">Enabled</th>
<td> <td>
<form action="/directory/{{ directory.id }}/update" style="display: inline;margin-left: 6px;"> <form action="/directory/{{ directory.id }}/update"
style="display: inline;margin-left: 6px;">
<input type="hidden" name="enabled" value="{{ "0" if directory.enabled else "1" }}"> <input type="hidden" name="enabled" value="{{ "0" if directory.enabled else "1" }}">
<button class="btn btn-sm {{ "btn-danger" if directory.enabled else "btn-success" }}"> <button class="btn btn-sm {{ "btn-danger" if directory.enabled else "btn-success" }}">
<i class="far {{ "fa-check-square" if directory.enabled else "fa-square" }}"></i> <i class="far {{ "fa-check-square" if directory.enabled else "fa-square" }}"></i>
{{ "Désactiver" if directory.enabled else "Activer" }} {{ "Disable" if directory.enabled else "Enable" }}
</button> </button>
</form> </form>
</td> </td>
</tr> </tr>
<tr> <tr>
<th>Taille des miniatures</th> <th>Thumbnail cache size</th>
<td><pre>{{ tn_size_formatted }} ({{ tn_size }} octets)</pre></td> <td>
<pre>{{ tn_size_formatted }} ({{ tn_size }} bytes)</pre>
</td>
</tr> </tr>
</table> </table>
</div> </div>
@ -113,7 +116,7 @@
<input type="hidden" value="1" name="type"> <input type="hidden" value="1" name="type">
<input type="hidden" value="{{ directory.id }}" name="directory"> <input type="hidden" value="{{ directory.id }}" name="directory">
<button class="btn btn-primary" href="/task/"> <button class="btn btn-primary" href="/task/">
<i class="fas fa-book"></i> Générer l'index <i class="fas fa-book"></i> Generate index
</button> </button>
</form> </form>
@ -121,7 +124,7 @@
<input type="hidden" value="2" name="type"> <input type="hidden" value="2" name="type">
<input type="hidden" value="{{ directory.id }}" name="directory"> <input type="hidden" value="{{ directory.id }}" name="directory">
<button class="btn btn-primary" href="/task/"> <button class="btn btn-primary" href="/task/">
<i class="far fa-images"></i> Générer les miniatures <i class="far fa-images"></i> Generate thumbnails
</button> </button>
</form> </form>
@ -129,8 +132,8 @@
<button class="btn dropdown-toggle btn-danger" data-toggle="dropdown">Action</button> <button class="btn dropdown-toggle btn-danger" data-toggle="dropdown">Action</button>
<div class="dropdown-menu"> <div class="dropdown-menu">
<a class="dropdown-item" href="/directory/{{ directory.id }}/del">Supprimer le dossier</a> <a class="dropdown-item" href="/directory/{{ directory.id }}/del">Delete directory</a>
<a class="dropdown-item" href="/directory/{{ directory.id }}/reset">Réinitialiser aux paramètres par défaut</a> <a class="dropdown-item" href="/directory/{{ directory.id }}/reset">Reset to default settings</a>
</div> </div>
</div> </div>
</div> </div>
@ -140,13 +143,14 @@
</div> </div>
<div class="card"> <div class="card">
<div class="card-header">Options <a href="#" style="float:right">En savoir plus <i class="fas fa-external-link-alt"></i></a></div> <div class="card-header">Options <a href="#" style="float:right">Learn more <i
class="fas fa-external-link-alt"></i></a></div>
<div class="card-body"> <div class="card-body">
<table class="info-table table-striped table-hover"> <table class="info-table table-striped table-hover">
<thead> <thead>
<tr> <tr>
<th>Option</th> <th>Option</th>
<th>Valeur</th> <th>Value</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -154,7 +158,9 @@
<tr> <tr>
<td style="width: 30%"><span>{{ option.key }}</span></td> <td style="width: 30%"><span>{{ option.key }}</span></td>
<td onclick="modifyVal({{ option.id }}, '{{ option.key }}')" title="Cliquer pour modifier"><pre id="val-{{ option.id }}">{{ option.value }}</pre></td> <td onclick="modifyVal({{ option.id }}, '{{ option.key }}')" title="Click to update">
<pre id="val-{{ option.id }}">{{ option.value }}</pre>
</td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@ -10,7 +10,7 @@
<div class="card-header">{{ doc.name }}</div> <div class="card-header">{{ doc.name }}</div>
<div class="card-body"> <div class="card-body">
<h3>Propriétés du document</h3> <h3>Document properties</h3>
<table class="info-table table-hover table-striped"> <table class="info-table table-hover table-striped">
<tbody> <tbody>
@ -26,21 +26,21 @@
<hr> <hr>
<h3>JSON</h3> <h3>Raw JSON</h3>
<textarea class="form-control" style="min-height: 100px" readonly>{{ doc | tojson }}</textarea> <textarea class="form-control" style="min-height: 100px" readonly>{{ doc | tojson }}</textarea>
<hr> <hr>
<h3><a href="/directory/{{ directory.id }}">Dossier</a></h3> <h3><a href="/directory/{{ directory.id }}">Directory</a></h3>
<table class="info-table table-hover table-striped"> <table class="info-table table-hover table-striped">
<tbody> <tbody>
<tr> <tr>
<th>Chemin</th> <th>Path</th>
<td><pre>{{ directory.path }}</pre></td> <td><pre>{{ directory.path }}</pre></td>
</tr> </tr>
<tr> <tr>
<th>Nom</th> <th>Name</th>
<td><pre>{{ directory.name }}</pre></td> <td><pre>{{ directory.name }}</pre></td>
</tr> </tr>
</tbody> </tbody>

View File

@ -52,7 +52,7 @@
<body> <body>
<nav class="navbar navbar-expand-lg navbar-light" style="background: #F7F7F7; border-bottom: solid 1px #dfdfdf;"> <nav class="navbar navbar-expand-lg navbar-light" style="background: #F7F7F7; border-bottom: solid 1px #dfdfdf;">
<a class="navbar-brand" href="/"><i class="fa fa-search"></i> Recherche</a> <a class="navbar-brand" href="/"><i class="fa fa-search"></i> Search</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
@ -60,30 +60,30 @@
<div class="collapse navbar-collapse" id="navbarSupportedContent"> <div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto"> <ul class="navbar-nav mr-auto">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link {% if "directory" == active_page %}active{% endif %}" href="/directory">Dossiers</a> <a class="nav-link {% if "directory" == active_page %}active{% endif %}" href="/directory">Directories</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link {% if "task" == active_page %}active{% endif %}" href="/task">Tâches</a> <a class="nav-link {% if "task" == active_page %}active{% endif %}" href="/task">Tasks</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link {% if "user" == active_page %}active{% endif %}" href="/user">Utilisateurs</a> <a class="nav-link {% if "user" == active_page %}active{% endif %}" href="/user">Users</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link {% if "dashboard" == active_page %}active{% endif %}" href="/dashboard">Panneau de contrôle</a> <a class="nav-link {% if "dashboard" == active_page %}active{% endif %}" href="/dashboard">Dashboard</a>
</li> </li>
</ul> </ul>
{% if session["username"] %} {% if session["username"] %}
<span> <span>
Connecté en tant que <i>{{ session["username"] }}</i> Logged in as <i>{{ session["username"] }}</i>
{% if session["admin"] %}(Administrateur){% endif %} {% if session["admin"] %}(Admin){% endif %}
</span> </span>
<a href="/logout" class="btn btn-outline-warning" style="margin-left: 8px">Déconnexion</a> <a href="/logout" class="btn btn-outline-warning" style="margin-left: 8px">Logout</a>
{% else %} {% else %}
<form class="form-inline my-2 my-lg-0" method="POST" action="/login"> <form class="form-inline my-2 my-lg-0" method="POST" action="/login">
<input class="form-control mr-sm-2" placeholder="Nom d'utilisateur" name="username"> <input class="form-control mr-sm-2" placeholder="Username" name="username">
<input class="form-control mr-sm-2" type="password" placeholder="Mot de pass" name="password"> <input class="form-control mr-sm-2" type="password" placeholder="Password" name="password">
<button class="btn btn-outline-success my-2 my-sm-0">Connexion</button> <button class="btn btn-outline-success my-2 my-sm-0">Login</button>
</form> </form>
{% endif %} {% endif %}
</div> </div>
@ -97,7 +97,7 @@
<div class="container" style="margin-top: 1em"> <div class="container" style="margin-top: 1em">
{% for category, message in messages %} {% for category, message in messages %}
<div class="alert alert-{{ category }}"> <div class="alert alert-{{ category }}">
<a href="#" class="close" data-dismiss="alert" aria-label="fermer">&times;</a> <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
{{ message | safe }} {{ message | safe }}
</div> </div>
{% endfor %} {% endfor %}

View File

@ -2,7 +2,7 @@
{% set active_page = "search" %} {% set active_page = "search" %}
{% block title %}Recherche{% endblock title %} {% block title %}Search{% endblock title %}
{% block imports %} {% block imports %}
<link href="/static/css/search.css" rel="stylesheet" type="text/css"> <link href="/static/css/search.css" rel="stylesheet" type="text/css">
@ -14,24 +14,24 @@
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<div class="form-group"> <div class="form-group">
<input id="pathBar" type="search" class="form-control" placeholder="Filtrer le chemin"> <input id="pathBar" type="search" class="form-control" placeholder="Filter path">
</div> </div>
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<div class="input-group-text"> <div class="input-group-text">
<span onclick="document.getElementById('barToggle').click()">Doit être égal&nbsp</span> <span onclick="document.getElementById('barToggle').click()">Must match&nbsp</span>
<input title="Basculer entre 'Devrait' and 'doit' être égal" type="checkbox" id="barToggle" onclick="toggleSearchBar()" checked> <input title="Toggle between 'Should' and 'Must' match mode" type="checkbox" id="barToggle" onclick="toggleSearchBar()" checked>
</div> </div>
</div> </div>
<input id="searchBar" type="search" class="form-control" placeholder="Recherche"> <input id="searchBar" type="search" class="form-control" placeholder="Search">
</div> </div>
<input title="Taille des fichiers" id="sizeSlider" name="size"> <input title="File size" id="sizeSlider" name="size">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<label for="directories" >Rechercher dans les dossiers</label> <label for="directories" >Search in directories</label>
<select class="custom-select" id="directories" multiple size="6"> <select class="custom-select" id="directories" multiple size="6">
{% if directories | length > 0%} {% if directories | length > 0%}
@ -39,13 +39,13 @@
<option selected value="{{ dir.id }}">{{ dir.name }}</option> <option selected value="{{ dir.id }}">{{ dir.name }}</option>
{% endfor %} {% endfor %}
{% else %} {% else %}
<option disabled>Il n'existe aucun dossier actif auquel vous avez accès</option> <option disabled>There are no active directories which you have access to</option>
{% endif %} {% endif %}
</select> </select>
</div> </div>
<div class="col"> <div class="col">
<label>Types de fichier</label> <label>Mime types</label>
<div class="tree"></div> <div class="tree"></div>
</div> </div>

View File

@ -1,7 +1,7 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% set active_page = "task" %} {% set active_page = "task" %}
{% block title %}Tâches{% endblock title %} {% block title %}Tasks{% endblock title %}
{% block body %} {% block body %}
@ -43,23 +43,23 @@
<div class="container"> <div class="container">
<div class="card"> <div class="card">
<div class="card-header">Ajouter un tâche</div> <div class="card-header">Add task</div>
<div class="card-body"> <div class="card-body">
<form class="form-inline" action="/task/add"> <form class="form-inline" action="/task/add">
<select title="Sélectionner le type de tâche" class="form-control" id="type" name="type"> <select title="Select task type" class="form-control" id="type" name="type">
<option hidden>Créer un tâche...</option> <option hidden>Create task...</option>
<option value="1">d'indexation</option> <option value="1">Indexing</option>
<option value="2">de génération des miniatures</option> <option value="2">Thumnail Generation</option>
</select> </select>
<select title="Sélectionner le dossier" class="form-control" id="directory" name="directory" > <select title="Select directory" class="form-control" id="directory" name="directory" >
<option hidden>Pour le dossier...</option> <option hidden>For directory...</option>
{% for dir_id in directories %} {% for dir_id in directories %}
<option value="{{ dir_id }}">{{ directories[dir_id].name }}</option> <option value="{{ dir_id }}">{{ directories[dir_id].name }}</option>
{% endfor %} {% endfor %}
</select> </select>
<button class="form-control btn btn-success"><i class="fas fa-plus"></i> Ajouter</button> <button class="form-control btn btn-success"><i class="fas fa-plus"></i> Add</button>
</form> </form>
</div> </div>
</div> </div>
@ -81,7 +81,7 @@
if (currentTask.total === 0) { if (currentTask.total === 0) {
document.getElementById("task-label-" + currentTask.id).innerHTML = "Calcul du nombre de fichier..."; document.getElementById("task-label-" + currentTask.id).innerHTML = "Calculating file count...";
} else { } else {
let bar = document.getElementById("task-bar-" + currentTask.id); let bar = document.getElementById("task-bar-" + currentTask.id);
@ -107,16 +107,16 @@
</script> </script>
<div class="card"> <div class="card">
<div class="card-header">Tâches en cours</div> <div class="card-header">Ongoing tasks</div>
<div class="card-body"> <div class="card-body">
{% for task_id in tasks | sort() %} {% for task_id in tasks | sort() %}
<div class="task-wrapper container-fluid"> <div class="task-wrapper container-fluid">
<a class="task-name" href="/directory/{{ tasks[task_id].dir_id }}">{{ directories[tasks[task_id].dir_id].name }}</a> <a class="task-name" href="/directory/{{ tasks[task_id].dir_id }}">{{ directories[tasks[task_id].dir_id].name }}</a>
<span class="task-info"> - <span class="task-info"> -
{% if tasks[task_id].type == 1 %} {% if tasks[task_id].type == 1 %}
Indexation Indexing
{% else %} {% else %}
Génération des miniatures Thumbnail generation
{% endif %} {% endif %}
</span> </span>
@ -124,12 +124,12 @@
<div class="container-fluid p-2"> <div class="container-fluid p-2">
<div class="progress"> <div class="progress">
<div id="task-bar-{{ task_id }}" class="progress-bar" role="progressbar" style="width: 0;"> <div id="task-bar-{{ task_id }}" class="progress-bar" role="progressbar" style="width: 0;">
<span id="task-label-{{ task_id }}">En attente</span> <span id="task-label-{{ task_id }}">Queued</span>
</div> </div>
</div> </div>
</div> </div>
<div class="p-2"><a class="btn btn-danger" href="/task/{{ task_id }}/del">Annuler</a></div> <div class="p-2"><a class="btn btn-danger" href="/task/{{ task_id }}/del">Cancel</a></div>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}

View File

@ -1,16 +1,16 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% set active_page = "user" %} {% set active_page = "user" %}
{% block title %}Liste des utilisateurs{% endblock title %} {% block title %}User list{% endblock title %}
{% block body %} {% block body %}
<div class="container"> <div class="card"> <div class="container"> <div class="card">
<div class="card-header">Créer un utilisateur</div> <div class="card-header">Create user</div>
<div class="card-body"> <div class="card-body">
{% if not admin_account_present %} {% if not admin_account_present %}
<p>Cette page est débloquée parce qu'il n'y a aucun compte administrateur</p> <p>This page is unlocked because there are no admin accounts</p>
{% endif %} {% endif %}
<form method="POST" action="/user/add"> <form method="POST" action="/user/add">
@ -18,37 +18,37 @@
<div class="input-group form-group"> <div class="input-group form-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<div class="input-group-text"> <div class="input-group-text">
<label for="is_admin" style="margin: 0 8px 0 0">Administrateur</label> <label for="is_admin" style="margin: 0 8px 0 0">Set admin</label>
<input title="administrateur" type="checkbox" id="is_admin" name="is_admin"> <input title="Set user as admin" type="checkbox" id="is_admin" name="is_admin">
</div> </div>
</div> </div>
<input type="text" class="form-control" placeholder="Nom d'utilisateur" name="username"> <input type="text" class="form-control" placeholder="Username" name="username">
</div> </div>
<div class="form-group"> <div class="form-group">
<input type="password" class="form-control" placeholder="Mot de passe" name="password"> <input type="password" class="form-control" placeholder="Password" name="password">
</div> </div>
<button type="submit" class="btn btn-success"><i class="fas fa-plus"></i> Créer un utilissateur</button> <button type="submit" class="btn btn-success"><i class="fas fa-plus"></i> Add user</button>
</form> </form>
</div> </div>
</div> </div>
<div class="card"> <div class="card">
<div class="card-header">Utilisateurs</div> <div class="card-header">Users</div>
<div class="card-body"> <div class="card-body">
<table class="info-table table-hover table-striped"> <table class="info-table table-hover table-striped">
<thead> <thead>
<tr> <tr>
<th>Utilisateur</th> <th>User</th>
<th>Administrateur</th> <th>Admin</th>
<th>Actions</th> <th>Actions</th>
</tr> </thead> </tr> </thead>
<tbody> <tbody>
{% for user in users %} <tr> {% for user in users %} <tr>
<td style="width: 80%;">{% if session["username"] == user %}<b>{{ user }}{% else %}{{ user }}{% endif %}</b></td> <td style="width: 80%;">{% if session["username"] == user %}<b>{{ user }}{% else %}{{ user }}{% endif %}</b></td>
<td><i class="far {{ "fa-check-square" if users[user].admin else "fa-square" }}"></i></td> <td><i class="far {{ "fa-check-square" if users[user].admin else "fa-square" }}"></i></td>
<td><a href="/user/{{ user }}" class="btn btn-primary">Gérer</a></td> <td><a href="/user/{{ user }}" class="btn btn-primary">Manage</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@ -7,19 +7,19 @@
<div class="container"> <div class="container">
<div class="card"> <div class="card">
<div class="card-header">Gérer les permission de <strong>{{ user.username }}</strong></div> <div class="card-header">Manage permissions of <strong>{{ user.username }}</strong></div>
<div class="card-body"> <div class="card-body">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<h5>Administrateur: </h5> <h5>Admin: </h5>
</div> </div>
<div class="col"> <div class="col">
<form action="/user/{{ user.username }}/set_admin" style="display: inline;margin-left: 6px;"> <form action="/user/{{ user.username }}/set_admin" style="display: inline;margin-left: 6px;">
<input type="hidden" name="admin" value="{{ "0" if user.admin else "1" }}"> <input type="hidden" name="admin" value="{{ "0" if user.admin else "1" }}">
<button class="btn btn-sm {{ "btn-danger" if user.admin else "btn-success" }}"> <button class="btn btn-sm {{ "btn-danger" if user.admin else "btn-success" }}">
<i class="far {{ "fa-check-square" if user.admin else "fa-square" }}"></i> <i class="far {{ "fa-check-square" if user.admin else "fa-square" }}"></i>
{{ "Rétrograder" if user.admin else "Faire administrateur" }} {{ "Remove admin" if user.admin else "Set admin" }}
</button> </button>
<input type="hidden" name="dir_id" value="{{ dir_id }}"> <input type="hidden" name="dir_id" value="{{ dir_id }}">
</form> </form>
@ -31,8 +31,8 @@
<table class="info-table table-hover table-striped"> <table class="info-table table-hover table-striped">
<thead> <thead>
<tr> <tr>
<th>Dossier</th> <th>Directory</th>
<th>Accès</th> <th>Access</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -43,7 +43,7 @@
<input type="hidden" name="access" value="{{ "0" if dir_id in user.readable_directories else "1" }}"> <input type="hidden" name="access" value="{{ "0" if dir_id in user.readable_directories else "1" }}">
<button class="btn btn-sm {{ "btn-danger" if dir_id in user.readable_directories else "btn-success" }}"> <button class="btn btn-sm {{ "btn-danger" if dir_id in user.readable_directories else "btn-success" }}">
<i class="far {{ "fa-check-square" if dir_id in user.readable_directories else "fa-square" }}"></i> <i class="far {{ "fa-check-square" if dir_id in user.readable_directories else "fa-square" }}"></i>
{{ "Désactiver" if dir_id in user.readable_directories else "Activer" }} {{ "Disable" if dir_id in user.readable_directories else "Enable" }}
</button> </button>
<input type="hidden" name="dir_id" value="{{ dir_id }}"> <input type="hidden" name="dir_id" value="{{ dir_id }}">
</form></td> </form></td>
@ -53,15 +53,14 @@
</table> </table>
<hr> <hr>
<button class="btn btn-danger" onclick="userDelete()">Delete account</button>
<button class="btn btn-danger" onclick="userDelete()">Supprimer le compte</button>
</div> </div>
</div> </div>
<script> <script>
function userDelete() { function userDelete() {
if (confirm("Êtes vous certain de vouloir supprimer ce compte?")) { if (confirm("Are you sure?")) {
window.location = "/user/{{ user.username }}/del" window.location = "/user/{{ user.username }}/del"
} }
} }

View File

@ -12,7 +12,7 @@ class MimeGuesserTest(TestCase):
guesser = ContentMimeGuesser() guesser = ContentMimeGuesser()
self.assertEqual("text/x-shellscript", guesser.guess_mime(dir_name + "/test_folder/test_utf8.sh")) self.assertEqual("text/x-shellscript", guesser.guess_mime(dir_name + "/test_folder/test_utf8.sh"))
self.assertEqual("text/plain", guesser.guess_mime(dir_name + "/test_folder/more_books.json")) self.assertTrue(guesser.guess_mime(dir_name + "/test_folder/more_books.json") in ["application/json", "text/plain"])
self.assertEqual("application/java-archive", guesser.guess_mime(dir_name + "/test_folder/post.jar")) self.assertEqual("application/java-archive", guesser.guess_mime(dir_name + "/test_folder/post.jar"))
self.assertEqual("image/jpeg", guesser.guess_mime(dir_name + "/test_folder/sample_1.jpg")) self.assertEqual("image/jpeg", guesser.guess_mime(dir_name + "/test_folder/sample_1.jpg"))
@ -20,7 +20,8 @@ class MimeGuesserTest(TestCase):
guesser = ExtensionMimeGuesser() guesser = ExtensionMimeGuesser()
self.assertEqual("text/x-sh", guesser.guess_mime(dir_name + "/test_folder/test_utf8.sh")) self.assertTrue(guesser.guess_mime(dir_name + "/test_folder/test_utf8.sh") in ["text/x-sh", "application/x-sh"])
self.assertEqual("application/json", guesser.guess_mime(dir_name + "/test_folder/more_books.json")) self.assertEqual("application/json", guesser.guess_mime(dir_name + "/test_folder/more_books.json"))
self.assertEqual("application/java-archive", guesser.guess_mime(dir_name + "/test_folder/post.jar")) self.assertTrue(guesser.guess_mime(dir_name + "/test_folder/post.jar")
in ["application/java-archive", "application/x-java-archive"])
self.assertEqual("image/jpeg", guesser.guess_mime(dir_name + "/test_folder/sample_1.jpg")) self.assertEqual("image/jpeg", guesser.guess_mime(dir_name + "/test_folder/sample_1.jpg"))