Initial commit for finalisation web interface
This commit is contained in:
1 parent
b295f871a7
commit
c36642e8de
33 files changed
+2745
-138
No files matched your search
@@ -279,6 +279,7 @@ class CopienatorApp(tk.Tk):
|
||||
self.step_by_id = {step.id: step for step in self.steps}
|
||||
self.state_store = StateStore()
|
||||
self.runner = ProcessRunner()
|
||||
self.web_session = None
|
||||
self.active_step_id: str | None = None
|
||||
self.current_step: StepDefinition | None = None
|
||||
self.arg_vars: dict[str, tk.Variable] = {}
|
||||
@@ -359,6 +360,7 @@ class CopienatorApp(tk.Tk):
|
||||
top, text="Ouvrir l’énoncé", command=self._open_statement_pdf
|
||||
)
|
||||
self.open_statement_button.grid(row=0, column=5, padx=(6, 0))
|
||||
ttk.Button(top, text="Finalisation web…", command=self._open_finalisation_web).grid(row=0, column=6, padx=(6, 0))
|
||||
ttk.Button(top, text="Diagnostic…", command=self._show_diagnostics).grid(row=0, column=7, padx=(6, 0))
|
||||
|
||||
ttk.Label(top, text="Clé Gemini").grid(row=1, column=0, sticky="w", padx=(0, 8), pady=(7, 0))
|
||||
@@ -536,6 +538,107 @@ class CopienatorApp(tk.Tk):
|
||||
status = ttk.Label(self, textvariable=self.info_var, anchor="w", relief="sunken", padding=(6, 3))
|
||||
status.grid(row=3, column=0, sticky="ew")
|
||||
|
||||
def _open_finalisation_web(self) -> None:
|
||||
if self.web_session is not None or self.runner.running or self.active_step_id or self.batch_monitor.active:
|
||||
messagebox.showinfo("Traitement en cours", "Terminez le traitement ou la surveillance en cours avant d’ouvrir la finalisation web.")
|
||||
return
|
||||
if not self.evaluation:
|
||||
messagebox.showerror("Évaluation absente", "Chargez d’abord une évaluation.")
|
||||
return
|
||||
self._save_current_form()
|
||||
dialog = tk.Toplevel(self)
|
||||
dialog.title("Finalisation web")
|
||||
dialog.transient(self)
|
||||
dialog.resizable(False, False)
|
||||
frame = ttk.Frame(dialog, padding=24)
|
||||
frame.pack(fill="both", expand=True)
|
||||
text = tk.StringVar(value="Choisissez le mode utilisé pour lire les annotations manuscrites.")
|
||||
ttk.Label(frame, textvariable=text, wraplength=500).pack(pady=(0, 12))
|
||||
mode = tk.StringVar(value=annotation_mode_for_reader(self.state_store.step("read_annotations")))
|
||||
choice = ttk.Combobox(frame, textvariable=mode, values=("BGnot", "Bnot"), state="readonly")
|
||||
choice.pack(fill="x", pady=8)
|
||||
url = tk.StringVar()
|
||||
link = ttk.Entry(frame, textvariable=url, state="readonly", width=65)
|
||||
link.pack(fill="x", pady=8)
|
||||
|
||||
def open_browser():
|
||||
import webbrowser
|
||||
if self.web_session:
|
||||
webbrowser.open(self.web_session.url)
|
||||
|
||||
def restore():
|
||||
session = self.web_session
|
||||
self.web_session = None
|
||||
dialog.grab_release()
|
||||
dialog.destroy()
|
||||
if session:
|
||||
data = session.service.state()
|
||||
reader = self.state_store.step("read_annotations")
|
||||
values = dict(reader.get("values", {}))
|
||||
values["update_score"] = True
|
||||
if data["dirty"] or session.service.job["status"] != "idle":
|
||||
self.state_store.invalidate_after(self._progression_ids("read_annotations"), "read_annotations")
|
||||
self.state_store.update_step("read_annotations", variant="standard" if session.service.mode == "Bnot" else "grouped")
|
||||
if data["dirty"] or session.service.job["status"] == "failed":
|
||||
self.state_store.update_step("read_annotations", status="stale", values=values)
|
||||
self.state_store.update_step("giving_names", status="stale")
|
||||
elif session.service.job["status"] == "success":
|
||||
self.state_store.update_step("read_annotations", status="success", values=values)
|
||||
self.state_store.update_step("giving_names", status="detected")
|
||||
self._populate_tree()
|
||||
self._render_step()
|
||||
self._update_controls()
|
||||
|
||||
def poll():
|
||||
session = self.web_session
|
||||
if session is None:
|
||||
return
|
||||
if not session.alive:
|
||||
restore()
|
||||
return
|
||||
running = session.service.job["running"]
|
||||
close_button.configure(state="disabled" if running else "normal")
|
||||
text.set("Régénération en cours. Le GUI reste verrouillé jusqu’à la fin." if running else
|
||||
"Finalisation ouverte dans le navigateur. Le GUI est verrouillé pendant cette session.")
|
||||
dialog.after(300, poll)
|
||||
|
||||
def stop():
|
||||
if self.web_session:
|
||||
try:
|
||||
self.web_session.request_stop()
|
||||
text.set("Fermeture du serveur…")
|
||||
except ValueError as exc:
|
||||
messagebox.showinfo("Traitement en cours", str(exc), parent=dialog)
|
||||
else:
|
||||
restore()
|
||||
|
||||
def start():
|
||||
try:
|
||||
from copienator.finalisation_server import WebSession
|
||||
self.web_session = WebSession(self.evaluation, mode.get())
|
||||
except Exception as exc:
|
||||
messagebox.showerror("Finalisation web", str(exc), parent=dialog)
|
||||
return
|
||||
choice.configure(state="disabled")
|
||||
start_button.configure(state="disabled")
|
||||
url.set(self.web_session.url)
|
||||
browser_button.configure(state="normal")
|
||||
close_button.configure(text="Arrêter le serveur et reprendre")
|
||||
open_browser()
|
||||
poll()
|
||||
|
||||
actions = ttk.Frame(frame)
|
||||
actions.pack(pady=12)
|
||||
start_button = ttk.Button(actions, text="Ouvrir", command=start)
|
||||
start_button.pack(side="left", padx=4)
|
||||
browser_button = ttk.Button(actions, text="Rouvrir le navigateur", command=open_browser, state="disabled")
|
||||
browser_button.pack(side="left", padx=4)
|
||||
close_button = ttk.Button(actions, text="Annuler", command=stop)
|
||||
close_button.pack(side="left", padx=4)
|
||||
dialog.protocol("WM_DELETE_WINDOW", stop)
|
||||
dialog.grab_set()
|
||||
dialog.focus_set()
|
||||
|
||||
def _show_diagnostics(self) -> None:
|
||||
checks = collect_diagnostics(
|
||||
self.show_personal_steps, self.api_key_var.get(), self.evaluation
|
||||
@@ -1617,6 +1720,8 @@ class CopienatorApp(tk.Tk):
|
||||
return True
|
||||
|
||||
def _run_current_step(self, *, syncthing_ready=False, review_command=None, orientation_repair=False) -> None:
|
||||
if self.web_session is not None:
|
||||
return
|
||||
step = self.current_step
|
||||
evaluation = self.evaluation
|
||||
if orientation_repair and (not step or step.id != 'labels'):
|
||||
@@ -2328,6 +2433,9 @@ class CopienatorApp(tk.Tk):
|
||||
self.tree.see("correction")
|
||||
|
||||
def _on_close(self) -> None:
|
||||
if self.web_session is not None:
|
||||
messagebox.showinfo("Finalisation web", "Arrêtez le serveur depuis la fenêtre de finalisation avant de fermer le GUI.")
|
||||
return
|
||||
if self.runner.running:
|
||||
if not messagebox.askyesno(
|
||||
"Traitement en cours", "Un script est encore actif. Le forcer à s’arrêter et fermer l’application ?"
|
||||
|
||||
Reference in new issue
Block a user