3.5.0: «Qué va a pasar» se explica con una carpeta, y una barra dice por dónde va
Munka, con el plan de Diana Méndez delante: «se lee mucho pero se entiende poco», «lo de ordenar por año y por mes, ¿me toca seleccionar uno a uno o lo hace todo?», y quería una barra para saber por dónde va y si hace falta algo. - Una frase arriba y un solo botón, «Aplicar los N cambios»: un clic lo hace todo, en orden. - Tres fichas, una por paso, con cambios, peso y cuántos quedan sin marcar; se pulsa una y se ve. - Un ejemplo animado: la fila más representativa del paso como dos ramas de carpetas, «Ahora» y «Después», y lo que se mueve vuela de una a otra; debajo, la frase y el porqué. «Otro ejemplo» recorre las filas. - La lista, corta: de dónde → a dónde y la cuenta; el motivo solo con «ver por qué». Lo que no va solo queda aparte y contado (cosméticos «01 - Celular» → «01- Celular», y dudosos), con «marcar los cosméticos». - Al aplicar, el servidor cuenta archivo a archivo (/api/aplicando) y la interfaz lo sondea: barra, qué se mueve ahora, y al acabar qué se hizo, qué falló y qué queda sin hacer. - Los avisos van plegados bajo «N cosas que conviene mirar antes de aplicar». Pruebas: probar 19, prueba_orden 33, prueba_funcional 30 (comprueba que el avance acaba en tantas de tantas), prueba_ventana 18. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Este commit está contenido en:
@@ -42,7 +42,7 @@ import actualizador
|
||||
asistente.O = sys.modules[__name__]
|
||||
actualizador.O = sys.modules[__name__]
|
||||
|
||||
VERSION = "3.4.0"
|
||||
VERSION = "3.5.0"
|
||||
|
||||
BASE = os.path.dirname(os.path.abspath(sys.executable if getattr(sys, "frozen", False) else __file__))
|
||||
# Empaquetado: el programa corre con el motor que viaja en su propia carpeta. OrganizadorLabstream.exe es
|
||||
@@ -1859,7 +1859,11 @@ def mover(origen, destino, lote, movidos):
|
||||
movidos.append((origen, destino))
|
||||
|
||||
|
||||
APLICANDO = {"hechas": 0, "total": 0, "actual": ""}
|
||||
# hechas/total cuentan filas del plan (es lo que miran «en marcha» y la barra de tareas); unidades cuenta
|
||||
# archivo a archivo dentro de las filas de archivos sueltos, para que la barra avance suave en una fila de
|
||||
# 400 clips; actual/archivo dicen qué se está moviendo; lote/fin, qué tanda fue y cuándo acabó.
|
||||
APLICANDO = {"hechas": 0, "total": 0, "actual": "", "archivo": "", "unidades": 0, "unidades_total": 0,
|
||||
"movidos": 0, "fallos": 0, "lote": "", "inicio": 0, "fin": 0}
|
||||
|
||||
|
||||
def aplicar(raiz, filas):
|
||||
@@ -1868,9 +1872,12 @@ def aplicar(raiz, filas):
|
||||
errores = []
|
||||
hechas = 0
|
||||
filas = sorted(filas, key=lambda f: (0 if f.get("archivos") else 1, -len(os.path.normpath(f["origen"]).split(os.sep)), f["origen"].lower()))
|
||||
APLICANDO.update(hechas=0, total=len(filas), actual="", raiz=_clave(raiz))
|
||||
unidades_total = sum(len(f["archivos"]) if f.get("archivos") else 1 for f in filas)
|
||||
fallos = 0
|
||||
APLICANDO.update(hechas=0, total=len(filas), actual="", archivo="", raiz=_clave(raiz), unidades=0,
|
||||
unidades_total=unidades_total, movidos=0, fallos=0, lote=lote, inicio=time.time(), fin=0)
|
||||
for f in filas:
|
||||
APLICANDO.update(hechas=hechas, actual=f.get("origen_rel") or "")
|
||||
APLICANDO.update(hechas=hechas, actual=f.get("origen_rel") or "", archivo="")
|
||||
if f.get("archivos"):
|
||||
# cada archivo va por su cuenta: antes, un clip abierto en Resolve cortaba el bucle y los
|
||||
# ciento y pico restantes de esa misma fila no se intentaban, mientras el resumen decía
|
||||
@@ -1884,6 +1891,7 @@ def aplicar(raiz, filas):
|
||||
errores.append(f"{f.get('origen_rel')}: no se pudo crear la carpeta destino: {ex}")
|
||||
continue
|
||||
for a in f["archivos"]:
|
||||
APLICANDO.update(unidades=APLICANDO["unidades"] + 1, archivo=os.path.basename(a))
|
||||
if not os.path.exists(a):
|
||||
continue
|
||||
try:
|
||||
@@ -1892,6 +1900,8 @@ def aplicar(raiz, filas):
|
||||
fallos_fila += 1
|
||||
if fallos_fila <= 5:
|
||||
errores.append(f"{os.path.basename(a)}: {ex}")
|
||||
APLICANDO.update(movidos=len(movidos), fallos=fallos + fallos_fila)
|
||||
fallos += fallos_fila
|
||||
if fallos_fila > 5:
|
||||
errores.append(f"{f.get('origen_rel')}: y otros {fallos_fila - 5} archivos que tampoco se pudieron mover")
|
||||
if not fallos_fila:
|
||||
@@ -1902,10 +1912,15 @@ def aplicar(raiz, filas):
|
||||
mover(f["origen"], f["destino"], lote, movidos)
|
||||
hechas += 1
|
||||
else:
|
||||
fallos += 1
|
||||
errores.append(f"{f.get('origen_rel')}: ya no está donde decía el plan (¿se movió fuera de la app?)")
|
||||
except Exception as ex: # noqa
|
||||
fallos += 1
|
||||
errores.append(f"{f.get('origen_rel')}: {ex}")
|
||||
APLICANDO.update(hechas=len(filas), actual="") # terminado (con o sin errores): la barra de tareas deja de mostrar «Moviendo»
|
||||
APLICANDO.update(unidades=APLICANDO["unidades"] + 1, movidos=len(movidos), fallos=fallos)
|
||||
# terminado (con o sin errores): la barra de tareas deja de mostrar «Moviendo»
|
||||
APLICANDO.update(hechas=len(filas), actual="", archivo="", unidades=unidades_total, movidos=len(movidos),
|
||||
fallos=fallos, fin=time.time())
|
||||
# carpetas que quedaron vacías al vaciarlas (p. ej. "Grabacion" tras repartir sus archivos)
|
||||
for f in filas:
|
||||
base = f["origen"] if f.get("archivos") else os.path.dirname(f["origen"])
|
||||
@@ -5583,6 +5598,8 @@ class Manejador(BaseHTTPRequestHandler):
|
||||
return
|
||||
if ruta == "/api/estado":
|
||||
return self._json(estado_general())
|
||||
if ruta == "/api/aplicando": # la barra de «Aplicar», sondeada mientras corre
|
||||
return self._json(dict(APLICANDO))
|
||||
if ruta == "/api/soltado":
|
||||
r = soltado(q.get("nombre", ""))
|
||||
return self._json({"ruta": r, "es_archivo": bool(r) and os.path.isfile(r)})
|
||||
@@ -6225,7 +6242,7 @@ def avance():
|
||||
if AUTO.get("activo"):
|
||||
return AUTO["hechas"] / AUTO["total"] if AUTO.get("total") else -1
|
||||
if APLICANDO.get("total") and APLICANDO.get("hechas", 0) < APLICANDO["total"]:
|
||||
return APLICANDO["hechas"] / APLICANDO["total"]
|
||||
return APLICANDO["unidades"] / APLICANDO["unidades_total"] if APLICANDO.get("unidades_total") else APLICANDO["hechas"] / APLICANDO["total"]
|
||||
if asistente.ESTADO.get("activo"):
|
||||
return asistente.ESTADO["pct"] / 100 if asistente.ESTADO.get("total") else -1
|
||||
for a in list(ANALISIS.values()):
|
||||
|
||||
Referencia en una nueva incidencia
Block a user