mirror of
https://github.com/morten-olsen/morten-olsen.github.io.git
synced 2026-02-08 01:46:28 +01:00
feat: add cv
This commit is contained in:
@@ -2,10 +2,12 @@ name: Morten Olsen
|
|||||||
tagline: “...One part genius, one part crazy”
|
tagline: “...One part genius, one part crazy”
|
||||||
avatar: me.jpg
|
avatar: me.jpg
|
||||||
email: hello@buy-me.coffee
|
email: hello@buy-me.coffee
|
||||||
|
github: morten-olsen
|
||||||
location: Copenhagen, DK
|
location: Copenhagen, DK
|
||||||
social:
|
social:
|
||||||
- name: Github
|
- name: Github
|
||||||
link: https://github.com/morten-olsen
|
link: https://github.com/morten-olsen
|
||||||
|
value: morten-olsen
|
||||||
logo: logos/github.svg
|
logo: logos/github.svg
|
||||||
- name: HackTheBox
|
- name: HackTheBox
|
||||||
link: https://app.hackthebox.eu/profile/174098
|
link: https://app.hackthebox.eu/profile/174098
|
||||||
@@ -19,4 +21,32 @@ social:
|
|||||||
- name: Linkedin
|
- name: Linkedin
|
||||||
link: https://www.linkedin.com/in/mortenolsendk
|
link: https://www.linkedin.com/in/mortenolsendk
|
||||||
logo: logos/linkedin.svg
|
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
|
||||||
|
|
||||||
|
|||||||
@@ -101,6 +101,11 @@ const Hero: React.FC<Props> = ({ profile }) => (
|
|||||||
</Name>
|
</Name>
|
||||||
<Tagline>{profile.tagline}</Tagline>
|
<Tagline>{profile.tagline}</Tagline>
|
||||||
<Social>
|
<Social>
|
||||||
|
<SlideIn>
|
||||||
|
<SocialItem href={profile.resume} target="_blank">
|
||||||
|
<SocialText>Resumé</SocialText>
|
||||||
|
</SocialItem>
|
||||||
|
</SlideIn>
|
||||||
{profile.social.map((social) => (
|
{profile.social.map((social) => (
|
||||||
<SlideIn key={social.name}>
|
<SlideIn key={social.name}>
|
||||||
<SocialItem key={social.name} href={social.link} target="_blank">
|
<SocialItem key={social.name} href={social.link} target="_blank">
|
||||||
|
|||||||
@@ -9,14 +9,24 @@ export type Profile = {
|
|||||||
name: string;
|
name: string;
|
||||||
avatar?: string | null;
|
avatar?: string | null;
|
||||||
email?: string;
|
email?: string;
|
||||||
|
github?: string;
|
||||||
location?: string;
|
location?: string;
|
||||||
tagline?: string;
|
tagline?: string;
|
||||||
|
resume: string;
|
||||||
social: {
|
social: {
|
||||||
name: string;
|
name: string;
|
||||||
value: string;
|
value: string;
|
||||||
link: string;
|
link: string;
|
||||||
logo: string;
|
logo: string;
|
||||||
}[]
|
}[]
|
||||||
|
platforms: {
|
||||||
|
name: string;
|
||||||
|
level: number;
|
||||||
|
}[];
|
||||||
|
skills: {
|
||||||
|
name: string;
|
||||||
|
level: number;
|
||||||
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
@@ -50,6 +60,10 @@ export class ProfileDB {
|
|||||||
logo: image || null,
|
logo: image || null,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
structure.resume = this.#assets.getPath(
|
||||||
|
'profile',
|
||||||
|
'a4.tex.yml',
|
||||||
|
);
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
|
import path from 'path';
|
||||||
import { LatexGenerator } from "../Generator";
|
import { LatexGenerator } from "../Generator";
|
||||||
import Container from 'typedi';
|
import Container from 'typedi';
|
||||||
import { AssetResolver } from '../../../data/assets';
|
import { AssetResolver } from '../../../data/assets';
|
||||||
import { ProfileDB } from '../../../data/repos/profile';
|
import { ProfileDB } from '../../../data/repos/profile';
|
||||||
import { ExperienceDB } from '../../../data/repos/experiences';
|
import { ExperienceDB } from '../../../data/repos/experiences';
|
||||||
|
import { fromMarkdown } from '../../helpers/convert';
|
||||||
|
|
||||||
const assets = {
|
const assets = {
|
||||||
getPath: (source: string) => {
|
getPath: (...source: string[]) => {
|
||||||
return source;
|
return path.join(process.cwd(), 'content', ...source);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
type Data = {
|
type Data = {
|
||||||
@@ -18,16 +20,101 @@ const resume: LatexGenerator<Data> = async (data, location) => {
|
|||||||
const experienceDB = Container.get(ExperienceDB);
|
const experienceDB = Container.get(ExperienceDB);
|
||||||
|
|
||||||
const profile = await profileDB.get();
|
const profile = await profileDB.get();
|
||||||
|
const avatar = profile.avatar;
|
||||||
const experiences = await experienceDB.list();
|
const experiences = await experienceDB.list();
|
||||||
|
console.log('a', avatar);
|
||||||
|
|
||||||
return `
|
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{graphicx}
|
||||||
\\usepackage[skip=5pt plus1pt, indent=10pt]{parskip}
|
\\usepackage{fancyhdr}
|
||||||
\\setlength\\columnsep{1cm}
|
|
||||||
\\title{${profile.name}}
|
\\setlength{\\columnseprule}{0.1pt}
|
||||||
|
\\pagestyle{fancy}
|
||||||
|
\\fancyhf{}
|
||||||
|
\\rhead{Morten Olsen \\today}
|
||||||
|
\\lhead{Curriculum Vitae}
|
||||||
|
\\rfoot{Page \\thepage}
|
||||||
|
|
||||||
\\begin{document}
|
\\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}
|
\\end{document}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user