feat: search engine timeline view
This commit is contained in:
parent
4dddc7973e
commit
52b45583c6
|
@ -1,19 +1,19 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<Home/>
|
||||
<Skills/>
|
||||
<Timeline/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import Home from './components/Home.vue';
|
||||
import Skills from './components/Skills.vue';
|
||||
import Timeline from './components/Timeline.vue';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
Home,
|
||||
Skills,
|
||||
Timeline,
|
||||
},
|
||||
})
|
||||
export default class App extends Vue {
|
||||
|
@ -30,8 +30,9 @@ export default class App extends Vue {
|
|||
min-height: 100%;
|
||||
height: auto;
|
||||
|
||||
padding-bottom: 4vw;
|
||||
|
||||
font-size: 1rem;
|
||||
font-family: 'Source Sans Pro';
|
||||
flex-flow: column nowrap;
|
||||
|
||||
overflow: hidden;
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="4.2333mm" height="4.2333mm" version="1.1" viewBox="0 0 4.2333 4.2333" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(-139.71 -124.82)">
|
||||
<g transform="matrix(.49451 0 0 .49451 38.616 -321.26)">
|
||||
<g transform="matrix(.64049 0 0 .64049 75.033 338.39)">
|
||||
<g transform="matrix(1.3569 0 0 1.3569 -74.479 -286.98)">
|
||||
<circle cx="208.71" cy="865.03" r="4.9253" fill="#292a2e" style="paint-order:stroke fill markers"/>
|
||||
<path d="m207.85 862.56a0.33661 0.33661 0 0 0-0.31641 0.18946l-0.96289 1.9766h-0.59961a0.33657 0.33657 0 0 0-0.33789 0.33594 0.33657 0.33657 0 0 0 0.33789 0.33789h0.81055a0.33661 0.33661 0 0 0 0.30273-0.18946l0.71875-1.4746 1.3867 3.543a0.33661 0.33661 0 0 0 0.61133 0.0332l0.99804-1.9121h0.64649a0.33657 0.33657 0 0 0 0.33594-0.33789 0.33657 0.33657 0 0 0-0.33594-0.33594h-0.84961a0.33661 0.33661 0 0 0-0.29883 0.18164l-0.75 1.4375-1.3984-3.5703a0.33661 0.33661 0 0 0-0.29882-0.21485z" color="#000000" fill="#9b9ea1" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="4.2333mm" height="4.2333mm" version="1.1" viewBox="0 0 4.2333 4.2333" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(-139.71 -124.82)">
|
||||
<g transform="matrix(.49451 0 0 .49451 38.616 -321.26)">
|
||||
<g transform="matrix(.64049 0 0 .64049 75.033 338.39)">
|
||||
<g transform="matrix(1.3569 0 0 1.3569 -74.479 -286.98)">
|
||||
<circle cx="208.71" cy="865.03" r="4.9253" fill="#292a2e" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="m208.16 907.55-0.20732 0.20589c-0.17972 0.17813-0.47201 0.17829-0.65163 0-0.0864-0.0857-0.13378-0.19948-0.13378-0.32046 0-0.12097 0.0474-0.23483 0.13373-0.32051l0.76312-0.75713c0.15816-0.15683 0.45567-0.38776 0.67252-0.1727 0.0995 0.0988 0.26023 0.0982 0.35903-2e-3 0.0988-0.0995 0.0982-0.26023-2e-3 -0.35897-0.3686-0.36579-0.91339-0.29819-1.3879 0.17259l-0.76317 0.75718c-0.1831 0.18177-0.28389 0.42351-0.28389 0.68082 0 0.25732 0.10079 0.49901 0.28394 0.68077 0.18843 0.18694 0.43585 0.28036 0.68338 0.28036 0.24758 0 0.4951-0.0934 0.68363-0.28046l0.20748-0.20594c0.0995-0.0987 0.10003-0.25946 8.7e-4 -0.35898-0.0987-0.0994-0.25956-0.1-0.35907-8.8e-4zm2.3127-2.9412c-0.39591-0.39282-0.94946-0.41413-1.316-0.0505l-0.25844 0.25654c-0.0995 0.0988-0.10012 0.25946-2e-3 0.35897 0.0989 0.0995 0.25957 0.10008 0.35909 2e-3l0.25833-0.25638c0.18985-0.18853 0.43846-0.11038 0.60061 0.0505 0.0865 0.0857 0.13393 0.19954 0.13393 0.32051 0 0.12103-0.0475 0.23488-0.13383 0.32056l-0.81418 0.80769c-0.37229 0.36937-0.54694 0.196-0.62145 0.12205-0.0995-0.0988-0.26019-0.0982-0.35904 2e-3 -0.0988 0.0995-0.0982 0.26023 2e-3 0.35897 0.17091 0.16963 0.36599 0.25372 0.5705 0.25372 0.2504 0 0.51488-0.12609 0.76636-0.37576l0.81418-0.80769c0.18305-0.18177 0.28394-0.42355 0.28394-0.68087 0-0.25721-0.10089-0.499-0.28404-0.68087z" fill="#9b9ea1"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="4.2333mm" height="4.2333mm" version="1.1" viewBox="0 0 4.2333 4.2333" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(-139.71 -124.82)">
|
||||
<g transform="matrix(.49451 0 0 .49451 38.616 -321.26)">
|
||||
<g transform="matrix(.64049 0 0 .64049 75.033 338.39)">
|
||||
<g transform="matrix(1.3569 0 0 1.3569 -74.479 -286.98)">
|
||||
<circle cx="208.71" cy="865.03" r="4.9253" fill="#292a2e" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="m210.17 904.55h-2.9336c-0.40336 0-0.73339 0.33003-0.73339 0.7334v1.8335c0 0.40337 0.33003 0.73339 0.73339 0.73339v0.55005c0 0.16502 0.20169 0.23836 0.3117 0.12835l0.67839-0.6784h1.9435c0.40336 0 0.73339-0.33002 0.73339-0.73339v-1.8335c0-0.40337-0.33003-0.7334-0.73339-0.7334zm-1.1001 2.2002h-1.1001c-0.11001 0-0.18336-0.0733-0.18336-0.18335 0-0.11001 0.0734-0.18334 0.18336-0.18334h1.1001c0.11001 0 0.18335 0.0733 0.18335 0.18334 0 0.11001-0.0733 0.18335-0.18335 0.18335zm0.36669-0.7334h-1.4668c-0.11001 0-0.18336-0.0733-0.18336-0.18334 0-0.11001 0.0734-0.18336 0.18336-0.18336h1.4668c0.11001 0 0.18336 0.0734 0.18336 0.18336 0 0.11001-0.0734 0.18334-0.18336 0.18334z" fill="#9b9ea1"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="4.2333mm" height="4.2333mm" version="1.1" viewBox="0 0 4.2333 4.2333" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(-55.204 -97.322)">
|
||||
<g transform="matrix(.42975 0 0 .42975 -32.37 -272.31)">
|
||||
<circle cx="208.71" cy="865.03" r="4.9253" fill="#2c55cf" style="paint-order:stroke fill markers"/>
|
||||
<path d="m209.6 862.95c0-0.0945-0.0733-0.29631-0.29592-0.29631-0.12969 0-0.24927 0.0842-0.28656 0.21504l-1.1874 4.156c-8e-3 0.0272-0.0115 0.0547-0.0115 0.0816-8e-3 0.0957 0.0745 0.29704 0.29715 0.29704 0.12913 0 0.24797-0.0849 0.28526-0.21541l1.1874-4.156c8e-3 -0.0276 0.0116-0.055 0.0116-0.082zm-2.2264 1.0312c0-0.16958-0.13869-0.29686-0.29686-0.29686-0.076 0-0.15195 0.029-0.20984 0.087l-1.039 1.039c-0.058 0.0661-0.087 0.14216-0.087 0.20987 0 0.0677 0.029 0.16049 0.087 0.21801l1.039 1.039c0.0577 0.0584 0.13382 0.0789 0.20988 0.0789 0.15817 0 0.29686-0.12737 0.29686-0.29686 0-0.076-0.029-0.15195-0.087-0.20993l-0.82911-0.82907 0.82916-0.82915c0.0582-0.0503 0.0869-0.12542 0.0869-0.20984zm4.3044 1.039c0-0.076-0.029-0.15195-0.087-0.20993l-1.039-1.039c-0.0577-0.0498-0.13382-0.0869-0.20989-0.0869-0.15816 0-0.29685 0.12737-0.29685 0.29686 0 0.076 0.029 0.15195 0.087 0.20993l0.82915 0.82916-0.82915 0.82916c-0.0582 0.066-0.087 0.14202-0.087 0.20974 0 0.16958 0.13869 0.29686 0.29685 0.29686 0.076 0 0.15196-0.029 0.20985-0.087l1.039-1.039c0.0583-0.0494 0.087-0.12546 0.087-0.20988z" fill="#fff"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="4.2333mm" height="4.2333mm" version="1.1" viewBox="0 0 4.2333 4.2333" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(-139.71 -124.82)">
|
||||
<g transform="matrix(.31672 0 0 .31672 75.72 -153.92)">
|
||||
<g transform="matrix(1.3569 0 0 1.3569 -74.479 -286.98)">
|
||||
<circle cx="208.71" cy="865.03" r="4.9253" fill="#292a2e" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
<path d="m211.76 887.29-0.13917-0.0804c-0.16563-0.0955-0.26458-0.26696-0.26458-0.45826 0-0.19129 0.099-0.36274 0.26458-0.45826l0.13917-0.0804c0.37994-0.2196 0.50985-0.70432 0.29051-1.0843l-0.26458-0.45826c-0.21881-0.37915-0.70538-0.50932-1.0843-0.29051l-0.13917 0.0802c-0.16563 0.0958-0.36381 0.0958-0.52917 0-0.16563-0.0958-0.26458-0.26697-0.26458-0.45826v-0.1606c0-0.43762-0.35613-0.79375-0.79375-0.79375h-0.52917c-0.43762 0-0.79375 0.35613-0.79375 0.79375v0.16086c0 0.1913-0.099 0.36248-0.26458 0.45826-0.16563 0.0955-0.36354 0.0958-0.52917 0l-0.13917-0.0804c-0.37888-0.21881-0.86545-0.0886-1.0845 0.29051l-0.26458 0.45826c-0.21934 0.37994-0.0894 0.86492 0.29051 1.0843l0.13944 0.0804c0.16563 0.0955 0.26458 0.26697 0.26458 0.45826 0 0.1913-0.099 0.36275-0.26458 0.45826l-0.13917 0.0804c-0.37995 0.21934-0.50986 0.70433-0.29052 1.0843l0.26459 0.45826c0.21907 0.37914 0.70564 0.50932 1.0843 0.29051l0.13917-0.0802c0.16563-0.096 0.36354-0.0955 0.52917 0 0.16563 0.0958 0.26458 0.26696 0.26458 0.45826v0.1606c0 0.43762 0.35613 0.79375 0.79375 0.79375h0.52917c0.43762 0 0.79375-0.35613 0.79375-0.79375v-0.16087c0-0.19129 0.099-0.36248 0.26458-0.45826 0.16536-0.0955 0.36354-0.0958 0.52917 0l0.13917 0.0804c0.37888 0.21854 0.86545 0.0884 1.0843-0.29051l0.26458-0.45826c0.21934-0.37994 0.0894-0.86493-0.29051-1.0843zm-3.0496 0.78423c-0.72945 0-1.3229-0.59346-1.3229-1.3229 0-0.72945 0.59346-1.3229 1.3229-1.3229 0.72946 0 1.3229 0.59346 1.3229 1.3229 0 0.72946-0.59346 1.3229-1.3229 1.3229z" fill="#9b9ea1"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="4.2333mm" height="4.2333mm" version="1.1" viewBox="0 0 4.2333 4.2333" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(-139.71 -124.82)">
|
||||
<g transform="matrix(.49451 0 0 .49451 38.616 -321.26)">
|
||||
<g transform="matrix(.64049 0 0 .64049 75.033 338.39)">
|
||||
<g transform="matrix(1.3569 0 0 1.3569 -74.479 -286.98)">
|
||||
<circle cx="208.71" cy="865.03" r="4.9253" fill="#292a2e" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="m210.25 905.42a0.61713 0.61713 0 1 0-0.92831 0.53266c-0.0221 0.28041-0.19362 0.35678-0.7232 0.4669-0.17126 0.0355-0.34646 0.0718-0.50827 0.13432v-1.2169a0.61713 0.61713 0 1 0-0.61713 0v2.0174a0.61713 0.61713 0 1 0 0.62118 2e-3c0.023-0.17357 0.15429-0.23461 0.62929-0.33287 0.2645-0.0547 0.53787-0.11128 0.76929-0.25987 0.27964-0.17916 0.42939-0.45109 0.44704-0.80892a0.61713 0.61713 0 0 0 0.31011-0.53508zm-2.4685-0.9257a0.30857 0.30857 0 1 1-0.30856 0.30857 0.30857 0.30857 0 0 1 0.30856-0.30857zm0 3.7028a0.30857 0.30857 0 1 1 0.30857-0.30856 0.30857 0.30857 0 0 1-0.30857 0.30856zm1.8514-2.4685a0.30857 0.30857 0 1 1 0.30857-0.30857 0.30857 0.30857 0 0 1-0.30857 0.30857z" fill="#9b9ea1"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
|
@ -1,142 +0,0 @@
|
|||
<template>
|
||||
<div id='banner1'>
|
||||
|
||||
<div class='border-card'></div>
|
||||
|
||||
<div class='content'>
|
||||
<h3>Hello, I'm</h3>
|
||||
<h1 class='name'>
|
||||
{{ model.firstname.toUpperCase() }}
|
||||
{{ model.lastname.toUpperCase() }}
|
||||
</h1>
|
||||
<h2 class='headline'>{{ model.headline.toUpperCase() }}</h2>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import BannerModel from '../model/banner';
|
||||
|
||||
@Component({})
|
||||
export default class Banner1 extends Vue {
|
||||
private model: any = BannerModel;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
@import '../global.scss';
|
||||
|
||||
$banner-size: 100vh;
|
||||
$bg-color: #ededed;
|
||||
|
||||
// MEDIA QUERIES
|
||||
// optimize vertical space
|
||||
$mq-vert: 590px;
|
||||
|
||||
#banner1 {
|
||||
flex: #{$banner-size * 0.999} 0 0;
|
||||
|
||||
display: flex;
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
flex-flow: row wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
color: #3d3d3d;
|
||||
font-size: 1rem;
|
||||
font-family: 'Source Sans Pro';
|
||||
font-weight: 400;
|
||||
white-space: nowrap;
|
||||
|
||||
background: $bg-color;
|
||||
}
|
||||
|
||||
.border-card {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: -20vw;
|
||||
left: 70vw;
|
||||
width: 60vw;
|
||||
height: 60vw;
|
||||
|
||||
background: linear-gradient(45deg, #1a1a1a, #292929);
|
||||
|
||||
border-radius: 3rem;
|
||||
|
||||
transform: rotate(35deg);
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: auto 0 1;
|
||||
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
flex-flow: column nowrap;
|
||||
|
||||
margin: 0 10rem;
|
||||
margin-bottom: 6rem;
|
||||
|
||||
h1 {
|
||||
font-size: 4em;
|
||||
font-weight: 700;
|
||||
}
|
||||
h2 {
|
||||
font-size: 2.2em;
|
||||
font-weight: 400;
|
||||
}
|
||||
h3 {
|
||||
font-size: 2em;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// not enough vertical space
|
||||
@media screen and (max-height: 615px){
|
||||
#banner1 {
|
||||
align-items: flex-start;
|
||||
|
||||
.content {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
// not enough horizontal space
|
||||
@media screen and (max-width: 740px){
|
||||
#banner1 {
|
||||
font-size: 2vw;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.content {
|
||||
margin: 0 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
// not enough vertical space
|
||||
@media screen and (max-height: 615px){
|
||||
#banner1 {
|
||||
font-size: 1vw;
|
||||
}
|
||||
}
|
||||
|
||||
// border-card overlaps with the text
|
||||
@media screen and (max-width: 1010px){
|
||||
.border-card {
|
||||
left: 80vw;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -1,203 +0,0 @@
|
|||
<template>
|
||||
<div id='banner2'>
|
||||
|
||||
<div class='content'>
|
||||
<h2>Hello, I'm a <u>freelance developer</u></h2>
|
||||
<br>
|
||||
<br>
|
||||
<h3>
|
||||
I make your ideas into sites and
|
||||
applications that work and <u>thrive</u>
|
||||
out of the box.
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class='images'>
|
||||
<div class='circle top'></div>
|
||||
<div class='circle bottom'></div>
|
||||
<div class='laptop'></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import BannerModel from '../model/banner';
|
||||
|
||||
@Component({})
|
||||
export default class Banner2 extends Vue {
|
||||
private model: any = BannerModel;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
@import '../global.scss';
|
||||
|
||||
$banner-size: 100vh;
|
||||
$bg-color: #0e0e10;
|
||||
|
||||
// MEDIA QUERIES
|
||||
// optimize vertical space
|
||||
$mq-vert: 590px;
|
||||
|
||||
#banner2 {
|
||||
flex: #{$banner-size * 0.999} 0 0;
|
||||
|
||||
display: flex;
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
flex-flow: row nowrap;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
color: #fff;
|
||||
font-size: 1rem;
|
||||
font-family: 'Source Sans Pro';
|
||||
font-weight: 400;
|
||||
white-space: nowrap;
|
||||
|
||||
background: $bg-color;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 37%;
|
||||
|
||||
white-space: normal;
|
||||
|
||||
margin: 0 10rem;
|
||||
margin-bottom: 6rem;
|
||||
|
||||
h2, h3 {
|
||||
display: inline;
|
||||
}
|
||||
u {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 5em;
|
||||
font-weight: 400;
|
||||
}
|
||||
h3 {
|
||||
font-size: 3em;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
u {
|
||||
position: relative;
|
||||
font-weight: 800;
|
||||
text-decoration: none;
|
||||
z-index: 0;
|
||||
|
||||
@keyframes grow-right {
|
||||
from{ width: 0%; }
|
||||
to{ width: 102%; }
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 70%;
|
||||
left: -1%;
|
||||
width: 0%;
|
||||
height: .2em;
|
||||
|
||||
background: #5768f8;
|
||||
|
||||
z-index: -1;
|
||||
|
||||
animation: .2s .5s ease-in-out grow-right forwards;
|
||||
}
|
||||
}
|
||||
|
||||
h3 u:before {
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.images {
|
||||
flex: auto 1 1;
|
||||
|
||||
position: relative;
|
||||
width: 50vw;
|
||||
height: 50vh;
|
||||
|
||||
background: radial-gradient(rgba(87, 104, 248, 0.5) 0%, transparent 70%);
|
||||
}
|
||||
|
||||
@keyframes scale-up {
|
||||
0% { transform: scale(0); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
// gradient circles around the leftmost center point
|
||||
$focus-point-x: 50%;
|
||||
$focus-point-y: 50%;
|
||||
|
||||
.circle,
|
||||
.circle.bottom {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: calc( #{$focus-point-y} - 5vw );
|
||||
left: calc( #{$focus-point-x} - 5vw );
|
||||
width: 50vw;
|
||||
height: 50vw;
|
||||
|
||||
border-radius: 50% / 50%;
|
||||
|
||||
background: linear-gradient(90deg, #6063f8, #6431f5);
|
||||
|
||||
transform: scale(0);
|
||||
animation: .2s 1.7s ease-in-out scale-up forwards;
|
||||
}
|
||||
|
||||
.circle.top {
|
||||
top: calc( #{$focus-point-y} - 20vw );
|
||||
left: calc( #{$focus-point-x} - 20vw );
|
||||
width: 20vw;
|
||||
height: 20vw;
|
||||
|
||||
background: linear-gradient(90deg, #3d4ba3, #57f2f8);
|
||||
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
.laptop {
|
||||
position: absolute;
|
||||
top: $focus-point-y;
|
||||
left: $focus-point-x;
|
||||
width: 40vw;
|
||||
height: 40vw;
|
||||
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
|
||||
background: url('../assets/laptop.svg');
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
// not enough horizontal space
|
||||
@media screen and (max-width: 1000px){
|
||||
#banner2 {
|
||||
font-size: 1vw;
|
||||
}
|
||||
}
|
||||
// not enough vertical space
|
||||
@media screen and (max-height: 615px){
|
||||
#banner2 {
|
||||
font-size: .8vw;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -4,44 +4,6 @@
|
|||
<div class='wave'></div>
|
||||
<div class='wave w2'></div>
|
||||
|
||||
<div id='banner-container'>
|
||||
<Banner1 v-if='theme == `black_white`' />
|
||||
<Banner2 v-if='theme == `blue`' />
|
||||
<Banner2 v-if='theme == `orange`' />
|
||||
</div>
|
||||
|
||||
<form class='themes' @change="onThemeSelected" ref='theme_form'>
|
||||
<h2>THEMES</h2>
|
||||
|
||||
<template v-for='t in themes'>
|
||||
<input :key='`${t.name}-input`' type='radio' name='theme' :id='t.name' :value='t.name' :checked='t.default'/>
|
||||
<label :key='`${t.name}-label`' :for='t.name'>
|
||||
<svg width="16" height="16" version="1.1" viewBox="0 0 4.2333 4.2333" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id='blue-gradient'>
|
||||
<stop offset='0' style='stop-color: var(--color0); stop-opacity: 1'/>
|
||||
<stop offset='1' style='stop-color: var(--color1); stop-opacity: 1'/>
|
||||
</linearGradient>
|
||||
<linearGradient id='orange-gradient'>
|
||||
<stop offset='0' style='stop-color: var(--color0); stop-opacity: 1'/>
|
||||
<stop offset='1' style='stop-color: var(--color1); stop-opacity: 1'/>
|
||||
</linearGradient>
|
||||
<linearGradient id='green-gradient'>
|
||||
<stop offset='0' style='stop-color: var(--color0); stop-opacity: 1'/>
|
||||
<stop offset='1' style='stop-color: var(--color1); stop-opacity: 1'/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g transform="translate(-157.14 -77.615)">
|
||||
<g transform="matrix(0 -.11388 -.11388 0 185.25 96.78)" stroke="#1a1a1a" stroke-width="11.855">
|
||||
<path d="m168.29 228.24c0 10.195-8.3886 18.587-18.585 18.587s-18.59-8.3921-18.59-18.587c0-10.195 8.3931-18.587 18.59-18.587s18.585 8.3921 18.585 18.587zm-5.9273 0c0-6.9441-5.7129-12.661-12.658-12.661s-12.662 5.7168-12.662 12.661c0 6.9441 5.7175 12.661 12.662 12.661s12.658-5.7168 12.658-12.661z" color="#000000" fill="#1a1a1a" stroke="none" style="paint-order:stroke fill markers"/>
|
||||
<circle cx="149.71" cy="228.24" r="6.4803" fill="#1a1a1a" stroke="none" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</label>
|
||||
</template>
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
@ -49,26 +11,13 @@
|
|||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import { Themes, Theme } from '@/model/themes';
|
||||
import Banner1 from '@/components/Banner1.vue';
|
||||
import Banner2 from '@/components/Banner2.vue';
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
Banner1,
|
||||
Banner2,
|
||||
},
|
||||
components: {},
|
||||
})
|
||||
export default class Home extends Vue {
|
||||
private themes: Theme[] = Themes;
|
||||
private theme: string = Themes[0].name;
|
||||
}
|
||||
|
||||
private onThemeSelected() {
|
||||
const fd = new FormData(this.$refs.theme_form as HTMLFormElement);
|
||||
console.log(fd);
|
||||
this.theme = fd.get('theme') as string;
|
||||
console.log(this.theme);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
|
@ -78,17 +27,6 @@
|
|||
|
||||
$wave-height: 6.3rem;
|
||||
|
||||
// horizontal spacing between theme chips
|
||||
$theme-chip-spacing: 1rem;
|
||||
// full size of a theme chip
|
||||
$theme-chip-size: 1.8rem;
|
||||
// empty space inside the chip (relative to the chip size)
|
||||
$theme-chip-void: 1.2rem;
|
||||
// size of the inner (checked) circle (relative to the chip void)
|
||||
$theme-chip-inner: .6rem;
|
||||
|
||||
|
||||
|
||||
#home {
|
||||
position: relative;
|
||||
top: 0;
|
||||
|
@ -96,7 +34,7 @@
|
|||
width: $width;
|
||||
height: $height;
|
||||
|
||||
background: #ededed;
|
||||
background: #07142d;
|
||||
}
|
||||
|
||||
@keyframes wave-x {
|
||||
|
@ -127,98 +65,4 @@
|
|||
z-index: 900;
|
||||
}
|
||||
|
||||
.themes {
|
||||
display: flex;
|
||||
position: relative;
|
||||
top: calc( #{$height} - #{$wave-height} );
|
||||
width: $width;
|
||||
|
||||
flex-flow: row wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
transform: translateY(-100%);
|
||||
|
||||
input[type=radio]{
|
||||
display: none;
|
||||
}
|
||||
|
||||
h2 {
|
||||
flex: 100%;
|
||||
text-align: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
& > label {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: $theme-chip-size;
|
||||
height: $theme-chip-size;
|
||||
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
margin: 0 #{$theme-chip-spacing};
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
transition: transform .2s ease-in;
|
||||
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
svg circle {
|
||||
opacity: 0;
|
||||
|
||||
transition: opacity .1s ease-in-out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
label:nth-child(2) { margin-left: 0; }
|
||||
label:last-child { margin-right: 0; }
|
||||
|
||||
input:checked + label svg circle {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
// define our custom svg gradients
|
||||
#blue-gradient {
|
||||
--color0: #3d4ba3;
|
||||
--color1: #5768f8;
|
||||
}
|
||||
#orange-gradient {
|
||||
--color0: #fcb67b;
|
||||
--color1: #c54556;
|
||||
}
|
||||
#green-gradient {
|
||||
--color0: #00d89f;
|
||||
--color1: #00a2d8;
|
||||
}
|
||||
|
||||
input[value='black_white'] + label {
|
||||
circle, path{ fill: #1a1a1a; }
|
||||
}
|
||||
input[value='blue'] + label {
|
||||
circle, path{ fill: url(#blue-gradient); }
|
||||
}
|
||||
input[value='forest'] + label {
|
||||
circle, path{ fill: url(#orange-gradient); }
|
||||
}
|
||||
input[value='glass'] + label {
|
||||
circle, path{ fill: url(#green-gradient); }
|
||||
}
|
||||
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#banner-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: $width;
|
||||
height: $height;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
<template>
|
||||
<div id='skills'>
|
||||
|
||||
<div class='skillset' v-for='(skillset, si) of skills' :key='si'>
|
||||
|
||||
<div class='title'>
|
||||
{{ skillset.title.toUpperCase() }}
|
||||
</div>
|
||||
|
||||
<div class='subtitle'>
|
||||
<span v-for='keyword of skillset.keywords' :key='keyword'>{{ keyword }}</span>
|
||||
</div>
|
||||
|
||||
<div class='stack'>
|
||||
<template v-for='(skill,i) of skillset.skills'>
|
||||
<a class='label' :key='`${i}-link`' :href='skill.link' v-html='skill.label'></a>
|
||||
<span class='level' :key='`${i}-span`'>
|
||||
<span :style='{ width: (skill.level*100)+"%" }'></span>
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import SkillsModel from '../model/skills';
|
||||
|
||||
@Component
|
||||
export default class Skills extends Vue {
|
||||
private skills = SkillsModel;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
@import '../global';
|
||||
|
||||
#skills {
|
||||
flex: auto 0 1;
|
||||
|
||||
display: flex;
|
||||
position: relative;
|
||||
margin: 0 5%;
|
||||
|
||||
margin-top: 3em;
|
||||
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
.skillset {
|
||||
flex: 30%-(2*3%);
|
||||
|
||||
display: flex;
|
||||
position: relative;
|
||||
margin: 0 3%;
|
||||
|
||||
flex-flow: column nowrap;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
.title {
|
||||
flex: auto 0 1;
|
||||
|
||||
display: block;
|
||||
position: relative;
|
||||
padding: .2em 1em;
|
||||
margin-bottom: .2em;
|
||||
|
||||
font-size: 1.5rem;
|
||||
font-weight: normal;
|
||||
|
||||
border-bottom: 2px solid #ccc;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
flex: auto 0 1;
|
||||
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
color: #ccc;
|
||||
font-size: 1rem;
|
||||
font-weight: normal;
|
||||
|
||||
span{
|
||||
padding-left: .5em;
|
||||
|
||||
&:not(:last-child):after{
|
||||
content: ' / ';
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.stack {
|
||||
flex: auto;
|
||||
|
||||
display: flex;
|
||||
position: relative;
|
||||
margin: 1rem;
|
||||
min-width: 15rem;
|
||||
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
|
||||
.label{
|
||||
flex: 60%;
|
||||
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding: .2rem 0;
|
||||
|
||||
font-size: 1.1rem;
|
||||
font-weight: normal;
|
||||
|
||||
}
|
||||
.level{
|
||||
flex: 40%;
|
||||
|
||||
display: block;
|
||||
position: relative;
|
||||
padding: .2rem 0;
|
||||
height: .5rem;
|
||||
|
||||
border-radius: .25rem / .25rem;
|
||||
|
||||
overflow: hidden;
|
||||
background-color: #e6e6e6;
|
||||
|
||||
@keyframes fillIn {
|
||||
from { width: 50%; }
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 100%;
|
||||
|
||||
background-size: 100% 100%;
|
||||
|
||||
animation: 1s ease fillIn;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.skillset:nth-of-type(3n+1) .stack .level span{
|
||||
@include gradient1;
|
||||
}
|
||||
// .skillset:nth-of-type(3n+1),
|
||||
// .skillset:nth-of-type(3n+3) {
|
||||
// margin-top: 5rem;
|
||||
// }
|
||||
.skillset:nth-of-type(3n+2) .stack .level span{
|
||||
@include gradient2;
|
||||
}
|
||||
.skillset:nth-of-type(3n+3) .stack .level span{
|
||||
@include gradient3;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
#skills .skillset .stack .label i {
|
||||
font-style: normal;
|
||||
opacity: 0.3;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,317 @@
|
|||
<template>
|
||||
<div id='timeline'>
|
||||
|
||||
<template class='project' v-for='(proj) of projects'>
|
||||
<div :key="'start-'+proj.name" class='start'>
|
||||
{{ proj.started_at | short_date }}
|
||||
</div>
|
||||
|
||||
<img :key="'name-icon-'+proj.name" class='name-icon' src='../assets/timeline/project.svg'/>
|
||||
<div :key="'name-'+proj.name" class='name'>
|
||||
Created <b>{{ proj.name }}</b> <span>{{ proj.started_at | date_diff }} ago</span>
|
||||
</div>
|
||||
|
||||
<img :key="'skill-icon-'+proj.name" class='skill-icon' src='../assets/timeline/skills.svg' />
|
||||
<div :key="'skillset-'+proj.name" class='skillset'>
|
||||
<span v-for='(skill) of proj.skills' :key='skill' v-html='skills[skill].name'></span>
|
||||
</div>
|
||||
|
||||
<img :key="'desc-icon-'+proj.name" class='desc-icon' src='../assets/timeline/info.svg' />
|
||||
<div :key="'desc-'+proj.name" class='desc' v-html='proj.info'></div>
|
||||
|
||||
<template v-if='proj.source != null'>
|
||||
<img :key="'src-icon-'+proj.name" class='src-icon' src='../assets/timeline/src.svg' />
|
||||
<div :key="'src-'+proj.name" class='src' >
|
||||
Hosted at <a :href='proj.source.link'>{{ proj.source.name }}</a> <span>({{ proj.commits }} commits)</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if='proj.doc != null'>
|
||||
<img :key="'doc-icon-'+proj.name" class='doc-icon' src='../assets/timeline/doc.svg' />
|
||||
<div :key="'doc-'+proj.name" class='doc'>
|
||||
Documentation at <a :href='proj.doc.link'>{{ proj.doc.name }}</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<img :key="'end-icon-'+proj.name" class='end-icon' src='../assets/timeline/activity.svg' />
|
||||
<div :key="'end-'+proj.name" class='end'>
|
||||
<template v-if='proj.stopped_at != null'>
|
||||
Project stopped in {{ proj.stopped_at | short_date }} <span>{{ proj.stopped_at | date_diff }} ago</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
Project still active
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from 'vue-property-decorator';
|
||||
import { Projects, Project } from '../model/projects';
|
||||
import { Skills, tSkills } from '../model/skills';
|
||||
|
||||
function pluralize(n: number, s: string): string {
|
||||
n = Math.floor(Math.abs(n));
|
||||
const plural = (n > 1);
|
||||
|
||||
switch(s){
|
||||
case 'second':
|
||||
return plural ? `${n} seconds` : `1 second`;
|
||||
case 'minute':
|
||||
return plural ? `${n} minutes` : `1 minute`;
|
||||
case 'day':
|
||||
return plural ? `${n} days` : `1 day`;
|
||||
case 'month':
|
||||
return plural ? `${n} months` : `1 month`;
|
||||
case 'year':
|
||||
return plural ? `${n} years` : `1 year`;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Component({
|
||||
filters: {
|
||||
short_date: function(date: Date): string {
|
||||
return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
|
||||
},
|
||||
date_diff: function(date: Date): string {
|
||||
const minute = 60*1000;
|
||||
const hour = 60*minute;
|
||||
const day = 24*hour;
|
||||
const month = 30*day;
|
||||
const year = 365*day;
|
||||
|
||||
let now = new Date();
|
||||
let diff = now.getTime() - date.getTime();
|
||||
|
||||
if( diff < 0 ){
|
||||
return "sometime";
|
||||
}
|
||||
|
||||
if( diff < minute ){
|
||||
return pluralize(diff, 'second');
|
||||
}
|
||||
if( diff < hour ){
|
||||
return pluralize(diff/minute, 'minute');
|
||||
}
|
||||
if( diff < day ){
|
||||
return pluralize(diff/hour, 'hour');
|
||||
}
|
||||
if( diff < month ){
|
||||
return pluralize(diff/day, 'day');
|
||||
}
|
||||
if( diff < year ){
|
||||
return pluralize(diff/month, 'month');
|
||||
}
|
||||
return pluralize(diff/year, 'year');
|
||||
}
|
||||
}
|
||||
})
|
||||
export default class Timeline extends Vue {
|
||||
private projects: Project[] = Projects;
|
||||
private skills: tSkills = Skills;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
@import '../global';
|
||||
|
||||
$icon-width: 2.3rem;
|
||||
$space-width: 1rem;
|
||||
|
||||
#timeline {
|
||||
display: grid;
|
||||
position: relative;
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
|
||||
grid-template-columns: auto $icon-width $icon-width $space-width auto;
|
||||
grid-gap: .5em;
|
||||
|
||||
font-size: 1.6rem;
|
||||
font-weight: 400;
|
||||
color: #fff;
|
||||
background: #161619;
|
||||
|
||||
padding: 0 5rem;
|
||||
|
||||
padding-top: 2em;
|
||||
|
||||
.start { grid-column: 1 / 2; }
|
||||
.name { grid-column: 3 / 6; }
|
||||
.skillset, .desc, .src, .doc, .end {
|
||||
grid-column: 5 / 6;
|
||||
}
|
||||
.name-icon { grid-column: 2 / 3; }
|
||||
.skill-icon, .desc-icon, .src-icon, .doc-icon, .end-icon {
|
||||
grid-column: 3 / 4;
|
||||
}
|
||||
|
||||
.skill-icon, .desc-icon, .src-icon, .doc-icon, .end-icon {
|
||||
position: relative;
|
||||
|
||||
width: #{$icon-width + .3rem};
|
||||
height: #{$icon-width + .3rem};
|
||||
margin-top: .3rem;
|
||||
|
||||
background: #161619;
|
||||
}
|
||||
.src-icon, .doc-icon, .end-icon {
|
||||
position: relative;
|
||||
|
||||
width: #{$icon-width + .1rem};
|
||||
height: #{$icon-width + .1rem};
|
||||
margin-top: .1rem;
|
||||
|
||||
background: #161619;
|
||||
}
|
||||
|
||||
.start {
|
||||
font-size: .8em;
|
||||
color: #535359;
|
||||
padding-top: .3em;
|
||||
}
|
||||
|
||||
.name-icon {
|
||||
position: relative;
|
||||
|
||||
width: #{$icon-width + .2rem};
|
||||
height: #{$icon-width + .2rem};
|
||||
|
||||
padding-top: -.2rem;
|
||||
|
||||
background: #161619;
|
||||
}
|
||||
.name, .end {
|
||||
b {
|
||||
color: #2c55cf;
|
||||
}
|
||||
|
||||
span {
|
||||
position: relative;
|
||||
|
||||
font-size: .8em;
|
||||
color: #4d4d4d;
|
||||
|
||||
margin-left: .5em;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin-bottom: .15em;
|
||||
margin-right: .5em;
|
||||
width: .3em;
|
||||
height: .3em;
|
||||
|
||||
background: #606060;
|
||||
|
||||
border-radius: 50% / 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.name {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.skillset {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
|
||||
span {
|
||||
font-size: .8em;
|
||||
padding: .4em .6em;
|
||||
margin-right: .4em;
|
||||
margin-bottom: .4em;
|
||||
|
||||
color: #fff;
|
||||
background: #28282d;
|
||||
|
||||
border-radius: .4em / .4em;
|
||||
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 50vw;
|
||||
|
||||
font-size: .8em;
|
||||
|
||||
padding: 1em;
|
||||
padding-bottom: 2em;
|
||||
margin-bottom: 1.5em;
|
||||
|
||||
background: #28282d;
|
||||
|
||||
border: .1rem solid #2f2f33;
|
||||
border-radius: .4em / .4em;
|
||||
z-index: 100;
|
||||
|
||||
transform-style: preserve-3d;
|
||||
|
||||
&:before, &:after {
|
||||
content: '';
|
||||
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: .6em;
|
||||
left: .6em;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
background: #202024;
|
||||
border: .1rem solid #2f2f33;
|
||||
border-radius: .4em / .4em;
|
||||
|
||||
transform: translateZ(-1px);
|
||||
}
|
||||
&:before {
|
||||
top: 1.2em;
|
||||
left: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
.src, .doc {
|
||||
color: #999999;
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
color: #fff;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
|
||||
display: block;
|
||||
position: absolute;
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
height: .15rem;
|
||||
|
||||
background: #3333be;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
margin-left: .5em;
|
||||
color: #4d4d4d;
|
||||
}
|
||||
}
|
||||
|
||||
.end {
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,73 @@
|
|||
import { tID as s } from './skills';
|
||||
|
||||
export interface Link {
|
||||
name: string;
|
||||
link: string;
|
||||
}
|
||||
|
||||
export interface Project {
|
||||
name: string;
|
||||
skills: s[];
|
||||
client: string|null;
|
||||
started_at: Date;
|
||||
stopped_at: Date|null;
|
||||
info: string;
|
||||
source: Link|null;
|
||||
doc: Link|null;
|
||||
commits: number;
|
||||
}
|
||||
|
||||
export const Projects: Project[] = [
|
||||
{
|
||||
name: 'Angular module system',
|
||||
client: 'Marlink',
|
||||
skills: [s.Angular, s.RnD, s.Concurrency, s.Html, s.Css, s.Inkscape, s.UIUX, s.Ts, s.Js, s.Ajax, s.Cordova, s.Bash, s.Git, s.Rest, s.Rpm, s.Vue, s.Web, s.Docker],
|
||||
started_at: new Date(2019, 10, 26),
|
||||
stopped_at: new Date(2021, 4, 11),
|
||||
info: 'Prototype for a front-end Angular modular system. I technically and visually designed a kind of app store. Hacked angular to allow injecting custom pages and code on-the-go.',
|
||||
source: null, doc: null,
|
||||
commits: 0, // ???
|
||||
},
|
||||
{
|
||||
name: 'EarthMap',
|
||||
client: 'Collins Aerospace',
|
||||
skills: [s.Qt, s.RnD, s.Cpp, s.Concurrency, s.Git, s.Css, s.Inkscape, s.UIUX],
|
||||
started_at: new Date(2019, 10, 26),
|
||||
stopped_at: new Date(2021, 4, 11),
|
||||
info: 'TODO',
|
||||
source: null, doc: null,
|
||||
commits: 840,
|
||||
},
|
||||
{
|
||||
name: 'ADSBOnPED',
|
||||
client: 'Collins Aerospace',
|
||||
skills: [s.Qt, s.RnD, s.Cpp, s.Concurrency, s.Git, s.Css, s.Bash, s.Linux, s.Inkscape, s.UIUX],
|
||||
started_at: new Date(2020, 7, 16),
|
||||
stopped_at: null,
|
||||
info: 'TODO',
|
||||
source: null, doc: null,
|
||||
commits: 1897 + 62,
|
||||
},
|
||||
{
|
||||
name: 'EasyCom',
|
||||
client: 'Medwin | Vygon',
|
||||
skills: [s.Go, s.Rest, s.Concurrency, s.Git, s.Bash, s.Linux, s.Docker, s.Crypto, s.Postgres, s.Opti, s.Websocket, s.Inkscape, s.UIUX],
|
||||
started_at: new Date(2021, 1, 6),
|
||||
stopped_at: new Date(2022, 11, 1),
|
||||
info: 'TODO',
|
||||
source: null, doc: null,
|
||||
commits: 1260+90 + 41+1 + 12+1 + 14,
|
||||
},
|
||||
|
||||
{
|
||||
name: 'aicra',
|
||||
client: null,
|
||||
skills: [s.Go, s.Web, s.Rest, s.OpenSource, s.Git, s.Inkscape],
|
||||
started_at: new Date(2018, 5, 19),
|
||||
stopped_at: null, // still active
|
||||
info: 'Started as a personal go library to ease REST API development. The main goal is to greatly enhance maintainability by providing a single configuration file that describes every endpoint of the API. Everything that can be automated is while staying idiomatic to go. Aicra automates routing, parameter validation and extraction, permission management, response output formatting. I then used it for a professional project in the medical field after corporate evaluation and audit.',
|
||||
source: { name: 'github.com/xdrm-io/aicra', link: 'https://github.com/xdrm-io/aicra' },
|
||||
doc: { name: 'pkg.go.dev/github.com/xdrm-io/aicra', link: 'https://pkg.go.dev/github.com/xdrm-io/aicra' },
|
||||
commits: 535,
|
||||
},
|
||||
];
|
|
@ -1,41 +1,290 @@
|
|||
export default [
|
||||
{
|
||||
title: 'Web',
|
||||
keywords: [ 'languages', 'technologies' ],
|
||||
skills: [
|
||||
{ label: 'MariaDB', link: 'https://mariadb.org/', level: 0.6 },
|
||||
{ label: 'Postgres', link: 'https://postgresql.org/', level: 0.8 },
|
||||
{ label: 'MongoDB', link: 'https://mongodb.com/', level: 0.5 },
|
||||
{ label: 'Vue <i>(.js)</i>', link: 'https://vuejs.org/', level: 0.8 },
|
||||
{ label: 'Angular <i>(7+)</i>', link: 'https://angular.io/', level: 0.3 },
|
||||
{ label: 'WebGL', link: 'https://www.khronos.org/webgl/', level: 0.3 },
|
||||
{ label: 'Audio API', link: 'https://webaudio.github.io/web-audio-api/', level: 0.5 },
|
||||
{ label: 'Websocket', link: 'https://tools.ietf.org/html/rfc6455', level: 1 },
|
||||
],
|
||||
export enum tID {
|
||||
MariaDB,
|
||||
Postgres,
|
||||
Mongo,
|
||||
Vue,
|
||||
Angular,
|
||||
Parcel,
|
||||
Cordova,
|
||||
Webpack,
|
||||
WebGL,
|
||||
AudioAPI,
|
||||
Websocket,
|
||||
Docker,
|
||||
Bash,
|
||||
Linux,
|
||||
Systemd,
|
||||
Git,
|
||||
Rpm,
|
||||
RaspBerry,
|
||||
Arduino,
|
||||
Php,
|
||||
Html,
|
||||
Css,
|
||||
Js,
|
||||
Ajax,
|
||||
Ts,
|
||||
C,
|
||||
Cpp,
|
||||
Python,
|
||||
Go,
|
||||
Qt,
|
||||
OpenSource,
|
||||
Electronics,
|
||||
Web,
|
||||
Rest,
|
||||
Crypto,
|
||||
ImageProcessing,
|
||||
AI,
|
||||
DeepLearning,
|
||||
NeuralNetwork,
|
||||
Opti,
|
||||
Sockets,
|
||||
Concurrency,
|
||||
UIUX,
|
||||
Inkscape,
|
||||
RnD,
|
||||
}
|
||||
|
||||
interface tSkill {
|
||||
icon: string;
|
||||
name: string;
|
||||
link: string;
|
||||
}
|
||||
|
||||
export type tSkills = { [id in tID]: tSkill };
|
||||
|
||||
export const Skills: tSkills = {
|
||||
[tID.MariaDB]: {
|
||||
name: 'MariaDB',
|
||||
link: 'https://mariadb.org',
|
||||
icon: 'skills/mariadb.svg',
|
||||
},
|
||||
{
|
||||
title: 'Sys',
|
||||
keywords: ['languages', 'technologies'],
|
||||
skills: [
|
||||
{ label: 'Linux/bash', link: 'https://www.gnu.org/software/bash/', level: 1 },
|
||||
{ label: 'docker', link: 'https://www.docker.com/', level: 0.8 },
|
||||
{ label: 'systemd', link: 'https://freedesktop.org/wiki/Software/systemd/', level: 1 },
|
||||
{ label: 'git', link: 'https://git-scm.com/', level: 0.8 },
|
||||
{ label: 'raspberry', link: 'https://www.raspberrypi.org/', level: 0.8 },
|
||||
{ label: 'arduino', link: 'https://www.arduino.cc/', level: 0.5 },
|
||||
{ label: 'RPM packaging', link: 'https://rpm.org/', level: 0.7 },
|
||||
],
|
||||
[tID.Postgres]: {
|
||||
name: 'PostgreSQL',
|
||||
link: 'https://postgresql.org',
|
||||
icon: 'skills/postgres.svg',
|
||||
},
|
||||
{
|
||||
title: 'Misc',
|
||||
keywords: ['frameworks', 'api', 'dependencies'],
|
||||
skills: [
|
||||
{ label: 'PHP', link: 'https://www.php.net/', level: 0.9 },
|
||||
{ label: 'HTML<i>/</i>CSS', link: 'https://www.w3.org/standards/webdesign/htmlcss', level: 1 },
|
||||
{ label: 'Typescript', link: 'https://www.typescriptlang.org/', level: 0.6 },
|
||||
{ label: 'C<i>/</i>C++', link: 'https://isocpp.org/', level: 0.8 },
|
||||
{ label: 'Python', link: 'https://www.python.org/', level: 0.3 },
|
||||
{ label: 'go', link: 'https://golang.org/', level: 1 },
|
||||
],
|
||||
[tID.Mongo]: {
|
||||
name: 'MongoDB',
|
||||
link: 'https://mongodb.com',
|
||||
icon: 'skills/mongo.svg',
|
||||
},
|
||||
];
|
||||
|
||||
[tID.Vue]: {
|
||||
name: 'Vue <i>(.js)</i>',
|
||||
link: 'https://vuejs.org',
|
||||
icon: 'skills/vue.svg',
|
||||
},
|
||||
[tID.Angular]: {
|
||||
name: 'Angular <i>(7+)</i>',
|
||||
link: 'https://angular.io',
|
||||
icon: 'skills/angular.svg',
|
||||
},
|
||||
[tID.Parcel]: {
|
||||
name: 'Parcel',
|
||||
link: 'https://parceljs.org/',
|
||||
icon: 'skills/parcel.svg',
|
||||
},
|
||||
[tID.Cordova]: {
|
||||
name: 'Apache Cordova',
|
||||
link: 'https://cordova.apache.org/',
|
||||
icon: 'skills/cordova.svg',
|
||||
},
|
||||
[tID.Webpack]: {
|
||||
name: 'Webpack',
|
||||
link: 'https://webpack.js.org/',
|
||||
icon: 'skills/webpack.svg',
|
||||
},
|
||||
|
||||
[tID.WebGL]: {
|
||||
name: 'WebGL',
|
||||
link: 'https://www.khronos.org/webgl/',
|
||||
icon: 'skills/web-gl.svg',
|
||||
},
|
||||
[tID.AudioAPI]: {
|
||||
name: 'Audio API',
|
||||
link: 'https://webaudio.github.io/web-audio-api/',
|
||||
icon: 'skills/audio-api.svg',
|
||||
},
|
||||
[tID.Websocket]: {
|
||||
name: 'Websocket',
|
||||
link: 'https://tools.ietf.org/html/rfc6455',
|
||||
icon: 'skills/websocket.svg',
|
||||
},
|
||||
|
||||
[tID.Docker]: {
|
||||
name: 'Docker',
|
||||
link: 'https://docker.com',
|
||||
icon: 'skills/docker.svg',
|
||||
},
|
||||
[tID.Bash]: {
|
||||
name: 'bash',
|
||||
link: 'https://www.gnu.org/software/bash/',
|
||||
icon: 'skills/bash.svg',
|
||||
},
|
||||
[tID.Linux]: {
|
||||
name: 'GNU/Linux',
|
||||
link: 'https://www.linux.org',
|
||||
icon: 'skills/linux.svg',
|
||||
},
|
||||
[tID.Systemd]: {
|
||||
name: 'systemd',
|
||||
link: 'https://freedesktop.org/wiki/Software/systemd/',
|
||||
icon: 'skills/systemd.svg',
|
||||
},
|
||||
[tID.Git]: {
|
||||
name: 'Git',
|
||||
link: 'https://git-scm.com/',
|
||||
icon: 'skills/git.svg',
|
||||
},
|
||||
[tID.Rpm]: {
|
||||
name: 'RPM packaging',
|
||||
link: 'https://rpm.org/',
|
||||
icon: 'skills/rpm.svg',
|
||||
},
|
||||
|
||||
[tID.RaspBerry]: {
|
||||
name: 'Raspberry',
|
||||
link: 'https://raspberrypi.org',
|
||||
icon: 'skills/raspberry.svg',
|
||||
},
|
||||
[tID.Arduino]: {
|
||||
name: 'Arduino',
|
||||
link: 'https://arduino.cc',
|
||||
icon: 'skills/arduino.svg',
|
||||
},
|
||||
|
||||
[tID.Php]: {
|
||||
name: 'PHP',
|
||||
link: 'https://www.php.net',
|
||||
icon: 'skills/php.svg',
|
||||
},
|
||||
[tID.Html]: {
|
||||
name: 'HTML5',
|
||||
link: 'https://www.w3.org/standards/webdesign/htmlcss',
|
||||
icon: 'skills/html.svg',
|
||||
},
|
||||
[tID.Css]: {
|
||||
name: 'CSS3',
|
||||
link: 'https://www.w3.org/standards/webdesign/htmlcss',
|
||||
icon: 'skills/css.svg',
|
||||
},
|
||||
[tID.Js]: {
|
||||
name: 'Javascript',
|
||||
link: 'http://www.ecma-international.org/publications-and-standards/standards/ecma-262/',
|
||||
icon: 'skills/js.svg',
|
||||
},
|
||||
[tID.Ajax]: {
|
||||
name: 'AJAX',
|
||||
link: 'https://www.w3schools.com/xml/ajax_intro.asp',
|
||||
icon: 'skills/ajax.svg',
|
||||
},
|
||||
[tID.Ts]: {
|
||||
name: 'Typescript',
|
||||
link: 'https://www.typescript.org/',
|
||||
icon: 'skills/ts.svg',
|
||||
},
|
||||
[tID.C]: {
|
||||
name: 'C (lang)',
|
||||
link: 'https://www.open-std.org/jtc1/sc22/wg14/',
|
||||
icon: 'skills/c.svg',
|
||||
},
|
||||
[tID.Cpp]: {
|
||||
name: 'C++',
|
||||
link: 'https://isocpp.org/',
|
||||
icon: 'skills/cpp.svg',
|
||||
},
|
||||
[tID.Python]: {
|
||||
name: 'Python',
|
||||
link: 'https://python.org/',
|
||||
icon: 'skills/python.svg',
|
||||
},
|
||||
[tID.Go]: {
|
||||
name: 'Go (lang)',
|
||||
link: 'https://go.dev',
|
||||
icon: 'skills/go.svg',
|
||||
},
|
||||
|
||||
[tID.Qt]: {
|
||||
name: 'Qt',
|
||||
link: 'https://qt.io',
|
||||
icon: 'skills/qt.svg',
|
||||
},
|
||||
|
||||
[tID.OpenSource]: {
|
||||
name: 'Open-source',
|
||||
link: 'https://opensource.org/',
|
||||
icon: 'skills/open-source.svg',
|
||||
},
|
||||
[tID.Electronics]: {
|
||||
name: 'Electronics',
|
||||
link: 'https://en.wikipedia.org/wiki/Electronics',
|
||||
icon: 'skills/electronics.svg',
|
||||
},
|
||||
[tID.Web]: {
|
||||
name: 'Web',
|
||||
link: 'https://en.wikipedia.org/wiki/World_Wide_Web',
|
||||
icon: 'skills/web.svg',
|
||||
},
|
||||
[tID.Rest]: {
|
||||
name: 'REST',
|
||||
link: 'https://en.wikipedia.org/wiki/Representational_state_transfer',
|
||||
icon: 'skills/rest.svg',
|
||||
},
|
||||
[tID.Crypto]: {
|
||||
name: 'Cryptography',
|
||||
link: 'https://en.wikipedia.org/wiki/Cryptography',
|
||||
icon: 'skills/crypto.svg',
|
||||
},
|
||||
[tID.ImageProcessing]: {
|
||||
name: 'Image processing',
|
||||
link: 'https://en.wikipedia.org/wiki/Digital_image_processing',
|
||||
icon: 'skills/image-processing.svg',
|
||||
},
|
||||
[tID.AI]: {
|
||||
name: 'Artificial Intelligence',
|
||||
link: 'https://en.wikipedia.org/wiki/Artificial_intelligence',
|
||||
icon: 'skills/ai.svg',
|
||||
},
|
||||
[tID.DeepLearning]: {
|
||||
name: 'Deep Learning',
|
||||
link: 'https://en.wikipedia.org/wiki/Deep_learning',
|
||||
icon: 'skills/deep-learning.svg',
|
||||
},
|
||||
[tID.NeuralNetwork]: {
|
||||
name: 'Neural Networks',
|
||||
link: 'https://en.wikipedia.org/wiki/Artificial_neural_network',
|
||||
icon: 'skills/neural-network.svg',
|
||||
},
|
||||
[tID.Opti]: {
|
||||
name: 'Program optimization',
|
||||
link: 'https://en.wikipedia.org/wiki/Program_optimization',
|
||||
icon: 'skills/opti.svg',
|
||||
},
|
||||
[tID.Sockets]: {
|
||||
name: 'Sockets',
|
||||
link: 'https://en.wikipedia.org/wiki/Computer_network_programming',
|
||||
icon: 'skills/sockets.svg',
|
||||
},
|
||||
[tID.Concurrency]: {
|
||||
name: 'Concurrent programming',
|
||||
link: 'https://en.wikipedia.org/wiki/Concurrent_computing',
|
||||
icon: 'skills/concurrency.svg',
|
||||
},
|
||||
[tID.UIUX]: {
|
||||
name: 'UI/UX',
|
||||
link: 'https://en.wikipedia.org/wiki/UX',
|
||||
icon: 'skills/ux.svg',
|
||||
},
|
||||
[tID.Inkscape]: {
|
||||
name: 'Inkscape',
|
||||
link: 'https://inkscape.org/',
|
||||
icon: 'skills/inkscape.svg',
|
||||
},
|
||||
[tID.RnD]: {
|
||||
name: 'R&D',
|
||||
link: 'https://en.wikipedia.org/wiki/R&D',
|
||||
icon: 'skills/rnd.svg',
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue