feat: add complete sidebar content to match original React CV
Comprehensive update to achieve feature parity with old React implementation. ## Data Layer (Backend) **Updated Go Models** (internal/models/cv.go): - Added Course struct (title, institution, location, date, duration, description) - Added Reference struct (title, URL, type) - Added Language.Detail field for proficiency descriptions - Added CV.Courses and CV.References arrays **Complete Data Population** (data/cv-es.json): - Added 6 NEW skill categories (42 items): * Lenguajes de Programación (11 items: Java, Groovy, PHP, XML, XSLT, ActionScript, Shell, C, C++) * Frameworks PHP (4 items: Yii, Zend, WordPress API, Joomla API) * Frameworks Java (8 items: Play!, Struts, Spring, Hibernate, Ibatis, Magnolia CMS, XWiki, TESEO) * Servidores de Aplicaciones (9 items: Apache, WAMP, MAMP, Tomcat, JBoss, Resin, Jetty, Websphere, Weblogic) * CMS y Entornos (6 items: Joomla, WordPress, RapidWeaver, Servoy, WebRatio, Magnolia) * Herramientas de Diseño (4 items: Corel, Photoshop, Illustrator, GIMP) - Updated existing categories with missing items: * Ecosistema JavaScript: +Redux, Flux, Gulp, Grunt * Desarrollo Web: +JSP, PHP, Handlebars, Moustache, Velocity, Freemarker, jQuery, mooTools, DOM, Ajax, SEO, WebServices * Bases de Datos: +Hypersonic, Dominio de SQL * Soft Skills: +5 team management items - Added Catalan language (Comprensión, Level 2) - Added detail field to all languages (oral/written breakdown) - Added 4 courses: * Servoy World 2011 (Amsterdam, 3 días) * Formador de Formadores (FOREM, 150 horas) * Windows 2003 Server (Cámara de Comercio, 80 horas) * I Jornada Extremeña (Universidad, 3 días) - Added 8 references: * Recommendation letters, portfolios, profiles, CVs - Fixed driver's license: Tipo C → Tipo B ## Presentation Layer (Frontend) **Template Updates** (templates/cv-content.html, templates/index.html): - Skills section: Now renders ALL 13 categories dynamically - Languages section: Added detail field display - NEW Courses section: Full course details with institutions - NEW References section: Clickable links with security attributes - NEW Other section: Driver's license display - Responsive grid layout maintained - Conditional rendering (sections only show if data exists) **Styling** (static/css/main.css): - Added .course-item, .course-desc styles - Added .reference-item, .ref-type styles - Added .language-detail styles - Maintained consistent sidebar section styling ## Impact **Before**: 7 skill categories, 3 languages, 0 courses, 0 references **After**: 13 skill categories (+6), 4 languages (+1), 4 courses (+4), 8 references (+8) **Total**: 90+ new data points added Sidebar now matches original React CV feature-for-feature.
This commit is contained in:
+193
-7
@@ -333,14 +333,35 @@
|
||||
"APIs OpenAI y Anthropic"
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Lenguajes de Programación",
|
||||
"proficiency": 4,
|
||||
"items": [
|
||||
"JavaScript (ES6+)",
|
||||
"Go (Golang)",
|
||||
"Java",
|
||||
"Groovy",
|
||||
"PHP",
|
||||
"XML",
|
||||
"XSLT",
|
||||
"Action Script",
|
||||
"Shell Scripts (Unix)",
|
||||
"C",
|
||||
"C++"
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Ecosistema JavaScript",
|
||||
"proficiency": 5,
|
||||
"items": [
|
||||
"JavaScript Avanzado (ES6+)",
|
||||
"React y Ecosistema React",
|
||||
"Redux",
|
||||
"Flux",
|
||||
"Node.js y Express",
|
||||
"Webpack, Vite, Herramientas de Build Modernas"
|
||||
"Webpack, Vite",
|
||||
"Gulp",
|
||||
"Grunt"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -350,7 +371,43 @@
|
||||
"HTML5, CSS3, Web Semántica",
|
||||
"Diseño y Desarrollo de APIs REST",
|
||||
"LESS, SASS, Preprocesadores CSS",
|
||||
"Diseño Responsive y Mobile-First"
|
||||
"Diseño Responsive y Mobile-First",
|
||||
"JSP",
|
||||
"PHP",
|
||||
"Handlebars",
|
||||
"Moustache",
|
||||
"Velocity",
|
||||
"Freemarker",
|
||||
"jQuery",
|
||||
"mooTools",
|
||||
"DOM",
|
||||
"Ajax",
|
||||
"SEO",
|
||||
"WebServices"
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Frameworks PHP",
|
||||
"proficiency": 4,
|
||||
"items": [
|
||||
"Yii Framework",
|
||||
"Zend Framework",
|
||||
"API de Wordpress",
|
||||
"API de Joomla"
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Frameworks Java",
|
||||
"proficiency": 4,
|
||||
"items": [
|
||||
"Play! Framework",
|
||||
"Struts",
|
||||
"Spring Framework",
|
||||
"Hibernate",
|
||||
"Ibatis",
|
||||
"Magnolia CMS",
|
||||
"XWiki",
|
||||
"Framework TESEO"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -364,6 +421,33 @@
|
||||
"PHP"
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Servidores de Aplicaciones",
|
||||
"proficiency": 4,
|
||||
"items": [
|
||||
"Apache",
|
||||
"WAMP",
|
||||
"MAMP",
|
||||
"Tomcat",
|
||||
"JBoss",
|
||||
"Resin",
|
||||
"Jetty",
|
||||
"Websphere",
|
||||
"Weblogic"
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "CMS y Entornos de Producción Web",
|
||||
"proficiency": 4,
|
||||
"items": [
|
||||
"Joomla",
|
||||
"Wordpress",
|
||||
"RapidWeaver",
|
||||
"Servoy",
|
||||
"WebRatio",
|
||||
"Magnolia CMS"
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Bases de Datos",
|
||||
"proficiency": 4,
|
||||
@@ -372,6 +456,8 @@
|
||||
"MySQL",
|
||||
"Oracle",
|
||||
"MongoDB (NoSQL)",
|
||||
"Hypersonic",
|
||||
"Dominio de SQL",
|
||||
"Diseño y Optimización de Bases de Datos"
|
||||
]
|
||||
},
|
||||
@@ -394,6 +480,16 @@
|
||||
"Testing Automatizado",
|
||||
"Metodologías Ágiles"
|
||||
]
|
||||
},
|
||||
{
|
||||
"category": "Herramientas de Diseño",
|
||||
"proficiency": 3,
|
||||
"items": [
|
||||
"Corel Draw",
|
||||
"Adobe PhotoShop",
|
||||
"Adobe Illustrator",
|
||||
"GIMP"
|
||||
]
|
||||
}
|
||||
],
|
||||
"soft_skills": [
|
||||
@@ -405,24 +501,38 @@
|
||||
"Formación y Mentoría",
|
||||
"Gestión de Relaciones con Clientes",
|
||||
"Flexibilidad y Adaptabilidad",
|
||||
"Marketing y Gestión de Recursos"
|
||||
"Marketing y Gestión de Recursos",
|
||||
"Preparación y puesta en marcha de proyectos",
|
||||
"Comunicación fluida con los clientes",
|
||||
"Contratación de personal",
|
||||
"Gestión de tareas",
|
||||
"Reportes mensuales"
|
||||
]
|
||||
},
|
||||
"languages": [
|
||||
{
|
||||
"language": "Español",
|
||||
"proficiency": "Nativo",
|
||||
"level": 5
|
||||
"level": 5,
|
||||
"detail": "Nativo"
|
||||
},
|
||||
{
|
||||
"language": "Catalán",
|
||||
"proficiency": "Comprensión",
|
||||
"level": 2,
|
||||
"detail": "Comprensión"
|
||||
},
|
||||
{
|
||||
"language": "Inglés",
|
||||
"proficiency": "Profesional Avanzado",
|
||||
"level": 4
|
||||
"level": 4,
|
||||
"detail": "Oral (Medio/Alto) Escrito (Alto)"
|
||||
},
|
||||
{
|
||||
"language": "Italiano",
|
||||
"proficiency": "Intermedio",
|
||||
"level": 3
|
||||
"level": 3,
|
||||
"detail": "Oral (Medio/Alto) Escrito (Medio)"
|
||||
}
|
||||
],
|
||||
"projects": [
|
||||
@@ -559,8 +669,84 @@
|
||||
"description": "Certificación de protección de datos y cumplimiento GDPR"
|
||||
}
|
||||
],
|
||||
"courses": [
|
||||
{
|
||||
"title": "Servoy World 2011",
|
||||
"institution": "Servoy",
|
||||
"location": "Amsterdam",
|
||||
"date": "2011-02",
|
||||
"duration": "3 días",
|
||||
"description": "Convención bianual que se celebra en Amsterdam en la que se discute acerca del mundo Servoy."
|
||||
},
|
||||
{
|
||||
"title": "Formador de Formadores",
|
||||
"institution": "FOREM Extremadura",
|
||||
"location": "Cáceres",
|
||||
"date": "2009-06",
|
||||
"duration": "150 horas",
|
||||
"description": "Realizado con aprovechamiento curso de Metodología Didáctica (Formador de Formadores)"
|
||||
},
|
||||
{
|
||||
"title": "Windows 2003 Server",
|
||||
"institution": "Cámara de Comercio de Cáceres",
|
||||
"location": "Cáceres",
|
||||
"date": "2006-01",
|
||||
"duration": "80 horas",
|
||||
"description": "Curso de 80 Horas impartido por la Cámara de Comercio de Cáceres."
|
||||
},
|
||||
{
|
||||
"title": "I Jornada Extremeña sobre la Industria del Software",
|
||||
"institution": "Universidad de Extremadura",
|
||||
"location": "Cáceres",
|
||||
"date": "2005-07",
|
||||
"duration": "3 días",
|
||||
"description": "Jornadas de 3 días de duración impartidas por la Universidad de Extremadura."
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"title": "Cartas de recomendación de TwenTiC",
|
||||
"url": "http://www.drolosoft.com/2010/downloads/recomendacion.pdf",
|
||||
"type": "recommendation"
|
||||
},
|
||||
{
|
||||
"title": "Carta de presentación",
|
||||
"url": "http://www.domestika.org/empleo/demanda/txeo",
|
||||
"type": "presentation"
|
||||
},
|
||||
{
|
||||
"title": "Portfolio Completo (Inglés)",
|
||||
"url": "http://www.behance.net/txeo",
|
||||
"type": "portfolio"
|
||||
},
|
||||
{
|
||||
"title": "Portfolio Completo (Castellano)",
|
||||
"url": "http://www.domestika.org/portfolios/txeo",
|
||||
"type": "portfolio"
|
||||
},
|
||||
{
|
||||
"title": "Perfil de LinkedIn",
|
||||
"url": "https://www.linkedin.com/in/juan-andr%C3%A9s-moreno-rubio-3277729/",
|
||||
"type": "profile"
|
||||
},
|
||||
{
|
||||
"title": "Perfil de Tecnoempleo",
|
||||
"url": "https://www.tecnoempleo.com/juan-andres-moreno-rubio.mpt",
|
||||
"type": "profile"
|
||||
},
|
||||
{
|
||||
"title": "Currículum Vitae en PDF en Inglés",
|
||||
"url": "http://www.morenoyrubio.com/cv/cv_jamr_2021_en.pdf",
|
||||
"type": "cv"
|
||||
},
|
||||
{
|
||||
"title": "Currículum Vitae Cronológico",
|
||||
"url": "http://morenoyrubio.com/cv/cv_cronologico_jamr_2021_es.pdf",
|
||||
"type": "cv"
|
||||
}
|
||||
],
|
||||
"other": {
|
||||
"driverLicense": "Tipo C"
|
||||
"driverLicense": "Tipo B"
|
||||
},
|
||||
"meta": {
|
||||
"version": "2024",
|
||||
|
||||
@@ -18,6 +18,8 @@ type CV struct {
|
||||
Projects []Project `json:"projects"`
|
||||
Awards []Award `json:"awards"`
|
||||
Certifications []Certification `json:"certifications"`
|
||||
Courses []Course `json:"courses"`
|
||||
References []Reference `json:"references"`
|
||||
Other Other `json:"other"`
|
||||
Meta Meta `json:"meta"`
|
||||
}
|
||||
@@ -90,6 +92,7 @@ type Language struct {
|
||||
Language string `json:"language"`
|
||||
Proficiency string `json:"proficiency"`
|
||||
Level int `json:"level"`
|
||||
Detail string `json:"detail,omitempty"` // Optional detail like "Oral (Medio/Alto) Escrito (Alto)"
|
||||
}
|
||||
|
||||
type Project struct {
|
||||
@@ -116,6 +119,21 @@ type Certification struct {
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type Course struct {
|
||||
Title string `json:"title"`
|
||||
Institution string `json:"institution"`
|
||||
Location string `json:"location"`
|
||||
Date string `json:"date"`
|
||||
Duration string `json:"duration"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type Reference struct {
|
||||
Title string `json:"title"`
|
||||
URL string `json:"url"`
|
||||
Type string `json:"type"` // "recommendation", "portfolio", "profile", "cv", "presentation"
|
||||
}
|
||||
|
||||
type Other struct {
|
||||
DriverLicense string `json:"driverLicense"`
|
||||
}
|
||||
|
||||
@@ -427,6 +427,73 @@ a:hover {
|
||||
.language-item {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-dark);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.language-item small {
|
||||
display: block;
|
||||
font-size: 0.8em;
|
||||
margin-top: 0.2rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* Courses */
|
||||
.course-item {
|
||||
margin-bottom: 1rem;
|
||||
padding-bottom: 0.8rem;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.course-item:last-child {
|
||||
border-bottom: none;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.course-item strong {
|
||||
font-size: 0.95em;
|
||||
color: var(--text-dark);
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.course-item small {
|
||||
display: block;
|
||||
font-size: 0.85em;
|
||||
color: var(--text-gray);
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
|
||||
.course-desc {
|
||||
font-size: 0.85em;
|
||||
color: var(--text-gray);
|
||||
margin-top: 0.4rem;
|
||||
line-height: 1.4;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
/* References */
|
||||
.reference-item {
|
||||
margin-bottom: 0.6rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.reference-item a {
|
||||
font-size: 0.9em;
|
||||
color: var(--accent-blue);
|
||||
text-decoration: none;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.reference-item a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.ref-type {
|
||||
display: block;
|
||||
font-size: 0.8em;
|
||||
color: var(--text-gray);
|
||||
font-style: italic;
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
|
||||
+49
-29
@@ -13,39 +13,70 @@
|
||||
|
||||
<!-- Left Sidebar - Skills -->
|
||||
<aside class="cv-sidebar">
|
||||
<!-- Skills Section -->
|
||||
<!-- Skills Section - Dynamically render all categories -->
|
||||
{{range .CV.Skills.Technical}}
|
||||
<section class="sidebar-section">
|
||||
<h3 class="sidebar-title">{{if eq .Lang "es"}}Lenguajes de Programación{{else}}Programming Languages{{end}}</h3>
|
||||
{{range .CV.Skills.Technical}}
|
||||
{{if eq .Category "Programming Languages"}}
|
||||
<h3 class="sidebar-title">{{.Category}}</h3>
|
||||
<div class="sidebar-content">
|
||||
{{range .Items}}<div class="skill-item">{{.}}</div>{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
<!-- Languages Section -->
|
||||
<section class="sidebar-section">
|
||||
<h3 class="sidebar-title">{{if eq .Lang "es"}}Idiomas{{else}}Languages{{end}}</h3>
|
||||
<div class="sidebar-content">
|
||||
{{range .CV.Languages}}
|
||||
<div class="language-item">
|
||||
<strong>{{.Language}}</strong>: {{.Proficiency}}
|
||||
{{if .Detail}}<br><small style="color: #666;">{{.Detail}}</small>{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Courses Section -->
|
||||
{{if .CV.Courses}}
|
||||
<section class="sidebar-section">
|
||||
<h3 class="sidebar-title">{{if eq .Lang "es"}}Desarrollo Web{{else}}Web Development{{end}}</h3>
|
||||
{{range .CV.Skills.Technical}}
|
||||
{{if eq .Category "Web Development"}}
|
||||
<h3 class="sidebar-title">{{if eq .Lang "es"}}Cursos Realizados{{else}}Training Courses{{end}}</h3>
|
||||
<div class="sidebar-content">
|
||||
{{range .Items}}<div class="skill-item">{{.}}</div>{{end}}
|
||||
{{range .CV.Courses}}
|
||||
<div class="course-item">
|
||||
<strong>{{.Title}}</strong><br>
|
||||
<small>{{.Institution}} - {{.Location}}</small><br>
|
||||
<small>{{.Date}} ({{.Duration}})</small>
|
||||
{{if .Description}}<p class="course-desc">{{.Description}}</p>{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
<!-- References Section -->
|
||||
{{if .CV.References}}
|
||||
<section class="sidebar-section">
|
||||
<h3 class="sidebar-title">{{if eq .Lang "es"}}Frameworks JavaScript{{else}}Javascript Frameworks{{end}}</h3>
|
||||
{{range .CV.Skills.Technical}}
|
||||
{{if eq .Category "JavaScript Frameworks"}}
|
||||
<h3 class="sidebar-title">{{if eq .Lang "es"}}Referencias{{else}}References{{end}}</h3>
|
||||
<div class="sidebar-content">
|
||||
{{range .Items}}<div class="skill-item">{{.}}</div>{{end}}
|
||||
{{range .CV.References}}
|
||||
<div class="reference-item">
|
||||
<a href="{{.URL}}" target="_blank" rel="noopener noreferrer">{{.Title}}</a>
|
||||
<small class="ref-type">({{.Type}})</small>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
<!-- Other Section (Driver's License) -->
|
||||
{{if .CV.Other.DriverLicense}}
|
||||
<section class="sidebar-section">
|
||||
<h3 class="sidebar-title">{{if eq .Lang "es"}}Otros{{else}}Other{{end}}</h3>
|
||||
<div class="sidebar-content">
|
||||
{{if eq .Lang "es"}}Carnet de conducir {{.CV.Other.DriverLicense}}{{else}}Driver's License {{.CV.Other.DriverLicense}}{{end}}
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
</aside>
|
||||
|
||||
<!-- Main Content Area -->
|
||||
@@ -119,15 +150,4 @@
|
||||
{{end}}
|
||||
</section>
|
||||
|
||||
<!-- Languages -->
|
||||
<section class="cv-section">
|
||||
<h3 class="section-title">{{if eq .Lang "es"}}Idiomas{{else}}Languages{{end}}</h3>
|
||||
<div class="languages-list">
|
||||
{{range .CV.Languages}}
|
||||
<div class="language-item">
|
||||
<strong>{{.Language}}</strong>: {{.Proficiency}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
@@ -137,15 +137,16 @@
|
||||
|
||||
<!-- Right: Action buttons -->
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
<a
|
||||
class="export-btn"
|
||||
onclick="window.print()"
|
||||
href="/export/pdf?lang={{.Lang}}"
|
||||
download
|
||||
aria-label="{{if eq .Lang "es"}}Descargar PDF del CV{{else}}Download CV as PDF{{end}}">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" style="display: inline-block; vertical-align: middle;">
|
||||
<path d="M8.5 11.5l3.5-3.5h-2.5v-6h-2v6h-2.5l3.5 3.5zm-6.5 2.5v2h12v-2h-12z"/>
|
||||
</svg>
|
||||
{{if eq .Lang "es"}}Descargar PDF{{else}}Download as PDF{{end}}
|
||||
</button>
|
||||
</a>
|
||||
<button
|
||||
class="export-btn"
|
||||
onclick="window.print()"
|
||||
|
||||
Reference in New Issue
Block a user