feat: documentar proceso de entrega final

Co-authored-by: wsf <alejandro.sartorio@gmail.com>
Signed-off-by: wsf <alejandro.sartorio@gmail.com>
This commit is contained in:
wsf
2026-08-25 16:21:47 -03:00
parent 49cdc3364c
commit 4aa1374ddc
6 changed files with 68 additions and 5 deletions
+19
View File
@@ -48,6 +48,7 @@ sap_tfi_2026/
├── evidence/ ├── evidence/
│ └── index.md ← catálogo de evidencias │ └── index.md ← catálogo de evidencias
├── prototipo/ ← pantallas navegables y trazabilidad ICONIX ├── prototipo/ ← pantallas navegables y trazabilidad ICONIX
├── trabajo_final/ ← entregas de alumnos por pull request
└── .gitignore └── .gitignore
``` ```
@@ -68,6 +69,24 @@ entrega final.
--- ---
## Procedimiento de entrega final
Antes de rendir, cada alumno debe entregar el trabajo mediante GitHub:
1. Hacer un [fork de este repositorio](https://github.com/cursos-uai/sap_tfi_2026/fork).
2. Subir el trabajo completo dentro de
**`trabajo_final/Apellido_Nombre/`**, reemplazando el ejemplo por los datos
del alumno y sin utilizar espacios.
3. Abrir un **pull request** desde el fork hacia la rama `main` de este
repositorio.
4. Presentar cada actualización posterior mediante un **nuevo pull request**.
Las instrucciones completas y la estructura esperada están en
[`trabajo_final/README.md`](trabajo_final/README.md). No se deben modificar las
carpetas correspondientes a otros alumnos.
---
## Prototipo navegable de fronteras ICONIX ## Prototipo navegable de fronteras ICONIX
El directorio **`prototipo/`** contiene una representación interactiva de las El directorio **`prototipo/`** contiene una representación interactiva de las
+3 -1
View File
@@ -62,7 +62,9 @@ secuencia, clases, patrones y testing estructural. Cada criterio admite una
referencia precisa al borrador —página, sección, tabla, figura, párrafo u otra— referencia precisa al borrador —página, sección, tabla, figura, párrafo u otra—
y el progreso queda guardado localmente en el navegador. Al finalizar se puede y el progreso queda guardado localmente en el navegador. Al finalizar se puede
generar un informe `.md`, descargarlo y preparar el correo de seguimiento para generar un informe `.md`, descargarlo y preparar el correo de seguimiento para
el profesor Alejandro Sartorio. el profesor Alejandro Sartorio. Para la entrega definitiva antes de rendir, la
página también guía el fork del repositorio, la ubicación obligatoria
`trabajo_final/Apellido_Nombre/` y el pull request que registra cada versión.
## Alcance ## Alcance
File diff suppressed because one or more lines are too long
+1
View File
@@ -7,6 +7,7 @@
<section class="toolbar"><label class="search-box"><span>⌕</span><input id="search" type="search" placeholder="Buscar criterio o artefacto…"></label><div class="filters"><button class="active" data-filter="all">Todos</button><button data-filter="pending">Pendientes</button><button data-filter="done">Completos</button></div><button id="expand-all" class="quiet-button">Contraer todo</button><button id="reset-checklist" class="quiet-button danger">Reiniciar</button></section> <section class="toolbar"><label class="search-box"><span>⌕</span><input id="search" type="search" placeholder="Buscar criterio o artefacto…"></label><div class="filters"><button class="active" data-filter="all">Todos</button><button data-filter="pending">Pendientes</button><button data-filter="done">Completos</button></div><button id="expand-all" class="quiet-button">Contraer todo</button><button id="reset-checklist" class="quiet-button danger">Reiniciar</button></section>
<div class="checklist-layout"><aside class="section-index"><div class="step-badge">Paso 2</div><p class="eyebrow">Validar y referenciar</p><nav id="section-index"></nav><div class="evidence-key"><b>Regla de oro</b><p>Para completar un ítem indicá el tipo y la ubicación exacta de la evidencia dentro del borrador.</p></div></aside><section id="checklist-sections" class="checklist-sections" aria-live="polite"></section></div> <div class="checklist-layout"><aside class="section-index"><div class="step-badge">Paso 2</div><p class="eyebrow">Validar y referenciar</p><nav id="section-index"></nav><div class="evidence-key"><b>Regla de oro</b><p>Para completar un ítem indicá el tipo y la ubicación exacta de la evidencia dentro del borrador.</p></div></aside><section id="checklist-sections" class="checklist-sections" aria-live="polite"></section></div>
<section class="submission-card"><div class="submission-copy"><div class="step-badge">Paso 3</div><p class="eyebrow">Preparar el seguimiento</p><h2>Generá y enviá el informe</h2><p>Revisá los datos, descargá el archivo Markdown y enviáselo al profesor para tutoría y evaluación.</p><div id="readiness" class="readiness" role="status"></div></div><div class="submission-actions"><button id="preview-report" class="quiet-button">Vista previa</button><button id="download-report" class="primary-action">Generar archivo .md</button><button id="email-report" class="email-action">Enviar al profesor</button><small>El correo se abrirá dirigido a <b>alejandro.sartorio@gmail.com</b>. Adjuntá el `.md` descargado antes de enviarlo.</small></div></section> <section class="submission-card"><div class="submission-copy"><div class="step-badge">Paso 3</div><p class="eyebrow">Preparar el seguimiento</p><h2>Generá y enviá el informe</h2><p>Revisá los datos, descargá el archivo Markdown y enviáselo al profesor para tutoría y evaluación.</p><div id="readiness" class="readiness" role="status"></div></div><div class="submission-actions"><button id="preview-report" class="quiet-button">Vista previa</button><button id="download-report" class="primary-action">Generar archivo .md</button><button id="email-report" class="email-action">Enviar al profesor</button><small>El correo se abrirá dirigido a <b>alejandro.sartorio@gmail.com</b>. Adjuntá el `.md` descargado antes de enviarlo.</small></div></section>
<section class="final-delivery" aria-labelledby="delivery-title"><header><div class="step-badge">Paso 4 · Entrega final</div><p class="eyebrow">Antes de rendir</p><h2 id="delivery-title">Publicá tu trabajo mediante un pull request</h2><p>La entrega oficial queda registrada en GitHub. Repetí el pull request cada vez que presentes una actualización.</p></header><ol class="delivery-steps"><li><span>1</span><div><h3>Hacé un fork del repositorio</h3><p>Creá una copia en tu cuenta desde <a href="https://github.com/cursos-uai/sap_tfi_2026/fork" target="_blank" rel="noreferrer">cursos-uai/sap_tfi_2026 ↗</a>.</p><label><input id="delivery-fork" type="checkbox"> Ya creé mi fork</label></div></li><li><span>2</span><div><h3>Subí el trabajo en la ubicación obligatoria</h3><p>Usá exactamente <code>trabajo_final/Apellido_Nombre/</code>, reemplazando el ejemplo por tus datos y sin espacios.</p><label>Nombre de la carpeta<input id="delivery-folder" placeholder="Ej.: Sartorio_Alejandro"></label></div></li><li><span>3</span><div><h3>Abrí un pull request hacia este repositorio</h3><p>En el título indicá apellido, nombre y versión. Para cada actualización, agregá cambios a tu fork y abrí un nuevo PR.</p><label>Link del pull request<input id="delivery-pr" type="url" placeholder="https://github.com/cursos-uai/sap_tfi_2026/pull/…"></label></div></li></ol><div id="delivery-status" class="delivery-status" role="status"></div></section>
<dialog id="report-dialog"><div class="dialog-head"><div><p class="eyebrow">Vista previa</p><h2>Informe de seguimiento</h2></div><button id="close-report" aria-label="Cerrar">×</button></div><pre id="report-preview"></pre></dialog> <dialog id="report-dialog"><div class="dialog-head"><div><p class="eyebrow">Vista previa</p><h2>Informe de seguimiento</h2></div><button id="close-report" aria-label="Cerrar">×</button></div><pre id="report-preview"></pre></dialog>
<section class="traceability-card"><div><p class="eyebrow">Chequeo transversal</p><h2>Cadena mínima de trazabilidad</h2><p>Elegí un caso de uso central y seguí la misma historia de extremo a extremo.</p></div><div class="trace-chain"><span>REQ</span><i>→</i><span>CU</span><i>→</i><span>UI</span><i>→</i><span>ROB</span><i>→</i><span>SEC</span><i>→</i><span>CLA</span><i>→</i><span>TEST</span></div></section> <section class="traceability-card"><div><p class="eyebrow">Chequeo transversal</p><h2>Cadena mínima de trazabilidad</h2><p>Elegí un caso de uso central y seguí la misma historia de extremo a extremo.</p></div><div class="trace-chain"><span>REQ</span><i>→</i><span>CU</span><i>→</i><span>UI</span><i>→</i><span>ROB</span><i>→</i><span>SEC</span><i>→</i><span>CLA</span><i>→</i><span>TEST</span></div></section>
<footer class="checklist-sources"><b>Fuentes:</b><a href="https://docs.google.com/document/d/1oThnR9euP2YW4K94A3oAoE3pvHdeDyNShRdwWDY-Nmk/edit?usp=sharing" target="_blank" rel="noreferrer">Temas técnicos ↗</a><a href="https://docs.google.com/document/d/1_ZjiF3pUANt0-bm4V6Xph6hdJuHCnxbp/edit?usp=sharing" target="_blank" rel="noreferrer">Apunte ICONIX ↗</a><a href="https://www.fceia.unr.edu.ar/ingsoft/testing-intro-a.pdf" target="_blank" rel="noreferrer">Testing ↗</a><a href="https://www.fceia.unr.edu.ar/ingsoft/testing-estruct-a.pdf" target="_blank" rel="noreferrer">Testing estructural ↗</a><a href="https://www.fceia.unr.edu.ar/ingsoft/p-testing.pdf" target="_blank" rel="noreferrer">Práctica ↗</a></footer> <footer class="checklist-sources"><b>Fuentes:</b><a href="https://docs.google.com/document/d/1oThnR9euP2YW4K94A3oAoE3pvHdeDyNShRdwWDY-Nmk/edit?usp=sharing" target="_blank" rel="noreferrer">Temas técnicos ↗</a><a href="https://docs.google.com/document/d/1_ZjiF3pUANt0-bm4V6Xph6hdJuHCnxbp/edit?usp=sharing" target="_blank" rel="noreferrer">Apunte ICONIX ↗</a><a href="https://www.fceia.unr.edu.ar/ingsoft/testing-intro-a.pdf" target="_blank" rel="noreferrer">Testing ↗</a><a href="https://www.fceia.unr.edu.ar/ingsoft/testing-estruct-a.pdf" target="_blank" rel="noreferrer">Testing estructural ↗</a><a href="https://www.fceia.unr.edu.ar/ingsoft/p-testing.pdf" target="_blank" rel="noreferrer">Práctica ↗</a></footer>
+5 -4
View File
@@ -23,10 +23,11 @@ function render(){root.innerHTML=S.map(([sid,title,sub,a],n)=>{const done=a.filt
function row([id,t,h]){const x=get(id),invalid=x.done&&(!x.type||!x.location.trim());return`<div class="check-item ${x.done?'done':''} ${invalid?'invalid':''}" data-id="${id}"><input id="${id}" type="checkbox" ${x.done?'checked':''}><div class="item-copy"><label for="${id}">${t}</label><p>${h}</p><div class="evidence-fields"><select class="evidence-type" aria-label="Tipo de referencia para ${t}"><option value="">Tipo de referencia…</option>${types.map(v=>`<option ${x.type===v?'selected':''}>${v}</option>`).join('')}</select><input class="evidence-location" aria-label="Ubicación para ${t}" placeholder="Ej.: pág. 12, sección 3.2, figura D-ROB-01" value="${esc(x.location)}"></div><small class="reference-help">Indicá dónde puede encontrar el profesor la evidencia dentro del borrador.</small></div></div>`} function row([id,t,h]){const x=get(id),invalid=x.done&&(!x.type||!x.location.trim());return`<div class="check-item ${x.done?'done':''} ${invalid?'invalid':''}" data-id="${id}"><input id="${id}" type="checkbox" ${x.done?'checked':''}><div class="item-copy"><label for="${id}">${t}</label><p>${h}</p><div class="evidence-fields"><select class="evidence-type" aria-label="Tipo de referencia para ${t}"><option value="">Tipo de referencia…</option>${types.map(v=>`<option ${x.type===v?'selected':''}>${v}</option>`).join('')}</select><input class="evidence-location" aria-label="Ubicación para ${t}" placeholder="Ej.: pág. 12, sección 3.2, figura D-ROB-01" value="${esc(x.location)}"></div><small class="reference-help">Indicá dónde puede encontrar el profesor la evidencia dentro del borrador.</small></div></div>`}
function bind(){document.querySelectorAll('.section-head').forEach(b=>b.onclick=()=>{const c=b.closest('.check-section');c.classList.toggle('open');b.setAttribute('aria-expanded',c.classList.contains('open'))});document.querySelectorAll('.check-item').forEach(r=>{const id=r.dataset.id,c=r.querySelector('[type=checkbox]'),t=r.querySelector('.evidence-type'),l=r.querySelector('.evidence-location');const update=()=>{st[id]={done:c.checked,type:t.value,location:l.value};save();total()};c.onchange=()=>{update();render()};t.onchange=update;l.oninput=update})} function bind(){document.querySelectorAll('.section-head').forEach(b=>b.onclick=()=>{const c=b.closest('.check-section');c.classList.toggle('open');b.setAttribute('aria-expanded',c.classList.contains('open'))});document.querySelectorAll('.check-item').forEach(r=>{const id=r.dataset.id,c=r.querySelector('[type=checkbox]'),t=r.querySelector('.evidence-type'),l=r.querySelector('.evidence-location');const update=()=>{st[id]={done:c.checked,type:t.value,location:l.value};save();total()};c.onchange=()=>{update();render()};t.onchange=update;l.oninput=update})}
function total(){const done=items.filter(([id])=>get(id).done).length,valid=items.filter(([id])=>{const x=get(id);return x.done&&x.type&&x.location.trim()}).length,missing=done-valid;document.querySelector('#total-percent').textContent=`${Math.round(valid/items.length*100)}%`;document.querySelector('#total-copy').textContent=`${valid} de ${items.length} referenciados`;const box=document.querySelector('#readiness');box.className=`readiness ${missing?'warning':valid?'ready':''}`;box.textContent=missing?`${missing} ítem${missing===1?'':'s'} marcado${missing===1?'':'s'} sin referencia completa.`:valid?`El informe tiene ${valid} evidencias listas para compartir.`:'Completá criterios para construir el informe.'} function total(){const done=items.filter(([id])=>get(id).done).length,valid=items.filter(([id])=>{const x=get(id);return x.done&&x.type&&x.location.trim()}).length,missing=done-valid;document.querySelector('#total-percent').textContent=`${Math.round(valid/items.length*100)}%`;document.querySelector('#total-copy').textContent=`${valid} de ${items.length} referenciados`;const box=document.querySelector('#readiness');box.className=`readiness ${missing?'warning':valid?'ready':''}`;box.textContent=missing?`${missing} ítem${missing===1?'':'s'} marcado${missing===1?'':'s'} sin referencia completa.`:valid?`El informe tiene ${valid} evidencias listas para compartir.`:'Completá criterios para construir el informe.'}
function syncMeta(){meta={student:document.querySelector('#student-name').value.trim(),group:document.querySelector('#course-group').value.trim(),draft:document.querySelector('#draft-link').value.trim()};save()} function syncMeta(){meta={student:document.querySelector('#student-name').value.trim(),group:document.querySelector('#course-group').value.trim(),draft:document.querySelector('#draft-link').value.trim(),fork:document.querySelector('#delivery-fork').checked,folder:document.querySelector('#delivery-folder').value.trim(),pr:document.querySelector('#delivery-pr').value.trim()};save();deliveryStatus()}
function report(){syncMeta();const done=items.filter(([id])=>get(id).done);let out=`# Informe de seguimiento del Trabajo Práctico\n\n- **Alumno/a o equipo:** ${md(meta.student)||'Sin completar'}\n- **Comisión:** ${md(meta.group)||'Sin completar'}\n- **Documento borrador:** ${meta.draft?`[Abrir borrador](${meta.draft})`:'Sin completar'}\n- **Fecha de generación:** ${new Date().toLocaleDateString('es-AR')}\n- **Avance referenciado:** ${done.filter(([id])=>get(id).type&&get(id).location.trim()).length}/${items.length} criterios\n\n`;S.forEach(([sid,title,,a])=>{out+=`## ${title}\n\n| Estado | Criterio | Tipo de referencia | Ubicación en el documento |\n|---|---|---|---|\n`;a.forEach(([t],i)=>{const x=get(`${sid}-${i}`);out+=`| ${x.done?'✅ Cumple':'⬜ Pendiente'} | ${md(t)} | ${md(x.type)||'—'} | ${md(x.location)||'—'} |\n`});out+='\n'});out+='---\n\nInforme generado con la checklist interactiva SAP-TFI-2026.\n';return out} function report(){syncMeta();const done=items.filter(([id])=>get(id).done);let out=`# Informe de seguimiento del Trabajo Práctico\n\n- **Alumno/a o equipo:** ${md(meta.student)||'Sin completar'}\n- **Comisión:** ${md(meta.group)||'Sin completar'}\n- **Documento borrador:** ${meta.draft?`[Abrir borrador](${meta.draft})`:'Sin completar'}\n- **Fecha de generación:** ${new Date().toLocaleDateString('es-AR')}\n- **Avance referenciado:** ${done.filter(([id])=>get(id).type&&get(id).location.trim()).length}/${items.length} criterios\n\n`;S.forEach(([sid,title,,a])=>{out+=`## ${title}\n\n| Estado | Criterio | Tipo de referencia | Ubicación en el documento |\n|---|---|---|---|\n`;a.forEach(([t],i)=>{const x=get(`${sid}-${i}`);out+=`| ${x.done?'✅ Cumple':'⬜ Pendiente'} | ${md(t)} | ${md(x.type)||'—'} | ${md(x.location)||'—'} |\n`});out+='\n'});out+=`## Entrega final por GitHub\n\n- **Fork creado:** ${meta.fork?'Sí':'Pendiente'}\n- **Carpeta de entrega:** ${meta.folder?`\`trabajo_final/${md(meta.folder)}/\``:'Pendiente'}\n- **Pull request:** ${meta.pr?`[Abrir pull request](${meta.pr})`:'Pendiente'}\n- **Política de actualización:** abrir un nuevo pull request por cada actualización de la entrega.\n\n---\n\nInforme generado con la checklist interactiva SAP-TFI-2026.\n`;return out}
function validateForShare(){syncMeta();const errors=[];if(!meta.student)errors.push('el nombre del alumno o equipo');if(!meta.draft||!/^https?:\/\//i.test(meta.draft))errors.push('un link válido al borrador');const incomplete=items.filter(([id])=>{const x=get(id);return x.done&&(!x.type||!x.location.trim())}).length;if(incomplete)errors.push(`la referencia de ${incomplete} ítem${incomplete===1?'':'s'} marcado${incomplete===1?'':'s'}`);if(errors.length){alert(`Antes de compartir, completá ${errors.join(', ')}.`);return false}return true} function validateForShare(){syncMeta();const errors=[];if(!meta.student)errors.push('el nombre del alumno o equipo');if(!meta.draft||!/^https?:\/\//i.test(meta.draft))errors.push('un link válido al borrador');const incomplete=items.filter(([id])=>{const x=get(id);return x.done&&(!x.type||!x.location.trim())}).length;if(incomplete)errors.push(`la referencia de ${incomplete} ítem${incomplete===1?'':'s'} marcado${incomplete===1?'':'s'}`);if(errors.length){alert(`Antes de compartir, completá ${errors.join(', ')}.`);return false}return true}
function download(){if(!validateForShare())return false;const blob=new Blob([report()],{type:'text/markdown;charset=utf-8'}),url=URL.createObjectURL(blob),a=document.createElement('a'),slug=(meta.student||'alumno').toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g,'').replace(/[^a-z0-9]+/g,'-').replace(/^-|-$/g,'');a.href=url;a.download=`seguimiento-tp-${slug||'alumno'}.md`;a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);return true} function download(){if(!validateForShare())return false;const blob=new Blob([report()],{type:'text/markdown;charset=utf-8'}),url=URL.createObjectURL(blob),a=document.createElement('a'),slug=(meta.student||'alumno').toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g,'').replace(/[^a-z0-9]+/g,'-').replace(/^-|-$/g,'');a.href=url;a.download=`seguimiento-tp-${slug||'alumno'}.md`;a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);return true}
['student-name','course-group','draft-link'].forEach(id=>{const el=document.querySelector(`#${id}`),key=id==='student-name'?'student':id==='course-group'?'group':'draft';el.value=meta[key]||'';el.oninput=syncMeta}); ['student-name','course-group','draft-link'].forEach(id=>{const el=document.querySelector(`#${id}`),key=id==='student-name'?'student':id==='course-group'?'group':'draft';el.value=meta[key]||'';el.oninput=syncMeta});const fork=document.querySelector('#delivery-fork'),folder=document.querySelector('#delivery-folder'),pr=document.querySelector('#delivery-pr');fork.checked=!!meta.fork;folder.value=meta.folder||'';pr.value=meta.pr||'';fork.onchange=syncMeta;folder.oninput=syncMeta;pr.oninput=syncMeta;
function deliveryStatus(){const box=document.querySelector('#delivery-status'),folderOk=/^[A-Za-zÀ-ÿ'’-]+_[A-Za-zÀ-ÿ'’-]+$/.test(meta.folder||''),prOk=/^https:\/\/github\.com\/[^/]+\/sap_tfi_2026\/pull\/\d+/i.test(meta.pr||'');const count=[meta.fork,folderOk,prOk].filter(Boolean).length;box.className=`delivery-status ${count===3?'ready':''}`;box.textContent=count===3?'Entrega final documentada: fork, carpeta y pull request completos.':`${count}/3 pasos documentados. La carpeta debe usar Apellido_Nombre y el link debe corresponder a un pull request.`}
document.querySelector('#search').oninput=e=>{query=e.target.value.trim().toLowerCase();render()};document.querySelectorAll('[data-filter]').forEach(b=>b.onclick=()=>{filter=b.dataset.filter;document.querySelectorAll('[data-filter]').forEach(x=>x.classList.toggle('active',x===b));render()});document.querySelector('#expand-all').onclick=e=>{const a=[...document.querySelectorAll('.check-section')],open=a.some(c=>!c.classList.contains('open'));a.forEach(c=>c.classList.toggle('open',open));e.target.textContent=open?'Contraer todo':'Expandir todo'};document.querySelector('#reset-checklist').onclick=()=>{if(confirm('¿Borrar todos los datos, tildes y referencias?')){st={};meta={};localStorage.removeItem(K);localStorage.removeItem(META);location.reload()}}; document.querySelector('#search').oninput=e=>{query=e.target.value.trim().toLowerCase();render()};document.querySelectorAll('[data-filter]').forEach(b=>b.onclick=()=>{filter=b.dataset.filter;document.querySelectorAll('[data-filter]').forEach(x=>x.classList.toggle('active',x===b));render()});document.querySelector('#expand-all').onclick=e=>{const a=[...document.querySelectorAll('.check-section')],open=a.some(c=>!c.classList.contains('open'));a.forEach(c=>c.classList.toggle('open',open));e.target.textContent=open?'Contraer todo':'Expandir todo'};document.querySelector('#reset-checklist').onclick=()=>{if(confirm('¿Borrar todos los datos, tildes y referencias?')){st={};meta={};localStorage.removeItem(K);localStorage.removeItem(META);location.reload()}};
const dialog=document.querySelector('#report-dialog');document.querySelector('#preview-report').onclick=()=>{document.querySelector('#report-preview').textContent=report();dialog.showModal()};document.querySelector('#close-report').onclick=()=>dialog.close();document.querySelector('#download-report').onclick=download;document.querySelector('#email-report').onclick=()=>{if(!download())return;const subject=encodeURIComponent(`Seguimiento TP SAP-TFI-2026 · ${meta.student}`),body=encodeURIComponent(`Profesor Alejandro Sartorio:\n\nAdjunto el informe Markdown de seguimiento de nuestro Trabajo Práctico.\n\nDocumento borrador: ${meta.draft}\n\nAlumno/a o equipo: ${meta.student}\nComisión: ${meta.group||'Sin completar'}\n\nImportante: adjuntar el archivo .md que acaba de descargarse antes de enviar este correo.`);window.location.href=`mailto:alejandro.sartorio@gmail.com?subject=${subject}&body=${body}`};render(); const dialog=document.querySelector('#report-dialog');document.querySelector('#preview-report').onclick=()=>{document.querySelector('#report-preview').textContent=report();dialog.showModal()};document.querySelector('#close-report').onclick=()=>dialog.close();document.querySelector('#download-report').onclick=download;document.querySelector('#email-report').onclick=()=>{if(!download())return;const subject=encodeURIComponent(`Seguimiento TP SAP-TFI-2026 · ${meta.student}`),body=encodeURIComponent(`Profesor Alejandro Sartorio:\n\nAdjunto el informe Markdown de seguimiento de nuestro Trabajo Práctico.\n\nDocumento borrador: ${meta.draft}\n\nAlumno/a o equipo: ${meta.student}\nComisión: ${meta.group||'Sin completar'}\n\nImportante: adjuntar el archivo .md que acaba de descargarse antes de enviar este correo.`);window.location.href=`mailto:alejandro.sartorio@gmail.com?subject=${subject}&body=${body}`};deliveryStatus();render();
+39
View File
@@ -0,0 +1,39 @@
# Entregas finales de alumnos
Cada alumno debe entregar su Trabajo Final dentro de una carpeta propia con
este formato:
```text
trabajo_final/
└── Apellido_Nombre/
├── README.md
└── ...archivos del trabajo...
```
## Procedimiento obligatorio
1. Hacer un **fork** de
[cursos-uai/sap_tfi_2026](https://github.com/cursos-uai/sap_tfi_2026/fork)
en la cuenta personal de GitHub.
2. Crear una rama en el fork para la entrega.
3. Crear `trabajo_final/Apellido_Nombre/`, sin espacios, y colocar allí todos
los archivos. No modificar carpetas de otros alumnos.
4. Agregar dentro de la carpeta personal un `README.md` con nombre, comisión,
link al documento borrador o final y una breve descripción de la versión.
5. Hacer commit y push de la rama al fork.
6. Abrir un **pull request** hacia la rama `main` de este repositorio.
## Actualizaciones
Cada actualización de una entrega se presenta mediante un **nuevo pull
request**. El título recomendado es:
```text
Entrega TP — Apellido Nombre — versión N
```
Antes de abrirlo, sincronizar el fork con `main`, crear una nueva rama, cambiar
únicamente la carpeta personal y describir en el PR qué se actualizó.
> No subir credenciales, contraseñas, tokens, datos personales sensibles,
> bases de datos productivas ni archivos que no correspondan al TP.