From 928d2ffaa2f31d982fcb148768a150280a22b1ff Mon Sep 17 00:00:00 2001 From: Morten Olsen Date: Wed, 30 Mar 2022 09:37:57 +0200 Subject: [PATCH] feat: add cv --- content/profile/index.yml | 30 ++++++++ src/components/hero/index.tsx | 5 ++ src/data/repos/profile.ts | 14 ++++ src/latex/generators/resume/index.ts | 101 +++++++++++++++++++++++++-- 4 files changed, 143 insertions(+), 7 deletions(-) diff --git a/content/profile/index.yml b/content/profile/index.yml index 1c8713a..6462bd9 100644 --- a/content/profile/index.yml +++ b/content/profile/index.yml @@ -2,10 +2,12 @@ name: Morten Olsen tagline: “...One part genius, one part crazy” avatar: me.jpg email: hello@buy-me.coffee +github: morten-olsen location: Copenhagen, DK social: - name: Github link: https://github.com/morten-olsen + value: morten-olsen logo: logos/github.svg - name: HackTheBox link: https://app.hackthebox.eu/profile/174098 @@ -19,4 +21,32 @@ social: - name: Linkedin link: https://www.linkedin.com/in/mortenolsendk logo: logos/linkedin.svg +platforms: + - name: JavaScript + level: 5 + - name: NodeJS + level: 5 + - name: React Native + level: 5 + - name: Typescript + level: 5 + - name: Docker + level: 4 + - name: Linux + level: 4 + - name: CSharp + level: 4 +skills: + - name: React + level: 5 + - name: Redux + level: 5 + - name: Webpack + level: 5 + - name: RxJS + level: 3 + - name: Styled-Components + level: 5 + - name: GraphQL + level: 4 diff --git a/src/components/hero/index.tsx b/src/components/hero/index.tsx index 26a1504..5d865b5 100644 --- a/src/components/hero/index.tsx +++ b/src/components/hero/index.tsx @@ -101,6 +101,11 @@ const Hero: React.FC = ({ profile }) => ( {profile.tagline} + + + Resumé + + {profile.social.map((social) => ( diff --git a/src/data/repos/profile.ts b/src/data/repos/profile.ts index efd0d65..26e7fed 100644 --- a/src/data/repos/profile.ts +++ b/src/data/repos/profile.ts @@ -9,14 +9,24 @@ export type Profile = { name: string; avatar?: string | null; email?: string; + github?: string; location?: string; tagline?: string; + resume: string; social: { name: string; value: string; link: string; logo: string; }[] + platforms: { + name: string; + level: number; + }[]; + skills: { + name: string; + level: number; + }[]; } @Service() @@ -50,6 +60,10 @@ export class ProfileDB { logo: image || null, }; }) + structure.resume = this.#assets.getPath( + 'profile', + 'a4.tex.yml', + ); return structure; } diff --git a/src/latex/generators/resume/index.ts b/src/latex/generators/resume/index.ts index df921cf..462749b 100644 --- a/src/latex/generators/resume/index.ts +++ b/src/latex/generators/resume/index.ts @@ -1,12 +1,14 @@ +import path from 'path'; import { LatexGenerator } from "../Generator"; import Container from 'typedi'; import { AssetResolver } from '../../../data/assets'; import { ProfileDB } from '../../../data/repos/profile'; import { ExperienceDB } from '../../../data/repos/experiences'; +import { fromMarkdown } from '../../helpers/convert'; const assets = { - getPath: (source: string) => { - return source; + getPath: (...source: string[]) => { + return path.join(process.cwd(), 'content', ...source); }, } type Data = { @@ -18,16 +20,101 @@ const resume: LatexGenerator = async (data, location) => { const experienceDB = Container.get(ExperienceDB); const profile = await profileDB.get(); + const avatar = profile.avatar; const experiences = await experienceDB.list(); + console.log('a', avatar); return ` -\\documentclass[twocolumn]{article} +\\documentclass[10pt, a4paper]{article} +\\usepackage[top=2cm, bottom=2cm, left=2cm, right=2cm]{geometry} +\\def \\columncount {3} +\\def \\skillcolumncount {2} +\\usepackage{pagecolor} +\\usepackage{paracol} +\\usepackage{kantlipsum} +\\usepackage{multicol} +\\usepackage{xifthen} +\\usepackage{tcolorbox} +\\usepackage{wrapfig} \\usepackage{graphicx} -\\usepackage[skip=5pt plus1pt, indent=10pt]{parskip} -\\setlength\\columnsep{1cm} -\\title{${profile.name}} +\\usepackage{fancyhdr} + +\\setlength{\\columnseprule}{0.1pt} +\\pagestyle{fancy} +\\fancyhf{} +\\rhead{Morten Olsen \\today} +\\lhead{Curriculum Vitae} +\\rfoot{Page \\thepage} + \\begin{document} -\\maketitle + \\noindent + \\begin{minipage}{\\textwidth} + \\noindent + \\begin{minipage}{\\textwidth - 3.2cm} + \\Huge Curriculum Vitae + \\newline\\large ${profile.name} + \\end{minipage} + \\noindent + \\begin{minipage}{3cm} + \\begin{flushright} + \\includegraphics[height=3cm]{${avatar}} + \\end{flushright} + \\end{minipage} + \\vspace{0.5cm} + \\hrule + \\vspace{0.5cm} + \\begin{multicols}{2} + \\noindent \\textbf{E-mail}\\dotfill ${profile.email}\\\\ + \\noindent \\textbf{Location}\\dotfill ${profile.location}\\\\ + \\noindent \\textbf{Github}\\dotfill ${profile.github}\\\\ + \\end{multicols} + \\end{minipage} + \\hfill + \\begin{minipage}{\\textwidth/3-2cm} + \\end{minipage} + \\vspace{1cm} + \\hrule + + + \\section*{Platforms and Languages} + Platforms and languages which I have worked with. The list is a shortened down version.\\\\\\\\ + \\noindent + \\begin{minipage}{\\textwidth} + \\begin{multicols}{2} + ${profile.platforms.map(({ name, level }) => ` + \\textbf{${name}} \\textit{${level}} + `).join('\n')} + \\end{multicols} + \\end{minipage} + \\vspace{0.5cm} + \\hrule + + \\section*{Experiences} + ${experiences.map((experience) => ` + \\noindent + \\begin{multicols}{3} + \\noindent{\\Large \\textbf{${experience.company.name}}} \\hfill {\\small ${experience.startDate} - ${experience.endDate}} \\\\ + \\textit{${experience.title}} + \\vfill\\null\\columnbreak + ${fromMarkdown(experience.content, 0)} + \\end{multicols} + \\vspace{0.5cm} + \\hrule + `).join('\n')} + + + \\section*{Frameworks} + This list of frameworks is a curated list of frameworks I have been using recently and therefore are all amongst frameworks which I prefer to work with.\\\\\\\\ + \\noindent + \\begin{minipage}{\\textwidth} + \\begin{multicols}{2} + ${profile.skills.map(({ name, level }) => ` + \\textbf{${name}} \\textit{${level}} + `).join('\n')} + \\end{multicols} + \\end{minipage} + \\vspace{0.5cm} + \\hrule \\end{document} `; }