Compare commits
No commits in common. "60345a5f263374eba71012598667c8f017beb2bd" and "d154d27c37224d983541d72c249b59bafdd87f02" have entirely different histories.
60345a5f26
...
d154d27c37
31
src/App.vue
31
src/App.vue
|
@ -42,35 +42,4 @@ export default class App extends Vue {
|
||||||
|
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
color: #fff;
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:visited {
|
|
||||||
color: #fefefa;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
content: '';
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
margin-left: 5%;
|
|
||||||
width: 90%;
|
|
||||||
height: .15rem;
|
|
||||||
|
|
||||||
background: #3333be;
|
|
||||||
|
|
||||||
transition: width .2s ease-in-out, margin-left .2s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover:after {
|
|
||||||
margin-left: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -9,13 +9,12 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||||
import { tID } from '@/model/skills';
|
import { tID, Skills } from '@/model/skills';
|
||||||
import * as skills from '@/service/skills';
|
|
||||||
|
|
||||||
@Component({})
|
@Component({})
|
||||||
export default class SkillCard extends Vue {
|
export default class SkillCard extends Vue {
|
||||||
// id of the skill to display (string representation)
|
// id of the skill to display (string representation)
|
||||||
@Prop(Number) readonly id: tID|undefined;
|
@Prop(String) readonly id: string|undefined;
|
||||||
|
|
||||||
// undefined -> automatic size
|
// undefined -> automatic size
|
||||||
// value -> fixed size applied (valid css value with unit)
|
// value -> fixed size applied (valid css value with unit)
|
||||||
|
@ -24,9 +23,7 @@
|
||||||
// whether it has the active style
|
// whether it has the active style
|
||||||
@Prop(Boolean) active: boolean|undefined;
|
@Prop(Boolean) active: boolean|undefined;
|
||||||
|
|
||||||
// folder name to display instead of a skill to fetch
|
// whether id is a folder name to display
|
||||||
// not empty -> used as displayed folder name
|
|
||||||
// empty -> this.id is used to fetch the skill
|
|
||||||
@Prop(String) folder: string|undefined;
|
@Prop(String) folder: string|undefined;
|
||||||
|
|
||||||
protected mounted() {
|
protected mounted() {
|
||||||
|
@ -37,40 +34,40 @@
|
||||||
el.style.width = this.width;
|
el.style.width = this.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected icon(): string {
|
private tid(): tID|null {
|
||||||
const unknown = () => require('../assets/skills/unknown.svg');
|
|
||||||
|
|
||||||
if( this.id == undefined ){
|
if( this.id == undefined ){
|
||||||
return unknown();
|
return null;
|
||||||
|
}
|
||||||
|
const id = parseInt(this.id!) as tID;
|
||||||
|
if( Skills[id] == undefined ){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( this.folder != undefined ){
|
protected icon(): string {
|
||||||
|
if( this.folder == '1' ){
|
||||||
return require('../assets/skills/folder.svg');
|
return require('../assets/skills/folder.svg');
|
||||||
}
|
}
|
||||||
const skill = skills.get(this.id);
|
let icon: string|null = null;
|
||||||
if( skill == null ){
|
if( this.tid() != undefined ){
|
||||||
return unknown();
|
icon = Skills[this.tid()!].icon;
|
||||||
}
|
}
|
||||||
|
if( icon == null ){
|
||||||
if( skill.icon == null ){
|
return require('../assets/skills/unknown.svg');
|
||||||
return unknown();
|
|
||||||
}
|
}
|
||||||
return require(`../assets/${skill.icon}`);
|
return require(`../assets/${icon}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected name(): string {
|
protected name(): string {
|
||||||
if( this.folder != undefined ){
|
if( this.folder == '1' ){
|
||||||
return this.folder;
|
return this.id!;
|
||||||
|
}
|
||||||
|
if( this.tid() != undefined ){
|
||||||
|
return Skills[this.tid()!].name!;
|
||||||
}
|
}
|
||||||
if( this.id == undefined ){
|
|
||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
const skill = skills.get(this.id);
|
|
||||||
if( skill == null ){
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
return skill.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
private onClick(e: MouseEvent) {
|
private onClick(e: MouseEvent) {
|
||||||
this.$emit('pick', !this.active);
|
this.$emit('pick', !this.active);
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
<section class='categories'>
|
<section class='categories'>
|
||||||
<SkillCard v-for='(t) of tags'
|
<SkillCard v-for='(t) of tags'
|
||||||
:key='t'
|
:key='t'
|
||||||
|
:id='t'
|
||||||
:active='t == tag'
|
:active='t == tag'
|
||||||
:folder='t'
|
folder='1'
|
||||||
width='18rem'
|
width='18rem'
|
||||||
@pick='onTag(t, $event)'/>
|
@pick='onTag(t, $event)'/>
|
||||||
</section>
|
</section>
|
||||||
|
@ -15,28 +16,13 @@
|
||||||
<section class='skills'>
|
<section class='skills'>
|
||||||
<SkillCard v-for='(id) of ids'
|
<SkillCard v-for='(id) of ids'
|
||||||
:key='id'
|
:key='id'
|
||||||
v-show='filtered.indexOf(id) >= 0'
|
v-show='hide.indexOf(id) < 0'
|
||||||
:id='id'
|
:id='id'
|
||||||
:active='id == sel'
|
:active='id == sel'
|
||||||
width='18rem'
|
width='18rem'
|
||||||
@pick='onPick(id, $event)' />
|
@pick='onPick(id, $event)' />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class='details' v-if='details != null'>
|
|
||||||
<img :src='details.icon'/>
|
|
||||||
<h1 v-html='details.title'></h1>
|
|
||||||
<h2>Featured in <b>{{ details.projects.length }}</b> {{ details.projects.length > 1 ? 'projects' : 'project' }}</h2>
|
|
||||||
<h3>
|
|
||||||
<template v-for='(proj, i) of details.projects'>
|
|
||||||
<a :key='proj.name' :href='"#p-" + proj.name'>
|
|
||||||
{{ proj.name }}
|
|
||||||
</a>
|
|
||||||
<span :key='proj.name'>, </span>
|
|
||||||
</template>
|
|
||||||
</h3>
|
|
||||||
<p v-html='details.text'></p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type='button' v-show='this.sel != null' value='Browse projects' @click='browse()'/>
|
<input type='button' v-show='this.sel != null' value='Browse projects' @click='browse()'/>
|
||||||
|
@ -47,17 +33,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from 'vue-property-decorator';
|
import { Component, Vue } from 'vue-property-decorator';
|
||||||
import SkillCard from './SkillCard.vue';
|
import SkillCard from './SkillCard.vue';
|
||||||
import { tID } from '@/model/skills';
|
import { tID, Skills } from '@/model/skills';
|
||||||
import { Project } from '@/model/projects';
|
|
||||||
import * as skills from '@/service/skills';
|
|
||||||
import * as projects from '@/service/projects';
|
|
||||||
|
|
||||||
interface Details {
|
|
||||||
icon: string|null;
|
|
||||||
title: string;
|
|
||||||
projects: Project[];
|
|
||||||
text: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
|
@ -66,38 +42,52 @@
|
||||||
})
|
})
|
||||||
export default class SkillPicker extends Vue {
|
export default class SkillPicker extends Vue {
|
||||||
// list of available skills
|
// list of available skills
|
||||||
readonly ids: tID[] = skills.available();
|
readonly ids: string[] = Object.keys(Skills);
|
||||||
// currently selected skill
|
// currently selected skill
|
||||||
private sel: tID|null = tID.Vue;
|
private sel: string|null = tID.Vue.toString();
|
||||||
|
|
||||||
// list of ids to display according to the current tag
|
// list of ids to hide according to the current tag
|
||||||
private filtered: tID[] = [];
|
private hide: string[] = [];
|
||||||
|
|
||||||
// available categories (tags)
|
// available categories (tags)
|
||||||
private tags: string[] = skills.tags();
|
private tags: string[] = [];
|
||||||
// currently selected tag
|
// currently selected tag
|
||||||
private tag: string|null = "web";
|
private tag: string|null = "web";
|
||||||
|
|
||||||
// details section when a skill is selected
|
|
||||||
private details: Details|null = null;
|
|
||||||
|
|
||||||
private mounted() {
|
private mounted() {
|
||||||
|
this.tags = this.fetchTags();
|
||||||
this.filterByTag();
|
this.filterByTag();
|
||||||
this.loadDetails(this.sel!);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected onPick(id: tID, picked: boolean){
|
private fetchTags(): string[] {
|
||||||
|
const tags: string[] = [];
|
||||||
|
|
||||||
|
for( const sid of this.ids ){
|
||||||
|
const id = parseInt(sid) as tID;
|
||||||
|
const skill = Skills[id];
|
||||||
|
if( skill == undefined ){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for( const tag of skill.tags ){
|
||||||
|
if( tags.indexOf(tag) < 0 ){
|
||||||
|
tags.push(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
private onPick(id: string, picked: boolean){
|
||||||
if( picked ){ // select
|
if( picked ){ // select
|
||||||
this.sel = id;
|
this.sel = id;
|
||||||
this.loadDetails(id);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// deselect
|
if( !picked && id == this.sel ){ // deselect
|
||||||
this.sel = null;
|
this.sel = null;
|
||||||
this.details = null;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
protected onTag(t: string, picked: boolean){
|
private onTag(t: string, picked: boolean){
|
||||||
if( picked ){ // select
|
if( picked ){ // select
|
||||||
this.tag = t;
|
this.tag = t;
|
||||||
this.filterByTag();
|
this.filterByTag();
|
||||||
|
@ -113,48 +103,44 @@
|
||||||
// apply filter by tag
|
// apply filter by tag
|
||||||
private filterByTag(){
|
private filterByTag(){
|
||||||
const tag = this.tag;
|
const tag = this.tag;
|
||||||
if( tag == null ){
|
|
||||||
|
// no folder selected -> hide everything
|
||||||
|
if( tag == null || this.tags.indexOf(tag) < 0 ){
|
||||||
this.tag = null;
|
this.tag = null;
|
||||||
this.filtered = [];
|
this.hide = this.ids;
|
||||||
} else {
|
|
||||||
this.filtered = skills.filtered(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
// deselect if selection has been filtered out
|
// deselect if selection has been filtered out
|
||||||
if( this.sel != null && this.filtered.indexOf(this.sel) < 0 ){
|
if( this.sel != null && this.hide.indexOf(this.sel) >= 0 ){
|
||||||
|
this.sel = null;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear filter
|
||||||
|
this.hide = [];
|
||||||
|
|
||||||
|
for( const sid of this.ids ){
|
||||||
|
const id = parseInt(sid) as tID;
|
||||||
|
const skill = Skills[id];
|
||||||
|
if( skill == undefined ){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if( skill.tags.indexOf(tag) < 0 ){
|
||||||
|
this.hide.push(sid);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// deselect if selection has been filtered out
|
||||||
|
if( this.sel != null && this.hide.indexOf(this.sel) >= 0 ){
|
||||||
this.sel = null;
|
this.sel = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loads details about a skill
|
|
||||||
private loadDetails(id: tID){
|
|
||||||
const skill = skills.get(id);
|
|
||||||
if( skill == null ){
|
|
||||||
this.details = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let icon: string|null = null;
|
|
||||||
if( skill.icon != null ){
|
|
||||||
icon = require(`../assets/${skill.icon}`);
|
|
||||||
}
|
|
||||||
this.details = {
|
|
||||||
icon: icon,
|
|
||||||
title: skill.name,
|
|
||||||
projects: projects.bySkill(id),
|
|
||||||
text: skill.info
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
protected browse(){
|
protected browse(){
|
||||||
const el = document.querySelector('#timeline');
|
document.querySelector("#timeline")!.scrollIntoView();
|
||||||
if( el != null ){
|
|
||||||
el.scrollIntoView();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
@ -191,10 +177,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.categories {
|
.categories {
|
||||||
flex: 20em 0 0;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: 20em;
|
||||||
|
|
||||||
flex-flow: column nowrap;
|
flex-flow: column nowrap;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
@ -209,10 +194,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.skills {
|
.skills {
|
||||||
flex: 20em 0 0;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: 20em;
|
||||||
|
|
||||||
flex-flow: column nowrap;
|
flex-flow: column nowrap;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
@ -226,77 +210,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.details {
|
|
||||||
flex: auto;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
margin: auto;
|
|
||||||
|
|
||||||
flex-flow: column nowrap;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
img {
|
|
||||||
display: block;
|
|
||||||
flex: 8em 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 4em;
|
|
||||||
color: #cacaca;
|
|
||||||
|
|
||||||
i { display: none; }
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
margin-top: .3em;
|
|
||||||
|
|
||||||
font-size: 1.8em;
|
|
||||||
color: #616c7c;
|
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
b { color: #fff; }
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
margin-top: .8em;
|
|
||||||
|
|
||||||
font-size: 1.3em;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #616c7c;
|
|
||||||
|
|
||||||
& > span:last-child {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
|
|
||||||
flex: auto 0 1;
|
|
||||||
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
margin: 0 2em;
|
|
||||||
margin-top: 2em;
|
|
||||||
margin-bottom: 4rem;
|
|
||||||
|
|
||||||
font-size: 1.7em;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #c1c1c1;
|
|
||||||
padding: 1em;
|
|
||||||
|
|
||||||
background: #323841;
|
|
||||||
border: .1rem solid #45454b;
|
|
||||||
border-radius: .4em / .4em;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
input {
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template class='project' v-for='(proj) of projects'>
|
<template class='project' v-for='(proj) of projects'>
|
||||||
<!-- id is used for navigation -->
|
<div :key="'start-'+proj.name" class='start'>
|
||||||
<div :key="'start-'+proj.name" class='start' :id='"p-" + proj.name'>
|
|
||||||
{{ proj.started_at | short_date }}
|
{{ proj.started_at | short_date }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -334,6 +333,24 @@
|
||||||
.src, .doc {
|
.src, .doc {
|
||||||
color: #999999;
|
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 {
|
span {
|
||||||
margin-left: .5em;
|
margin-left: .5em;
|
||||||
color: #4d4d4d;
|
color: #4d4d4d;
|
||||||
|
|
|
@ -46,12 +46,11 @@ export enum tID {
|
||||||
RnD,
|
RnD,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface tSkill {
|
interface tSkill {
|
||||||
icon: string|null;
|
icon: string|null;
|
||||||
name: string;
|
name: string;
|
||||||
link: string;
|
link: string;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
info: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type tSkills = { [id in tID]: tSkill };
|
export type tSkills = { [id in tID]: tSkill };
|
||||||
|
@ -62,21 +61,18 @@ export const Skills: tSkills = {
|
||||||
link: 'https://mariadb.org',
|
link: 'https://mariadb.org',
|
||||||
icon: 'skills/mariadb.svg',
|
icon: 'skills/mariadb.svg',
|
||||||
tags: ['web', 'storage'],
|
tags: ['web', 'storage'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Postgres]: {
|
[tID.Postgres]: {
|
||||||
name: 'PostgreSQL',
|
name: 'PostgreSQL',
|
||||||
link: 'https://postgresql.org',
|
link: 'https://postgresql.org',
|
||||||
icon: 'skills/postgres.svg',
|
icon: 'skills/postgres.svg',
|
||||||
tags: ['web', 'storage'],
|
tags: ['web', 'storage'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Mongo]: {
|
[tID.Mongo]: {
|
||||||
name: 'MongoDB',
|
name: 'MongoDB',
|
||||||
link: 'https://mongodb.com',
|
link: 'https://mongodb.com',
|
||||||
icon: 'skills/mongo.svg',
|
icon: 'skills/mongo.svg',
|
||||||
tags: ['web', 'storage'],
|
tags: ['web', 'storage'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
[tID.Vue]: {
|
[tID.Vue]: {
|
||||||
|
@ -84,35 +80,30 @@ export const Skills: tSkills = {
|
||||||
link: 'https://vuejs.org',
|
link: 'https://vuejs.org',
|
||||||
icon: 'skills/vue.svg',
|
icon: 'skills/vue.svg',
|
||||||
tags: ['web', 'UI'],
|
tags: ['web', 'UI'],
|
||||||
info: "I started learning Vue (.js) back in 2016, and never stopped practicing since then for personal and professional projects. I view it as a better alternative than angular which provides you with a strict framework that can lack flexibility among teams and projects.<br><br>Vue makes it your responsability to properly structure your project which I like to take care of myself, as it tends to provide a better workflow adjusted for every project.<br><br>It is my top choice when considering a web framework for rendering pages.",
|
|
||||||
},
|
},
|
||||||
[tID.Angular]: {
|
[tID.Angular]: {
|
||||||
name: 'Angular <i>(7+)</i>',
|
name: 'Angular <i>(7+)</i>',
|
||||||
link: 'https://angular.io',
|
link: 'https://angular.io',
|
||||||
icon: 'skills/angular.svg',
|
icon: 'skills/angular.svg',
|
||||||
tags: ['web', 'UI'],
|
tags: ['web', 'UI'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Parcel]: {
|
[tID.Parcel]: {
|
||||||
name: 'Parcel',
|
name: 'Parcel',
|
||||||
link: 'https://parceljs.org/',
|
link: 'https://parceljs.org/',
|
||||||
icon: 'skills/parcel.svg',
|
icon: 'skills/parcel.svg',
|
||||||
tags: ['web'],
|
tags: ['web'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Cordova]: {
|
[tID.Cordova]: {
|
||||||
name: 'Apache Cordova',
|
name: 'Apache Cordova',
|
||||||
link: 'https://cordova.apache.org/',
|
link: 'https://cordova.apache.org/',
|
||||||
icon: 'skills/cordova.svg',
|
icon: 'skills/cordova.svg',
|
||||||
tags: ['system', 'web', 'mobile'],
|
tags: ['system', 'web', 'mobile'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Webpack]: {
|
[tID.Webpack]: {
|
||||||
name: 'Webpack',
|
name: 'Webpack',
|
||||||
link: 'https://webpack.js.org/',
|
link: 'https://webpack.js.org/',
|
||||||
icon: 'skills/webpack.svg',
|
icon: 'skills/webpack.svg',
|
||||||
tags: ['web'],
|
tags: ['web'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
[tID.WebGL]: {
|
[tID.WebGL]: {
|
||||||
|
@ -120,21 +111,18 @@ export const Skills: tSkills = {
|
||||||
link: 'https://www.khronos.org/webgl/',
|
link: 'https://www.khronos.org/webgl/',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['web'],
|
tags: ['web'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.AudioAPI]: {
|
[tID.AudioAPI]: {
|
||||||
name: 'Audio API',
|
name: 'Audio API',
|
||||||
link: 'https://webaudio.github.io/web-audio-api/',
|
link: 'https://webaudio.github.io/web-audio-api/',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['web'],
|
tags: ['web'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Websocket]: {
|
[tID.Websocket]: {
|
||||||
name: 'Websocket',
|
name: 'Websocket',
|
||||||
link: 'https://tools.ietf.org/html/rfc6455',
|
link: 'https://tools.ietf.org/html/rfc6455',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['web', 'networking', 'IoT'],
|
tags: ['web', 'networking', 'IoT'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
[tID.Docker]: {
|
[tID.Docker]: {
|
||||||
|
@ -142,42 +130,36 @@ export const Skills: tSkills = {
|
||||||
link: 'https://docker.com',
|
link: 'https://docker.com',
|
||||||
icon: 'skills/docker.svg',
|
icon: 'skills/docker.svg',
|
||||||
tags: ['web', 'system'],
|
tags: ['web', 'system'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Bash]: {
|
[tID.Bash]: {
|
||||||
name: 'bash',
|
name: 'bash',
|
||||||
link: 'https://www.gnu.org/software/bash/',
|
link: 'https://www.gnu.org/software/bash/',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['system'],
|
tags: ['system'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Linux]: {
|
[tID.Linux]: {
|
||||||
name: 'GNU/Linux',
|
name: 'GNU/Linux',
|
||||||
link: 'https://www.linux.org',
|
link: 'https://www.linux.org',
|
||||||
icon: 'skills/linux.svg',
|
icon: 'skills/linux.svg',
|
||||||
tags: ['system'],
|
tags: ['system'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Systemd]: {
|
[tID.Systemd]: {
|
||||||
name: 'systemd',
|
name: 'systemd',
|
||||||
link: 'https://freedesktop.org/wiki/Software/systemd/',
|
link: 'https://freedesktop.org/wiki/Software/systemd/',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['system'],
|
tags: ['system'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Git]: {
|
[tID.Git]: {
|
||||||
name: 'Git',
|
name: 'Git',
|
||||||
link: 'https://git-scm.com/',
|
link: 'https://git-scm.com/',
|
||||||
icon: 'skills/git.svg',
|
icon: 'skills/git.svg',
|
||||||
tags: ['system', 'organization'],
|
tags: ['system', 'organization'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Rpm]: {
|
[tID.Rpm]: {
|
||||||
name: 'RPM packaging',
|
name: 'RPM packaging',
|
||||||
link: 'https://rpm.org/',
|
link: 'https://rpm.org/',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['system'],
|
tags: ['system'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
[tID.RaspBerry]: {
|
[tID.RaspBerry]: {
|
||||||
|
@ -185,14 +167,12 @@ export const Skills: tSkills = {
|
||||||
link: 'https://raspberrypi.org',
|
link: 'https://raspberrypi.org',
|
||||||
icon: 'skills/raspberry.svg',
|
icon: 'skills/raspberry.svg',
|
||||||
tags: ['system', 'IoT'],
|
tags: ['system', 'IoT'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Arduino]: {
|
[tID.Arduino]: {
|
||||||
name: 'Arduino',
|
name: 'Arduino',
|
||||||
link: 'https://arduino.cc',
|
link: 'https://arduino.cc',
|
||||||
icon: 'skills/arduino.svg',
|
icon: 'skills/arduino.svg',
|
||||||
tags: ['system', 'IoT'],
|
tags: ['system', 'IoT'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
[tID.Php]: {
|
[tID.Php]: {
|
||||||
|
@ -200,70 +180,60 @@ export const Skills: tSkills = {
|
||||||
link: 'https://www.php.net',
|
link: 'https://www.php.net',
|
||||||
icon: 'skills/php.svg',
|
icon: 'skills/php.svg',
|
||||||
tags: ['language', 'web', 'IoT'],
|
tags: ['language', 'web', 'IoT'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Html]: {
|
[tID.Html]: {
|
||||||
name: 'HTML5',
|
name: 'HTML5',
|
||||||
link: 'https://www.w3.org/standards/webdesign/htmlcss',
|
link: 'https://www.w3.org/standards/webdesign/htmlcss',
|
||||||
icon: 'skills/html.svg',
|
icon: 'skills/html.svg',
|
||||||
tags: ['language', 'web', 'UI'],
|
tags: ['language', 'web', 'UI'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Css]: {
|
[tID.Css]: {
|
||||||
name: 'CSS3',
|
name: 'CSS3',
|
||||||
link: 'https://www.w3.org/standards/webdesign/htmlcss',
|
link: 'https://www.w3.org/standards/webdesign/htmlcss',
|
||||||
icon: 'skills/css.svg',
|
icon: 'skills/css.svg',
|
||||||
tags: ['language', 'web', 'UI'],
|
tags: ['language', 'web', 'UI'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Js]: {
|
[tID.Js]: {
|
||||||
name: 'Javascript',
|
name: 'Javascript',
|
||||||
link: 'http://www.ecma-international.org/publications-and-standards/standards/ecma-262/',
|
link: 'http://www.ecma-international.org/publications-and-standards/standards/ecma-262/',
|
||||||
icon: 'skills/js.svg',
|
icon: 'skills/js.svg',
|
||||||
tags: ['language', 'web', 'UI'],
|
tags: ['language', 'web', 'UI'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Ajax]: {
|
[tID.Ajax]: {
|
||||||
name: 'AJAX',
|
name: 'AJAX',
|
||||||
link: 'https://www.w3schools.com/xml/ajax_intro.asp',
|
link: 'https://www.w3schools.com/xml/ajax_intro.asp',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['web', 'networking'],
|
tags: ['web', 'networking'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Ts]: {
|
[tID.Ts]: {
|
||||||
name: 'Typescript',
|
name: 'Typescript',
|
||||||
link: 'https://www.typescript.org/',
|
link: 'https://www.typescript.org/',
|
||||||
icon: 'skills/ts.svg',
|
icon: 'skills/ts.svg',
|
||||||
tags: ['language', 'web', 'UI'],
|
tags: ['language', 'web', 'UI'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.C]: {
|
[tID.C]: {
|
||||||
name: 'C (lang)',
|
name: 'C (lang)',
|
||||||
link: 'https://www.open-std.org/jtc1/sc22/wg14/',
|
link: 'https://www.open-std.org/jtc1/sc22/wg14/',
|
||||||
icon: 'skills/c.svg',
|
icon: 'skills/c.svg',
|
||||||
tags: ['language', 'system'],
|
tags: ['language', 'system'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Cpp]: {
|
[tID.Cpp]: {
|
||||||
name: 'C++',
|
name: 'C++',
|
||||||
link: 'https://isocpp.org/',
|
link: 'https://isocpp.org/',
|
||||||
icon: 'skills/cpp.svg',
|
icon: 'skills/cpp.svg',
|
||||||
tags: ['language', 'system'],
|
tags: ['language', 'system'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Python]: {
|
[tID.Python]: {
|
||||||
name: 'Python',
|
name: 'Python',
|
||||||
link: 'https://python.org/',
|
link: 'https://python.org/',
|
||||||
icon: 'skills/python.svg',
|
icon: 'skills/python.svg',
|
||||||
tags: ['language', 'system'],
|
tags: ['language', 'system'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Go]: {
|
[tID.Go]: {
|
||||||
name: 'Go (lang)',
|
name: 'Go (lang)',
|
||||||
link: 'https://go.dev',
|
link: 'https://go.dev',
|
||||||
icon: 'skills/go.svg',
|
icon: 'skills/go.svg',
|
||||||
tags: ['language', 'system', 'IoT', 'networking'],
|
tags: ['language', 'system', 'IoT', 'networking'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
[tID.Qt]: {
|
[tID.Qt]: {
|
||||||
|
@ -271,7 +241,6 @@ export const Skills: tSkills = {
|
||||||
link: 'https://qt.io',
|
link: 'https://qt.io',
|
||||||
icon: 'skills/qt.svg',
|
icon: 'skills/qt.svg',
|
||||||
tags: ['language', 'system', 'IoT', 'networking'],
|
tags: ['language', 'system', 'IoT', 'networking'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
[tID.OpenSource]: {
|
[tID.OpenSource]: {
|
||||||
|
@ -279,104 +248,89 @@ export const Skills: tSkills = {
|
||||||
link: 'https://opensource.org/',
|
link: 'https://opensource.org/',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['human'],
|
tags: ['human'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Electronics]: {
|
[tID.Electronics]: {
|
||||||
name: 'Electronics',
|
name: 'Electronics',
|
||||||
link: 'https://en.wikipedia.org/wiki/Electronics',
|
link: 'https://en.wikipedia.org/wiki/Electronics',
|
||||||
icon: 'skills/electronics.svg',
|
icon: 'skills/electronics.svg',
|
||||||
tags: ['other', 'IoT'],
|
tags: ['other', 'IoT'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Web]: {
|
[tID.Web]: {
|
||||||
name: 'Web',
|
name: 'Web',
|
||||||
link: 'https://en.wikipedia.org/wiki/World_Wide_Web',
|
link: 'https://en.wikipedia.org/wiki/World_Wide_Web',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['web'],
|
tags: ['web'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Rest]: {
|
[tID.Rest]: {
|
||||||
name: 'REST',
|
name: 'REST',
|
||||||
link: 'https://en.wikipedia.org/wiki/Representational_state_transfer',
|
link: 'https://en.wikipedia.org/wiki/Representational_state_transfer',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['web', 'networking'],
|
tags: ['web', 'networking'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Crypto]: {
|
[tID.Crypto]: {
|
||||||
name: 'Security/crypto',
|
name: 'Security/crypto',
|
||||||
link: 'https://en.wikipedia.org/wiki/Cryptography',
|
link: 'https://en.wikipedia.org/wiki/Cryptography',
|
||||||
icon: 'skills/security.svg',
|
icon: 'skills/security.svg',
|
||||||
tags: ['system', 'networking'],
|
tags: ['system', 'networking'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.ImageProcessing]: {
|
[tID.ImageProcessing]: {
|
||||||
name: 'Image processing',
|
name: 'Image processing',
|
||||||
link: 'https://en.wikipedia.org/wiki/Digital_image_processing',
|
link: 'https://en.wikipedia.org/wiki/Digital_image_processing',
|
||||||
icon: 'skills/image-processing.svg',
|
icon: 'skills/image-processing.svg',
|
||||||
tags: ['system'],
|
tags: ['system'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.AI]: {
|
[tID.AI]: {
|
||||||
name: 'Artificial Intelligence',
|
name: 'Artificial Intelligence',
|
||||||
link: 'https://en.wikipedia.org/wiki/Artificial_intelligence',
|
link: 'https://en.wikipedia.org/wiki/Artificial_intelligence',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['other'],
|
tags: ['other'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.DeepLearning]: {
|
[tID.DeepLearning]: {
|
||||||
name: 'Deep Learning',
|
name: 'Deep Learning',
|
||||||
link: 'https://en.wikipedia.org/wiki/Deep_learning',
|
link: 'https://en.wikipedia.org/wiki/Deep_learning',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['other'],
|
tags: ['other'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.NeuralNetwork]: {
|
[tID.NeuralNetwork]: {
|
||||||
name: 'Neural Networks',
|
name: 'Neural Networks',
|
||||||
link: 'https://en.wikipedia.org/wiki/Artificial_neural_network',
|
link: 'https://en.wikipedia.org/wiki/Artificial_neural_network',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['other'],
|
tags: ['other'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Opti]: {
|
[tID.Opti]: {
|
||||||
name: 'Program optimization',
|
name: 'Program optimization',
|
||||||
link: 'https://en.wikipedia.org/wiki/Program_optimization',
|
link: 'https://en.wikipedia.org/wiki/Program_optimization',
|
||||||
icon: 'skills/opti.svg',
|
icon: 'skills/opti.svg',
|
||||||
tags: ['system', 'networking'],
|
tags: ['system', 'networking'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Sockets]: {
|
[tID.Sockets]: {
|
||||||
name: 'Sockets',
|
name: 'Sockets',
|
||||||
link: 'https://en.wikipedia.org/wiki/Computer_network_programming',
|
link: 'https://en.wikipedia.org/wiki/Computer_network_programming',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['system', 'networking', 'IoT', 'web'],
|
tags: ['system', 'networking', 'IoT', 'web'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Concurrency]: {
|
[tID.Concurrency]: {
|
||||||
name: 'Concurrency',
|
name: 'Concurrency',
|
||||||
link: 'https://en.wikipedia.org/wiki/Concurrent_computing',
|
link: 'https://en.wikipedia.org/wiki/Concurrent_computing',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['system', 'networking'],
|
tags: ['system', 'networking'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.UIUX]: {
|
[tID.UIUX]: {
|
||||||
name: 'UI/UX',
|
name: 'UI/UX',
|
||||||
link: 'https://en.wikipedia.org/wiki/UX',
|
link: 'https://en.wikipedia.org/wiki/UX',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['system', 'web', 'IoT'],
|
tags: ['system', 'web', 'IoT'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.Inkscape]: {
|
[tID.Inkscape]: {
|
||||||
name: 'Inkscape',
|
name: 'Inkscape',
|
||||||
link: 'https://inkscape.org/',
|
link: 'https://inkscape.org/',
|
||||||
icon: 'skills/inkscape.svg',
|
icon: 'skills/inkscape.svg',
|
||||||
tags: ['UI', 'web', 'organization'],
|
tags: ['UI', 'web', 'organization'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
[tID.RnD]: {
|
[tID.RnD]: {
|
||||||
name: 'R&D',
|
name: 'R&D',
|
||||||
link: 'https://en.wikipedia.org/wiki/R&D',
|
link: 'https://en.wikipedia.org/wiki/R&D',
|
||||||
icon: null,
|
icon: null,
|
||||||
tags: ['organization'],
|
tags: ['organization'],
|
||||||
info: "",
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { Projects, Project } from '@/model/projects';
|
|
||||||
import { tID } from '@/model/skills';
|
|
||||||
|
|
||||||
// returns all projects featuring a specified skill. Keeping the order of the
|
|
||||||
// projects model
|
|
||||||
export function bySkill(skill: tID): Project[] {
|
|
||||||
const filtered: Project[] = [];
|
|
||||||
|
|
||||||
for( const proj of Projects ){
|
|
||||||
if( proj.skills.indexOf(skill) >= 0 ){
|
|
||||||
filtered.push(proj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filtered;
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
import { tID, Skills, tSkill } from '@/model/skills';
|
|
||||||
|
|
||||||
let available_cache: tID[]|null = null;
|
|
||||||
let tags_cache: string[]|null = null;
|
|
||||||
|
|
||||||
// returns available skill ids.
|
|
||||||
export function available(): tID[] {
|
|
||||||
if( available_cache != null ){
|
|
||||||
return available_cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
available_cache = [];
|
|
||||||
for( const str_id in Skills ){
|
|
||||||
const id = str2ID(str_id)
|
|
||||||
if( id == null ){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
available_cache.push(id);
|
|
||||||
}
|
|
||||||
return available_cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns the list of ids filtered by a tag. Skills NOT featuring the provided
|
|
||||||
// tag are filtered out of the list.
|
|
||||||
export function filtered(tag: string): tID[] {
|
|
||||||
if( available_cache == null ){
|
|
||||||
available();
|
|
||||||
}
|
|
||||||
|
|
||||||
const filtered = [];
|
|
||||||
for( const id of available_cache! ){
|
|
||||||
const skill = get(id);
|
|
||||||
if( skill == null ){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if( skill.tags.indexOf(tag) >= 0 ){
|
|
||||||
filtered.push(id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filtered;
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns available tags used among skills
|
|
||||||
export function tags(): string[] {
|
|
||||||
if( tags_cache != null ){
|
|
||||||
return tags_cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
tags_cache = [];
|
|
||||||
for( const skill of Object.values(Skills) ){
|
|
||||||
for( const tag of skill.tags ){
|
|
||||||
if( tags_cache.indexOf(tag) < 0 ){
|
|
||||||
tags_cache.push(tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return tags_cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns a skill from its id
|
|
||||||
export function get(id: tID): tSkill|null {
|
|
||||||
if( Skills[id] == undefined ){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return Skills[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
// converts a string to a skill id
|
|
||||||
export function str2ID(str: string): tID|null {
|
|
||||||
const id = parseInt(str) as tID;
|
|
||||||
if( Skills[id] == undefined ){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
Loading…
Reference in New Issue