Files
dtic-DIIAA/docs/ambito/dtic-NOTAS/app/app.js
T
Ricardo MonlaandClaude Opus 4.6 85645ce0b8 feat(A08): Ámbito dtic-NOTAS creado - Sistema web de notas/informes
Nuevo ámbito A08 para gestión de notas e informes formales:

Arquitectura:
- Separación contenido (archivos .md) de presentación (web HTML)
- Plantillas configurables para diferentes tipos de notas
- Vista previa con membrete institucional UTN-FRLR
- Impresión/PDF via window.print() con CSS @media print

Archivos creados:
- docs/ambito/dtic-NOTAS/A08_dtic-NOTAS.md (manifiesto)
- docs/ambito/dtic-NOTAS/A08.P001_Sistema-Web-Notas.md (plan)
- docs/ambito/dtic-NOTAS/app/index.html (interfaz)
- docs/ambito/dtic-NOTAS/app/styles.css (estilos institucionales)
- docs/ambito/dtic-NOTAS/app/app.js (lógica + marked.js CDN)
- docs/ambito/dtic-NOTAS/plantillas/nota-simple.md
- docs/ambito/dtic-NOTAS/contenido/2026/ejemplo-nota.md

Migración:
- dtic-NOTAs/ movido a docs/ambito/dtic-NOTAS/dtic-NOTAs/
- Histórico 2019-2025 preservado en .Hist/
- Convención de nombres documentada: Nota-<AÑO><NUMERO>_<Asunto>.<ext>

Uso:
1. Abrir docs/ambito/dtic-NOTAS/app/index.html en navegador
2. Seleccionar plantilla o cargar archivo .md
3. Completar datos de nota
4. Generar vista previa e imprimir

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 19:18:56 -03:00

319 lines
8.3 KiB
JavaScript

/**
* Generador de Notas - DTIC UTN-FRLR
* Lógica de la aplicación web
*/
// Estado de la aplicación
let estado = {
plantillaCargada: null,
contenidoCargado: null,
datosNota: {}
};
// Inicialización
document.addEventListener('DOMContentLoaded', () => {
// Establecer fecha actual por defecto
document.getElementById('fecha').valueAsDate = new Date();
// Cargar último número disponible (simulado)
document.getElementById('numero').placeholder = 'Ej: ' + generarNumeroSugerido();
});
/**
* Genera un número sugerido basado en la fecha
* Formato: AAMM (ej: 2604 para abril 2026)
*/
function generarNumeroSugerido() {
const fecha = new Date();
const año = fecha.getFullYear() % 100;
const mes = String(fecha.getMonth() + 1).padStart(2, '0');
return `${año}${mes}`;
}
/**
* Carga la plantilla seleccionada
*/
function cargarPlantilla() {
const plantilla = document.getElementById('plantilla').value;
if (!plantilla) {
alert('Por favor seleccioná una plantilla');
return;
}
// Plantillas embebidas
const plantillas = {
'nota-simple': `---
tipo: nota-simple
numero: ${document.getElementById('numero').value || 'XXXX'}
fecha: ${document.getElementById('fecha').value || '____'}
destinatario: [Nombre del Destinatario]
remitente: DTIC - UTN FRLR
asunto: [Asunto de la nota]
---
# Nota Simple
Estimado/a [Nombre]:
Por medio de la presente, me dirijo a usted para [propósito de la nota].
[Cuerpo principal de la nota - desarrollar el tema]
Sin otro particular, saludo a usted atentamente.
`,
'informe-tecnico': `---
tipo: informe-tecnico
numero: ${document.getElementById('numero').value || 'XXXX'}
fecha: ${document.getElementById('fecha').value || '____'}
destinatario: [Nombre del Destinatario]
remitente: DTIC - UTN FRLR
asunto: Informe Técnico sobre [tema]
---
# Informe Técnico
## 1. Objeto del Informe
El presente informe tiene por objeto [describir el propósito].
## 2. Antecedentes
[Describir contexto y situación previa]
## 3. Análisis Técnico
[Desarrollar análisis detallado]
## 4. Conclusiones
[Conclusiones y recomendaciones]
## 5. Anexos
- Anexo A: [Descripción]
- Anexo B: [Descripción]
`,
'memorando': `---
tipo: memorando
numero: ${document.getElementById('numero').value || 'XXXX'}
fecha: ${document.getElementById('fecha').value || '____'}
destinatario: [Personal de DTIC / Nombre]
remitente: Dirección DTIC
asunto: [Asunto del memorando]
---
# Memorando
**PARA:** [Destinatario]
**DE:** [Remitente]
**FECHA:** [Fecha]
**ASUNTO:** [Asunto]
---
[Cuerpo del memorando]
Se comunica a todo el personal que [contenido].
Es importante destacar que [puntos clave].
Quedan a disposición para cualquier consulta.
`,
'solicitud': `---
tipo: solicitud
numero: ${document.getElementById('numero').value || 'XXXX'}
fecha: ${document.getElementById('fecha').value || '____'}
destinatario: [Autoridad/Área]
remitente: DTIC - UTN FRLR
asunto: Solicitud de [qué se solicita]
---
# Nota de Solicitud
Por medio de la presente, me dirijo a usted con el fin de solicitar [describir lo que se solicita].
**Fundamentación:**
[Explicar razones y necesidad de lo solicitado]
**Especificaciones:**
- [Ítem 1]
- [Ítem 2]
- [Ítem 3]
Agradeciendo de antemano su atención, saludo a usted atentamente.
`
};
const contenido = plantillas[plantilla];
document.getElementById('editorTexto').value = contenido;
estado.plantillaCargada = plantilla;
// Extraer metadatos del frontmatter
extraerMetadatos(contenido);
alert('Plantilla "' + plantilla + '" cargada. Editá el contenido y generá la vista previa.');
}
/**
* Carga contenido desde archivo .md
*/
function cargarContenido() {
const input = document.getElementById('contenido');
if (!input.files || !input.files[0]) {
alert('Por favor seleccioná un archivo .md');
return;
}
const archivo = input.files[0];
const lector = new FileReader();
lector.onload = (e) => {
document.getElementById('editorTexto').value = e.target.result;
estado.contenidoCargado = archivo.name;
extraerMetadatos(e.target.result);
alert('Contenido cargado desde: ' + archivo.name);
};
lector.readAsText(archivo);
}
/**
* Extrae metadatos del frontmatter (YAML entre ---)
*/
function extraerMetadatos(contenido) {
const match = contenido.match(/^---\n([\s\S]*?)\n---/);
if (match) {
const frontmatter = match[1];
// Extraer campos individuales
const campos = {
numero: frontmatter.match(/numero:\s*(.+)/)?.[1]?.trim(),
fecha: frontmatter.match(/fecha:\s*(.+)/)?.[1]?.trim(),
destinatario: frontmatter.match(/destinatario:\s*(.+)/)?.[1]?.trim(),
asunto: frontmatter.match(/asunto:\s*(.+)/)?.[1]?.trim()
};
// Completar formulario
if (campos.numero && campos.numero !== 'XXXX') {
document.getElementById('numero').value = campos.numero;
}
if (campos.fecha && campos.fecha !== '____') {
document.getElementById('fecha').value = campos.fecha;
}
if (campos.destinatario && !campos.destinatario.includes('[')) {
document.getElementById('destinatario').value = campos.destinatario;
}
if (campos.asunto && !campos.asunto.includes('[')) {
document.getElementById('asunto').value = campos.asunto;
}
estado.datosNota = { ...estado.datosNota, ...campos };
}
}
/**
* Genera la vista previa del documento
*/
function generarVistaPrevia() {
const contenido = document.getElementById('editorTexto').value;
// Obtener datos del formulario
const datos = {
numero: document.getElementById('numero').value,
fecha: formatearFecha(document.getElementById('fecha').value),
destinatario: document.getElementById('destinatario').value,
asunto: document.getElementById('asunto').value
};
// Separar frontmatter del cuerpo
const cuerpo = contenido.replace(/^---\n[\s\S]*?\n---\n/, '');
// Renderizar markdown a HTML
const htmlCuerpo = marked.parse(cuerpo);
// Construir documento
const template = document.getElementById('templateNota');
const clone = template.content.cloneNode(true);
// Completar datos
clone.querySelector('.campo-numero').textContent = datos.numero || '____';
clone.querySelector('.campo-fecha').textContent = datos.fecha || '____';
clone.querySelector('.campo-destinatario').textContent = datos.destinatario || '____';
clone.querySelector('.campo-asunto').textContent = datos.asunto || '____';
clone.querySelector('.cuerpo').innerHTML = htmlCuerpo;
// Actualizar vista previa
const preview = document.getElementById('vistaPrevia');
preview.innerHTML = '';
preview.appendChild(clone);
// Scroll a la vista previa
preview.scrollIntoView({ behavior: 'smooth' });
}
/**
* Formatea fecha de YYYY-MM-DD a DD/MM/YYYY
*/
function formatearFecha(fechaISO) {
if (!fechaISO) return '____';
const [año, mes, dia] = fechaISO.split('-');
return `${dia}/${mes}/${año}`;
}
/**
* Imprime o genera PDF del documento
*/
function imprimir() {
const vistaPrevia = document.getElementById('vistaPrevia');
if (!vistaPrevia.innerHTML.trim() || vistaPrevia.querySelector('.placeholder')) {
alert('Por favor generá primero la vista previa');
return;
}
// Crear ventana de impresión
const contenido = vistaPrevia.innerHTML;
const ventana = window.open('', '_blank');
ventana.document.write(`
<!DOCTYPE html>
<html>
<head>
<title>Nota ${document.getElementById('numero').value || '____'}</title>
<style>
${document.querySelector('style').innerHTML}
body { background: white; }
.sidebar, .editor { display: none; }
.container { display: block; padding: 0; }
.preview { position: absolute; width: 100%; }
</style>
</head>
<body>
${contenido}
<script>
window.onload = () => {
window.print();
window.onafterprint = () => window.close();
};
</script>
</body>
</html>
`);
ventana.document.close();
}