2.2.1: el diálogo de añadir carpeta se explica solo
«Cliente» y «Tipo» no decían para qué servían ni qué iba a pasar al confirmar, y el tipo se describía por a quién se le hace en vez de por cómo queda ordenado. - Cada campo es una pregunta con una línea debajo que dice qué hace. - Debajo se ven, armadas con la plantilla de verdad (ESTADO.plantillas), las cuatro carpetas donde va a guardar el material; cambian al cambiar el tipo. - Si el nombre es un cliente que ya existe, se preselecciona SU tipo. Antes salía siempre «contenido», así que una segunda carpeta de un cliente de pauta o de proyecto se podía registrar con la plantilla equivocada. - El diálogo dice que al confirmar solo lee y arma una lista, sin mover nada. - TIPOS_CLIENTE se reescribe en términos de cómo queda ordenado. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Este commit está contenido en:
@@ -143,6 +143,13 @@
|
||||
.modal.on{display:flex}
|
||||
.modal .box{max-width:640px;width:92%;max-height:90vh;overflow:auto;box-shadow:0 20px 60px rgba(0,0,0,.18)}
|
||||
.modal h3{font-size:15px;text-transform:none;letter-spacing:0;color:var(--tx);font-weight:700}
|
||||
.preg{margin:14px 0 0}
|
||||
.preg>label{display:block;font-weight:600;margin-bottom:5px}
|
||||
.preg>span{display:block;color:var(--mut);font-size:12px;margin-top:4px}
|
||||
.ejtipo{display:grid;gap:5px;margin:6px 0 0;padding:10px 12px;background:var(--panel2);border-radius:8px}
|
||||
.ejtipo div{display:flex;gap:4px 10px;align-items:baseline;flex-wrap:wrap}
|
||||
.ejtipo b{font-family:ui-monospace,Consolas,monospace;font-size:11.5px;font-weight:600;word-break:break-all}
|
||||
.ejtipo span{font-size:12px;color:var(--mut)}
|
||||
pre{background:var(--panel2);padding:10px;border-radius:6px;overflow:auto;font-size:11.5px;max-height:280px}
|
||||
.tree{font-family:ui-monospace,Consolas,monospace;font-size:11.5px;white-space:pre;line-height:1.5;overflow:auto;max-height:420px}
|
||||
.hint{background:var(--acc2);border:0;border-left:3px solid var(--acc);border-radius:0 6px 6px 0;padding:9px 12px;color:var(--tx);font-size:12.5px;margin-bottom:14px}
|
||||
@@ -1234,12 +1241,43 @@ $('#btnElegir').onclick = () => elegirCarpeta($('#btnElegir'));
|
||||
$('#btnElegir2').onclick = e => { e.stopPropagation(); elegirCarpeta($('#btnElegir2')); };
|
||||
zona.onkeydown = e => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); zona.onclick(); } };
|
||||
$('#vacioCaja').onclick = () => zona.onclick(); $('#vacioCaja').onkeydown = zona.onkeydown;
|
||||
const MESES_UI = ['Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'];
|
||||
const EJEMPLO_CUBETAS = [['GRABACION', 'lo que sale de la cámara'], ['PIEZA', 'cada pieza, con su edición'],
|
||||
['EXPORTADOS', 'lo que ya se entregó'], ['MUSICA', 'música y sonidos de siempre'],
|
||||
['BASURA', 'lo que sobra, para que lo borres tú']];
|
||||
function ejemploTipo(ruta, tipo){
|
||||
// se arma con la plantilla de verdad, así que el ejemplo es exactamente lo que la app va a hacer
|
||||
const pl = (ESTADO.plantillas || {})[tipo] || {}, h = new Date();
|
||||
const val = {anio: h.getFullYear(), mes: `${String(h.getMonth() + 1).padStart(2, '0')}- ${MESES_UI[h.getMonth()]}`,
|
||||
nombre: 'Nombre de la pieza', sub: '', fuente: '', rel: ''};
|
||||
const base = (ruta || '').replace(/[\\/]+$/, ''), visto = new Set(), filas = [];
|
||||
for (const [cub, que] of EJEMPLO_CUBETAS){
|
||||
const dest = (pl[cub] || '').replace(/\{(\w+)\}/g, (_, k) => val[k] !== undefined ? String(val[k]) : '')
|
||||
.replace(/\/+$/, '').replace(/\/+/g, '\\');
|
||||
if (!dest || visto.has(dest)) continue;
|
||||
visto.add(dest);
|
||||
filas.push(`<div><b>${esc(base)}\\${esc(dest)}\\</b><span>${que}</span></div>`);
|
||||
if (filas.length === 4) break;
|
||||
}
|
||||
return filas.join('');
|
||||
}
|
||||
function proponerRaiz(ruta){
|
||||
if (!ruta) return;
|
||||
const clientes = Object.keys(ESTADO.config.clientes);
|
||||
const nombre = ruta.replace(/[\\/]+$/, '').split(/[\\/]/).pop();
|
||||
const sugerido = clientes.find(c => (ESTADO.config.clientes[c].alias || []).concat(c).some(a => a.toLowerCase() === nombre.toLowerCase())) || nombre;
|
||||
modal('Añadir carpeta de cliente', `<p class="path">${esc(ruta)}</p><label>Cliente <input type="text" id="nuevoCliente" value="${esc(sugerido)}" list="lcli2"></label><datalist id="lcli2">${clientes.map(c => `<option value="${esc(c)}">`).join('')}</datalist> <label>Tipo <select id="nuevoTipo">${Object.entries(ESTADO.tipos).map(([k,v]) => `<option value="${k}">${k} · ${esc(v)}</option>`).join('')}</select></label>`, seguro(async () => {
|
||||
const tipoDe = c => ((ESTADO.config.clientes[c] || {}).tipo) || 'contenido';
|
||||
modal('Añadir carpeta de cliente', `<p class="path">${esc(ruta)}</p>
|
||||
<div class="preg"><label for="nuevoCliente">¿De quién es este material?</label>
|
||||
<input type="text" id="nuevoCliente" value="${esc(sugerido)}" list="lcli2" style="width:100%">
|
||||
<datalist id="lcli2">${clientes.map(c => `<option value="${esc(c)}">`).join('')}</datalist>
|
||||
<span>Con ese nombre reúne todas sus carpetas, aunque en cada disco estén escritas distinto.</span></div>
|
||||
<div class="preg"><label for="nuevoTipo">¿Qué clase de trabajo le haces?</label>
|
||||
<select id="nuevoTipo" style="width:100%">${Object.entries(ESTADO.tipos).map(([k,v]) => `<option value="${k}">${esc(v)}</option>`).join('')}</select>
|
||||
<span>Es lo único que decide en qué carpetas va a guardar su material. Se cambia luego en Ajustes.</span></div>
|
||||
<p style="margin:14px 0 0"><b>Así va a quedar ordenada:</b></p>
|
||||
<div class="ejtipo" id="ejemploTipo"></div>
|
||||
<p class="mut" style="margin-top:12px">Al confirmar solo la lee y te arma una lista de lo que haría. <b>No mueve ni un archivo</b> hasta que tú lo apliques.</p>`, seguro(async () => {
|
||||
const cliente = $('#nuevoCliente').value.trim() || nombre, tipo = $('#nuevoTipo').value;
|
||||
const raices = ESTADO.config.raices.filter(r => r.ruta.toLowerCase() !== ruta.toLowerCase()); raices.push({ruta, cliente, tipo});
|
||||
await api('/api/raices', {raices});
|
||||
@@ -1248,6 +1286,13 @@ function proponerRaiz(ruta){
|
||||
await api('/api/escanear', {raiz: raizActual()}); await cargarEstado(); irA('carpeta');
|
||||
aviso('Carpeta añadida. Escaneando…', 'ok');
|
||||
}));
|
||||
const sel = $('#nuevoTipo'), inp = $('#nuevoCliente');
|
||||
const pinta = () => $('#ejemploTipo').innerHTML = ejemploTipo(ruta, sel.value);
|
||||
sel.value = tipoDe(sugerido); sel.onchange = pinta;
|
||||
// si escribe el nombre de un cliente que ya existe, manda el tipo que ese cliente ya tiene: dos
|
||||
// carpetas del mismo cliente ordenadas con plantillas distintas serían un lío
|
||||
inp.oninput = () => { const c = ESTADO.config.clientes[inp.value.trim()]; if (c && c.tipo && c.tipo !== sel.value) { sel.value = c.tipo; pinta(); } };
|
||||
pinta();
|
||||
}
|
||||
|
||||
// ---------------- asistente ----------------
|
||||
|
||||
Referencia en una nueva incidencia
Block a user