Compare commits

..

No commits in common. "e5fc1dd0e1fa3c55d027b39dcc41394747e4ea03" and "54c70ce8737222978588ac023e6e17d440013244" have entirely different histories.

11 changed files with 78 additions and 176 deletions

View File

@ -51,7 +51,7 @@ export default class App extends Vue {
if ( picker == null ) { if ( picker == null ) {
return; return;
} }
picker.select(0, true); picker.select(tID.Vue, false);
} }
} }

View File

@ -25,12 +25,12 @@
inkscape:document-units="mm" inkscape:document-units="mm"
showgrid="false" showgrid="false"
inkscape:zoom="23.318967" inkscape:zoom="23.318967"
inkscape:cx="5.2103509" inkscape:cx="5.2532343"
inkscape:cy="9.5630308" inkscape:cy="9.5630307"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="1008" inkscape:window-height="1006"
inkscape:window-x="0" inkscape:window-x="0"
inkscape:window-y="36" inkscape:window-y="42"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="layer1" /> inkscape:current-layer="layer1" />
<defs <defs
@ -43,7 +43,7 @@
<circle <circle
style="fill:none;fill-opacity:1;stroke:#202228;stroke-width:0.639316;stroke-linejoin:round;stroke-opacity:1;paint-order:fill markers stroke" style="fill:none;fill-opacity:1;stroke:#202228;stroke-width:0.639316;stroke-linejoin:round;stroke-opacity:1;paint-order:fill markers stroke"
id="path1850" id="path1850"
cx="154.40691" cx="155.16"
cy="26.429564" cy="26.429564"
r="0.92050833" /> r="0.92050833" />
</g> </g>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -20,8 +20,7 @@
<p ref='text1'>{{ $t('home.line1') }}</p> <p ref='text1'>{{ $t('home.line1') }}</p>
<p ref='text2'>{{ $t('home.line2-1') }} <u>{{ $t('home.line2-2') }}</u> {{$t('home.line2-3') }}</p> <p ref='text2'>{{ $t('home.line2-1') }} <u>{{ $t('home.line2-2') }}</u> {{$t('home.line2-3') }}</p>
<p ref='text3'>{{ $t('home.line3') }}</p> <p ref='text3'>{{ $t('home.line3') }}</p>
<p ref='text4'>{{ $t('home.line4') }}</p> <p ref='text4'>{{ $t('home.line4-1') }} <u>Go</u> {{ $t('home.line4-2') }} <u>IoT</u> {{ $t('home.line4-3') }}</p>
<p ref='text5'>{{ $t('home.line5-1') }} <u>Go</u> {{ $t('home.line5-2') }} <u>IoT</u> {{ $t('home.line5-3') }}</p>
</section> </section>
<div class='scroll-arrow' @click='scrollNext()'> <div class='scroll-arrow' @click='scrollNext()'>
@ -65,11 +64,10 @@ export default class Home extends Vue {
// skip animation if already done less than 10min ago // skip animation if already done less than 10min ago
if ( diff_sec < threshold ) { if ( diff_sec < threshold ) {
(this.$refs.text1 as HTMLElement).style.display = 'block';
(this.$refs.text2 as HTMLElement).style.display = 'block'; (this.$refs.text2 as HTMLElement).style.display = 'block';
(this.$refs.text3 as HTMLElement).style.display = 'block'; (this.$refs.text3 as HTMLElement).style.display = 'block';
(this.$refs.text4 as HTMLElement).style.display = 'block'; (this.$refs.text4 as HTMLElement).style.display = 'block';
(this.$refs.text5 as HTMLElement).style.display = 'block'; (this.$refs.text1 as HTMLElement).style.display = 'block';
return; return;
} }
@ -77,7 +75,6 @@ export default class Home extends Vue {
const t2 = new TypeWriter( this.$refs.text2 as HTMLElement ); const t2 = new TypeWriter( this.$refs.text2 as HTMLElement );
const t3 = new TypeWriter( this.$refs.text3 as HTMLElement ); const t3 = new TypeWriter( this.$refs.text3 as HTMLElement );
const t4 = new TypeWriter( this.$refs.text4 as HTMLElement ); const t4 = new TypeWriter( this.$refs.text4 as HTMLElement );
const t5 = new TypeWriter( this.$refs.text5 as HTMLElement );
// wait for i18n to change text // wait for i18n to change text
@ -86,7 +83,6 @@ export default class Home extends Vue {
t2.init(); t2.init();
t3.init(); t3.init();
t4.init(); t4.init();
t5.init();
// wait 1s, anim 1.5s // wait 1s, anim 1.5s
setTimeout( () => t1.animate(1500), 1000 ); setTimeout( () => t1.animate(1500), 1000 );
@ -96,13 +92,11 @@ export default class Home extends Vue {
setTimeout( () => t3.animate(4000), 6000 ); setTimeout( () => t3.animate(4000), 6000 );
// wait 10s, anim 3s // wait 10s, anim 3s
setTimeout( () => t4.animate(3000), 10000 ); setTimeout( () => t4.animate(3000), 10000 );
// wait 13s, anim 3s
setTimeout( () => t5.animate(3000), 13000 );
// local storage: store that we animated once // local storage: store that we animated once
setTimeout( () => { setTimeout( () => {
localStorage.setItem('typed', `${new Date().getTime()}`); localStorage.setItem('typed', `${new Date().getTime()}`);
}, 16000 ); }, 13000 );
}, 100); }, 100);
} }

View File

@ -36,14 +36,9 @@
<p v-html='details.text[$i18n.locale]'></p> <p v-html='details.text[$i18n.locale]'></p>
</section> </section>
<section class='guide' v-else>
<p v-html='$t("skills.guide")'></p>
</section>
</div> </div>
<input type='button' v-show='this.sel != null' :value="$t('skills.browse')" @click='browse()'/> <input type='button' v-show='this.sel != null' :value="$t('skills.browse')" @click='browse()'/>
<input type='button' v-show='this.sel == null' :value="$t('skills.browse-all')" @click='browse()'/>
</div> </div>
<div class='spacer'></div> <div class='spacer'></div>
@ -79,7 +74,7 @@ export default class SkillPicker extends Vue {
// list of available skills // list of available skills
public readonly ids: tID[] = skills.available(); public readonly ids: tID[] = skills.available();
// currently selected skill // currently selected skill
private sel: tID|null = null; private sel: tID|null = tID.Vue;
// list of ids to display according to the current tag // list of ids to display according to the current tag
private filtered: tID[] = []; private filtered: tID[] = [];
@ -87,10 +82,10 @@ export default class SkillPicker extends Vue {
// available categories (tags) // available categories (tags)
private tags: tTag[] = [DEFAULT_TAG, ...skills.tags()]; private tags: tTag[] = [DEFAULT_TAG, ...skills.tags()];
// currently selected tag // currently selected tag
private tag: tTag = DEFAULT_TAG; private tag: tTag = tTag.Web;
// details section when a skill is selected // details section when a skill is selected
protected details: Details|null = null; private details: Details|null = null;
// selects or deselects a skill. If the skill is not in the current // selects or deselects a skill. If the skill is not in the current
// folder, it navigates to the DEFAULT_TAG folder beforehand. Scrolls to // folder, it navigates to the DEFAULT_TAG folder beforehand. Scrolls to
@ -136,11 +131,11 @@ export default class SkillPicker extends Vue {
go(`search-header`, 0); go(`search-header`, 0);
} }
protected mounted() { private mounted() {
this.filterByTag(); this.filterByTag();
} }
protected scroll(proj_name: string) { private scroll(proj_name: string) {
const head = document.querySelector(`#search-header`) as HTMLElement; const head = document.querySelector(`#search-header`) as HTMLElement;
if ( head == null ) { if ( head == null ) {
return; return;
@ -354,40 +349,6 @@ export default class SkillPicker extends Vue {
} }
.guide {
flex: auto;
display: flex;
height: 100%;
margin: auto;
flex-flow: column nowrap;
align-items: center;
justify-content: center;
p {
flex: auto 0 1;
display: block;
position: relative;
margin: 0 3em;
margin-top: 2em;
margin-bottom: 4rem;
font-size: 1.8em;
font-weight: 500;
text-align: justify;
color: #667;
padding: 1em;
overflow: hidden;
user-select: none;
}
}
input { input {
display: block; display: block;
position: absolute; position: absolute;

View File

@ -4,9 +4,7 @@
<div id='search-header' ref='header'> <div id='search-header' ref='header'>
<img src='../assets/timeline/logo.svg'/> <img src='../assets/timeline/logo.svg'/>
<span> <span>
<h6>{{ projects.length }}</h6> <h3>{{ $t('timeline.title') }}</h3> <SkillCard :id='skill' :active='true'/>
<h3>{{ $t( (skill == null) ? 'timeline.title-all' : 'timeline.title') }}</h3>
<SkillCard v-show='skill != null' :id='skill' :active='true'/>
</span> </span>
<input type='button' :value="$t('timeline.back')" @click='$event.preventDefault(); scrollBack()'/> <input type='button' :value="$t('timeline.back')" @click='$event.preventDefault(); scrollBack()'/>
</div> </div>
@ -38,17 +36,14 @@
<div :key="'desc-icon-'+proj.name" class='desc-icon'> <div :key="'desc-icon-'+proj.name" class='desc-icon'>
<img src='../assets/timeline/info.svg' /> <img src='../assets/timeline/info.svg' />
</div> </div>
<div :key="'desc-'+proj.name" class='desc'> <div :key="'desc-'+proj.name" class='desc' v-html='proj.info[$i18n.locale]'></div>
<div class='user'>{{ $t('project.username') }}</div>
<p v-html='proj.info[$i18n.locale]'/>
</div>
<template v-if='proj.source != null'> <template v-if='proj.source != null'>
<template v-for='(src, i) in proj.source'> <template v-for='src in proj.source'>
<div :key="'src-icon-'+proj.name+'-'+i" class='src-icon'> <div :key="'src-icon-'+proj.name+src" class='src-icon'>
<img src='../assets/timeline/src.svg' /> <img src='../assets/timeline/src.svg' />
</div> </div>
<div :key="'src-'+proj.name+'-'+i" class='src'> <div :key="'src-'+proj.name+src" class='src'>
{{ $t('project.sources') }} <a :href='src.link'>{{ src.name }}</a> <span>({{ proj.commits || src.commits }} commits)</span> {{ $t('project.sources') }} <a :href='src.link'>{{ src.name }}</a> <span>({{ proj.commits || src.commits }} commits)</span>
</div> </div>
</template> </template>
@ -139,7 +134,14 @@ export default class Timeline extends Vue {
private skill: tID|null = null; private skill: tID|null = null;
private projects: Project[] = []; private projects: Project[] = [];
private sort_projects(a: Project, b: Project): number {
public filter(skill: tID|null) {
this.skill = skill;
if ( skill == null ) {
this.projects = [];
return;
}
this.projects = projects.bySkill(skill).sort( (a, b) => {
if ( b.stopped_at == null && a.stopped_at == null ) { if ( b.stopped_at == null && a.stopped_at == null ) {
return b.started_at.getTime() - a.started_at.getTime(); return b.started_at.getTime() - a.started_at.getTime();
} }
@ -150,16 +152,7 @@ export default class Timeline extends Vue {
return -1; return -1;
} }
return b.started_at.getTime() - a.started_at.getTime(); return b.started_at.getTime() - a.started_at.getTime();
} });
public filter(skill: tID|null) {
this.skill = skill;
if ( skill == null ) {
this.projects = projects.all().sort(this.sort_projects);
return;
}
this.projects = projects.bySkill(skill).sort(this.sort_projects);
} }
protected short_date(date: Date): string { protected short_date(date: Date): string {
@ -304,19 +297,6 @@ export default class Timeline extends Vue {
} }
} }
h6 {
display: block;
margin-right: .5em;
padding: .2em .5em;
font-size: 1em;
color: #fff;
background: #444952;
border-radius: .1em / .1em;
}
input { input {
padding: .4em 1em; padding: .4em 1em;
margin-right: 1.5em; margin-right: 1.5em;
@ -337,21 +317,21 @@ export default class Timeline extends Vue {
&.fixed { &.fixed {
position: fixed; position: fixed;
left: 1rem; left: 1rem;
width: calc( 100% - #{2*1rem} ); width: calc( 100% - #{1*2rem} );
margin-top: 1rem;
opacity: .95; background: #fff;
background: #2b2d37;
// background: linear-gradient(to top right, #564ba4, #745cfc); // background: linear-gradient(to top right, #564ba4, #745cfc);
border-radius: 0 0 1rem 1rem; border-radius: 1rem / 1rem;
box-shadow: 0 0 1em .5em darken(#202228, 5%); box-shadow: 0 0 1em darken(#202228, 5%);
img { img {
opacity: 1; opacity: 1;
} }
h3 { h3 {
color: #fff; color: #000;
} }
input { input {
@ -555,23 +535,6 @@ export default class Timeline extends Vue {
top: 1.2em; top: 1.2em;
left: 1.2em; left: 1.2em;
} }
.user {
margin-bottom: 1em;
width: 100%;
height: 2em;
background: url('../assets/home/logo.svg');
background-repeat: no-repeat;
background-size: auto 90%;
background-position: 0 center;
text-align: left;
text-indent: 2.5em;
line-height: 2em;
color: #fff;
}
} }
.src, .doc, .end { .src, .doc, .end {
@ -622,9 +585,7 @@ export default class Timeline extends Vue {
color: #fff; color: #fff;
} }
i { i {
font-size: .8em; color: #d5d5d5;
font-style: normal;
color: #9d9d9d;
} }
li { li {

View File

@ -1,25 +1,21 @@
{ {
"home.title": "FREELANCE DEVELOPER", "home.title": "FREELANCE DEVELOPER",
"home.line1": "Hi, I am another freelance developer !", "home.line1": "Hi, I am another freelance developer !",
"home.line2-1": "I've created this website so you can", "home.line2-1": "I made this website so you can",
"home.line2-2": "browse", "home.line2-2": "browse",
"home.line2-3": "my skills and projects.", "home.line2-3": "some of my skills and projects.",
"home.line3": "I started dev back in 2010. I now have worked on more than 50 projects.", "home.line3": "After 50+ projects since I started IT back in 2010, I still work hard for making projects maintainable so they last and can evolve.",
"home.line4": "I work hard to provide my clients with maintainable projects so that they can evolve at low cost (economic and ecological).", "home.line4-1": "For now, my technologies of choice are : ",
"home.line5-1": "My top technologies at the moment are", "home.line4-2": "and",
"home.line5-2": "and", "home.line4-3": "(Arduino, Raspberry).",
"home.line5-3": "(Arduino, Raspberry).",
"timeline.title": "Timeline of projects featuring", "timeline.title": "Timeline of projects featuring",
"timeline.title-all": "Timeline of all projects",
"timeline.back": "Change skill", "timeline.back": "Change skill",
"skills.featured-before": "Featured in", "skills.featured-before": "Featured in",
"skills.featured-after-1": "project", "skills.featured-after-1": "project",
"skills.featured-after-n": "projects", "skills.featured-after-n": "projects",
"skills.browse": "Browse projects", "skills.browse": "Browse projects",
"skills.browse-all": "Browse all projects",
"skills.guide": "You can select a skill to browse related projects. You can browse all projects by not selecting or deselecting the active skill.",
"tag.all": "All", "tag.all": "All",
"tag.web": "Web", "tag.web": "Web",
@ -98,7 +94,6 @@
"project.doc": "Documentation at", "project.doc": "Documentation at",
"project.end": "Project stopped in", "project.end": "Project stopped in",
"project.still": "Project still active", "project.still": "Project still active",
"project.username": "Adrien Marquès",
"end": "" "end": ""
} }

View File

@ -1,25 +1,21 @@
{ {
"home.title": "DÉVELOPPEUR FREELANCE", "home.title": "DÉVELOPPEUR FREELANCE",
"home.line1": "Hello, je suis développeur freelance !", "home.line1": "Hello, je suis un développeur freelance de plus !",
"home.line2-1": "J'ai développé ce site afin de vous permettre de", "home.line2-1": "J'ai mis en place ce site afin de pouvoir",
"home.line2-2": "parcourir", "home.line2-2": "parcourir",
"home.line2-3": "mes compétences et projets.", "home.line2-3": "certaines de mes compétences et projets.",
"home.line3": "J'ai démarré le dev en 2010. Aujourd'hui je compte plus de 50 projets à mon actif.", "home.line3": "Avec 50+ projets depuis que j'ai démarré le dev en 2010, je suis toujours très attentif à rendre les projets maintenables afin qu'ils durent et puissent évoluer.",
"home.line4": "Je suis très attaché à fournir à mes clients des projets maintenables afin qu'ils puissent évoluer à moindre coût (économique et écologique).", "home.line4-1": "Pour le moment, les technologies qui m'intéressent sont : le",
"home.line5-1": "Les technologies qui m'intéressent actuellement sont le", "home.line4-2": "et l'",
"home.line5-2": "et l'", "home.line4-3": "(Arduino, Raspberry).",
"home.line5-3": "(Arduino, Raspberry).",
"timeline.title": "Chronologie des projets avec", "timeline.title": "Chronologie des projets avec",
"timeline.title-all": "Chronologie des tous les projets", "timeline.back": "Choisir compétence",
"timeline.back": "Changer de compétence",
"skills.featured-before": "Apparaît dans", "skills.featured-before": "Apparaît dans",
"skills.featured-after-1": "projet", "skills.featured-after-1": "projet",
"skills.featured-after-n": "projets", "skills.featured-after-n": "projets",
"skills.browse": "Parcourir les projets", "skills.browse": "Parcourir les projets",
"skills.browse-all": "Parcourir tous les projets",
"skills.guide": "Vous pouvez sélectionner une compétence afin de parcourir les projets liés. Vous pouvez aussi parcourir tous les projets en ne sélectionnant pas de compétence.",
"tag.all": "Tout", "tag.all": "Tout",
"tag.web": "Web", "tag.web": "Web",
@ -99,7 +95,6 @@
"project.doc": "Documentation:", "project.doc": "Documentation:",
"project.end": "Projet terminé en", "project.end": "Projet terminé en",
"project.still": "Projet toujours actif", "project.still": "Projet toujours actif",
"project.username": "Adrien Marquès",
"end": "" "end": ""
} }

View File

@ -42,8 +42,8 @@ export const Projects: Project[] = [
started_at: new Date(2019, 9, 26), started_at: new Date(2019, 9, 26),
stopped_at: new Date(2021, 3, 11), stopped_at: new Date(2021, 3, 11),
info: { info: {
[Locales.EN]: 'Multi-platform (Surface, iOS) flight assistance application for pilots. In the research and development branch of an international aeronautical company (US). It performs data retrieval and visualization of standardized aeronautical data such as flight information, airport information, meteorological information, etc. The application is embedded in an existing software that interfaces with aircraft computers.<br><br>Project existing for about 10 years, I first rewrote and refactored critical parts in order to soften the blocking points. In a second time, I added new functionalities that were impossible or too expensive until then. I was also able to sensitize the team and the client to transition from SVN to Git. Some of my work:<ul><li>redesign of the network data fetching core</li><li>redesign of the asynchronous weather image download manager</li><li>redesign of the color management</li><li>support for the Arinc 424 standard</li><li>redesign of the popup system and click management</li><li>integration of new data sources</li></ul><br>The project ended with a stable version that is still in use today.', [Locales.EN]: 'TODO',
[Locales.FR]: 'Application multi-plateforme (Surface, iOS) d\'assistance de vol pour pilotes de ligne. Dans la branche recherche et développement d\'une entreprise aéronautique internationale (US). Elle effecture la récupération et la représentation graphique de données standardisées aéronautiques d\'informations de vol, d\'aéroports, météorologiques, etc. L\'application est intégrée dans un logiciel existant qui s\'interface avec les calculateur avioniques.<br><br>Projet ayant environ 10 ans d\'existence, j\'ai tout d\'abord ré-écris et refactorisé des parties critiques afin d\'assouplir les points bloquants. Dans un second temps il a été question d\'ajouter de nouvelles fonctionnalités jusque là impossibles ou trop coûteuses. J\'ai aussi pu sensibiliser l\'équipe et le client à une transition de SVN vers Git. Quelques uns de mes travaux:<ul><li>refonte du moteur de récupération de données réseau</li><li>refonte du gestionnaire de téléchargement asynchrone d\'images météorologiques</li><li>refonte de la gestion des couleurs</li><li>support du standard Arinc 424</li><li>refonte du système de popups et gestion des clicks</li><li>ajout de nouvelles sources de données</li></ul><br>Le projet s\'est terminé sur une version stable qui est encore aujourd\'hui utilisée.', [Locales.FR]: 'TODO',
}, },
source: null, doc: null, source: null, doc: null,
commits: 840, commits: 840,
@ -55,11 +55,11 @@ export const Projects: Project[] = [
started_at: new Date(2020, 6, 16), started_at: new Date(2020, 6, 16),
stopped_at: null, stopped_at: null,
info: { info: {
[Locales.EN]: 'Multi-platform (linux, windows and iOS) flight assistance application for pilots. In the research and development branch of an international aeronautical company (US).<br><br>I am the project architect and have been in charge of the technical direction since its creation. I lead a rotating team of 2 to 3 people, ensure the follow-up and the analysis of the customer needs up to task extraction through a simplified Agile organization.<br><br>The project is developed in C++ with the <b>Qt</b> framework. It features:<ul><li>an asynchronous event-driven message bus</li><li>a simplified <a href="https://sass-lang.com/documentation/syntax#scss">SCSS</a> engine</li><li>a dynamic settings system</li><li>a generic iOS windowing system</li><li>a unit test and integration framework</li><li>a generic interface for aircraft on-board computers</li></ul><br>The first iteration of the project has now been accepted for the industrialization process. I now work on the next R&D phases.', [Locales.EN]: 'TODO',
[Locales.FR]: 'Application multi-plateforme (linux, windows et iOS) d\'assistance de vol pour les pilotes de ligne. Dans la branche recherche et développement d\'une entreprise aéronautique internationale (US).<br><br>Je suis architecte du projet et assure la direction technique depuis sa création. Je pilote une équipe tournante de 2 à 3 personnes, assure le suivi et l\'analyse des besoins client jusqu\'à l\'extraction de tâches à travers une organisation Agile simplifiée.<br><br>Le projet est développé en C++ avec le framework <b>Qt</b>. Il comporte notamment :<ul><li>un bus de messages évènementiel asynchrone</li><li>un moteur <a href="https://sass-lang.com/documentation/syntax#scss">SCSS</a> simplifié</li><li>un système de paramètres dynamique</li><li>un système de fenêtrage générique iOS</li><li>un système de tests unitaires et tests d\'intégration</li><li>une interface générique pour différents calculateurs avioniques</li></ul><br>La première itération du projet est passée en industrialisation après tests par les pilotes. Je travaille depuis sur les prochaines phases R&D.', [Locales.FR]: 'TODO',
}, },
source: null, doc: null, source: null, doc: null,
commits: 1897 + 86, commits: 1897 + 62,
}, },
{ {
name: 'EasyCom', name: 'EasyCom',
@ -68,11 +68,11 @@ export const Projects: Project[] = [
started_at: new Date(2021, 0, 6), started_at: new Date(2021, 0, 6),
stopped_at: new Date(2022, 10, 1), stopped_at: new Date(2022, 10, 1),
info: { info: {
[Locales.EN]: 'Medical project for a French company with international reach. The project consists in a modern web platform for the management of nutrient pumps via Internet. I developed the backend of the system as well as the production environment.<br><br>The backend is written in Go and uses docker. It exposes a REST API for the frontend and a websocket API to communicate with the pumps. A PostgreSQL database allows managing the different resources. We have implemented several systems to ensure medical grade security at each level, such as the use of certificate chains, argon2, mTLS, jwt. The backend is fully tested by both unit and integration tests (dockerized) in order to reach a maximum code coverage (+80%). I have developed integration and continuous deployment mechanisms to provide an up-to-date version to the client throughout the development.<br><br>The REST API is based on the use of the open-source library <a href="#project-aicra">aicra</a> that I have been developing for several years.<br><br>My work consists of:<ul><li><b>backend</b> : the backend with its 2 APIs. <i>(1493 commits)</i></li><li><b>cert</b> : command line tool to manage certificate chains, used as a library by the backend. <i>(47 commits)</i></li><li><b>package</b> : simplified execution environment for team members. <i>(13 commits)</i></li><li><b>setup</b> : production environment. <i>(14 commits)</i></li></ul>', [Locales.EN]: 'TODO',
[Locales.FR]: 'Projet médical pour une entreprise française à portée internationale. Le projet consiste en un système web moderne permettant la gestion de parcs de pompes à nutriments via Internet. J\'ai réalisé le backend du système ainsi que l\'élaboration de l\'environnement de production.<br><br>Le backend est développé en Go et utilise docker. Il expose une API REST pour le frontend et une API websocket pour communiquer avec les pompes. Une base de données postgreSQL permet la gestion des différentes ressouces. Plusieurs systèmes ont été mis en place afin d\'assurer une sécurité de grade médical aux différents niveaux, notamment avec l\'utilisation de chaînes de certificats, argon2, mTLS, jwt. Le backend est entièrement testé par des tests unitaires et d\'intégration (dockerisés) afin d\'atteindre une couverture maximale du code (+80%). J\'ai développé des mécanismes d\'intégration et de déploiement continu afin de fournir un version à jour au client tout au long du développement.<br><br>L\'API REST repose sur l\'utilisation de la librairie open-source <a href="#project-aicra">aicra</a> que je développe depuis plusieurs années.<br><br>Mon travail consiste en:<ul><li><b>backend</b> : le backend avec ses 2 APIs. <i>(1493 commits)</i></li><li><b>cert</b> : outil en ligne de commande permettant la gestion des chaînes de certificats, utilisé comme librairie par le backend. <i>(47 commits)</i></li><li><b>package</b> : environnement simplifié d\'exécution pour les membres de l\'équipe. <i>(13 commits)</i></li><li><b>setup</b> : environnement de production. <i>(14 commits)</i></li>', [Locales.FR]: 'TODO',
}, },
source: null, doc: null, source: null, doc: null,
commits: 1493 + 47 + 13 + 14, commits: 1260 + 90 + 41 + 1 + 12 + 1 + 14,
}, },
{ {
@ -83,7 +83,7 @@ export const Projects: Project[] = [
stopped_at: null, // still active stopped_at: null, // still active
info: { info: {
[Locales.EN]: '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.<br><br>I then used it for a professional project in the medical field after corporate evaluation and audit. At the end of the project, results in production are promising : development and testing speed and ease, overall performances, configuration readability for other team members provides a real benefit, they can know the whole api at any time.', [Locales.EN]: '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.<br><br>I then used it for a professional project in the medical field after corporate evaluation and audit. At the end of the project, results in production are promising : development and testing speed and ease, overall performances, configuration readability for other team members provides a real benefit, they can know the whole api at any time.',
[Locales.FR]: 'Démarré en tant que projet personnel afin de simplifier mes développements d\'API REST. L\'objectif principal et d\'améliorer significativement la maintenabilité avec l\'utilisation d\'un fichier de configuration unique qui décrit/définit tous les endpoints de l\'API. Tout ce qui peut être automatisé l\'est, tout en restant idiomatique à Go. Aicra automatise le routage, la validation et l\'extraction des paramètres, les classes de permissions, le formattage des réponses, etc.<br><br>Ce projet a été utilisé pour un projet industriel dans le domaine médical après audit et évaluation de l\'entreprise. Au terme du projet, les résultats sont plutôt encourageants :<ul><li>rapidité de développement</li><li>rapidité d\'écriture des tests</li><li>performances</li><li>lisibilité du fichier de configuration pour les membres de l\'équipe (permet de connaître toute l\'API à tout moment du développement)</li></ul>', [Locales.FR]: 'Démarré en tant que projet personnel afin de simplifier mes développements d\'API REST. L\'objectif principal et d\'améliorer significativement la maintenabilité avec l\'utilisation d\'un fichier de configuration unique qui décrit/définit tous les endpoints de l\'API. Tout ce qui peut être automatisé l\'est tout en restant idiomatique à Go. Aicra automatise le routage, la validation et extraction des paramètres, les classes de permissions, le formattage des réponses, etc.<br><br>J\'ai ensuite pu utiliser cette librairie lors d\'un projet industriel dans le domaine médical après audit et evaluation par l\'entreprise. Après avoir terminé ce projet, les résultats sont plutôt encourageants : rapidité de développement et de test, performances, lisibilité du fichier de configuration pour les autres membres de l\'équipe, (permet de connaître toute l\'API à tout moment du développement) etc.',
}, },
source: [{ name: 'github.com/xdrm-io/aicra', link: 'https://github.com/xdrm-io/aicra', commits: 535 }], source: [{ name: 'github.com/xdrm-io/aicra', link: 'https://github.com/xdrm-io/aicra', commits: 535 }],
doc: { name: 'pkg.go.dev/github.com/xdrm-io/aicra', link: 'https://pkg.go.dev/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' },
@ -97,8 +97,8 @@ export const Projects: Project[] = [
started_at: new Date(2018, 3, 24), started_at: new Date(2018, 3, 24),
stopped_at: new Date(2021, 5, 21), stopped_at: new Date(2021, 5, 21),
info: { info: {
[Locales.EN]: 'Research project to better understand websockets. It consists of a websocket client and server exclusively based on the protocol RFC.<br><br>I also did an optimization pass to achieve an efficient concurrency management solution that is idiomatic to Go (channels, select).', [Locales.EN]: 'Research project to learn more about websockets. I developed a websocket client and server using the RFC as only guidance.<br><br>I did some optimizations to provide a performant solution based on the idiomatic way of dealing with asynchronous resources (channels). By the way I used gorilla/websocket later and I don\'t understand why everything in the API is synchronous ?!<br><br>"I know websockets"',
[Locales.FR]: 'Projet de recherche pour mieux comprendre les websockets. Cela consiste en un client et un serveur websocket en me basant exclusivement de la RFC du protocole.<br><br>J\'ai aussi fait une passe optimisation pour avoir une solution performante en gestion de concurrence qui soit idiomatique à Go (channels, select).', [Locales.FR]: 'Projet de recherche pour mieux comprendre les websockets. J\'ai développé un client et un serveur websocket avec la RFC comme seul guide.<br><br>J\'ai aussi fait une passe optimisation pour avoir une solution performante basée sur la manière idiomatique (Go) de gérer la concurrence (channels). D\'ailleurs j\'ai utilisé gorilla/websocket plus tard, et je ne comprends pas pourquoi toute l\'api est synchrone ?!<br><br>"I know websockets"',
}, },
source: [{ name: 'git.xdrm.io/go/ws', link: 'https://git.xdrm.io/go/ws', commits: 114 }], source: [{ name: 'git.xdrm.io/go/ws', link: 'https://git.xdrm.io/go/ws', commits: 114 }],
doc: { name: 'pkg.go.dev/git.xdrm.io/go/ws', link: 'https://pkg.go.dev/git.xdrm.io/go/ws' }, doc: { name: 'pkg.go.dev/git.xdrm.io/go/ws', link: 'https://pkg.go.dev/git.xdrm.io/go/ws' },
@ -112,8 +112,8 @@ export const Projects: Project[] = [
started_at: new Date(2017, 0, 18), started_at: new Date(2017, 0, 18),
stopped_at: new Date(2018, 10, 5), stopped_at: new Date(2018, 10, 5),
info: { info: {
[Locales.EN]: 'I conducted the LogAuth project back in 2017 for a French branch of an international carrier and logistics company. The project aims to provide a solution to track their warehouse\'s users and vehicles.<br>The project consists of:<ul><li><b>SMMP</b> : website accessible on the Internet for warehouse management.</li><li><b>SATS</b> : hardware and software for a Raspberry Pi that is embedded on each machine. It provides RFID authentication to users with history capability.</li><li><b>setup</b> : tool to write a functional microSD card for each new Raspberry to add to the system (custom credentials, id, features, plugins).</li></ul><br>The SMMP platform is a website developed with a PHP backend and a vanilla frontend (no library). It allows managing groups of users and groups of machines. Actions can be configured for groups of users on groups of machines. A page allows to view real-time access history.<br><br>The strength of the project is that it allows the addition of new features without any changes, thanks to a generic database model, which allows the direct definition of inputs/outputs on the Raspberry Pi. The state machine is also defined in a generic database model.', [Locales.EN]: 'I conducted the LogAuth project back in 2017 for a French branch of an international carrier and logistics company. The project aims to provide a solution to track their warehouse\'s users and vehicles.<br><br>I developed:<ul><li><b>SMMP</b> <i>(Secure Management & Monitoring Platform)</i> : a web interface accessible on the internet to manage the warehouse</li><li><b>SATS</b> <i>(Secure Authentication & Tracking System)</i> : Raspberry Pi hardware & software to interface with vehicles and provide an RFID authentication for users with logging abilities.</li><li><b>setup</b> : A tool project that builds a fully-functional micro sd card for a new SATS (custom credentials, id, features, plugins).</li></ul><br><br>The SMMP is a website developped with a PHP backend and vanilla frontend (no lib). It manages groups of users and groups of machines. Some groups of users can be authorized to do some actions on some groups of machines. A page allows to browse the access history in real-time.<br><br>Also the website allowed for new features on-the-fly by using a generic database model that can define what feature read or write what GPIO pin on the RaspBerry Pi. Machine state management was also defined by the generic database model.',
[Locales.FR]: 'J\'ai réalisé le projet <b>LogAuth</b> en 2017 pour la branche française d\'une entreprise internationale de transport et logistique. Le projet vise à fournir une solution de suivi et gestion des accès utilisateurs aux machines d\'un entrepôt.<br><br>Le projet consiste en:<ul><li><b>SMMP</b> : site web accessible sur Internet pour la gestion par entrepôt.</li><li><b>SATS</b> : hardware et logiciel pour un Raspberry Pi qui est embarqué sur chaque machine. Il fournit une authentification RFID aux utilisateurs avec historique.</li><li><b>setup</b> : outil permettant d\'écrire un carte microSD fonctionnelle pour chaque nouveau Raspberry à ajouter au système (authentification sur-mesure, id, fonctionnalités, plugins).</li></ul><br>La plateforme SMMP est un site web développé avec un backend PHP et un frontend vanilla (pas de librairie). Elle permet la gestion de groupes d\'utilisateurs et de groupes de machines. Des actions peuvent être configurées pour des groupes d\'utilisateurs sur des groupes de machines. Une page permet de parcourir l\'historique des accès en temps réel.<br><br>Le point fort du projet est qu\'il permet l\'ajout de nouvelles fonctionnalités en l\'état, grâce à un modèle de base de données générique, qui permet directement de définir des entrées/sorties du Raspberry Pi. La machine à état est aussi définie dans le modèle générique en base.', [Locales.FR]: 'J\'ai réalisé le projet <b>LogAuth</b> en 2017 pour la branche française d\'une entreprise internationale de transport et logistique. Le projet vise à fournir une solution afin de suivre et gérer les accès des utilisateurs aux machines d\'un entrepot.<br><br>J\'ai développé:<ul><li><b>SMMP</b> <i>(Secure Management & Monitoring Platform)</i> : un site web accessible sur Internet pour la gestion par entrepôt.</li><li><b>SATS</b> <i>(Secure Authentication & Tracking System)</i> : le hardware et logiciel pour un Raspberry Pi qui est embarqué sur chaque machine. Il fournit une authentification RFID aux utilisateurs avec historique.</li><li><b>setup</b> : Un outil permettant d\'écrire un carte microSD functionnelle pour chaque nouveau Raspberry à ajouter au système (authentification sur-mesure, id, fonctionnalités, plugins).</li></ul><br><br>La plateforme SMMP est un site web développé avec un backend PHP et un frontend vanilla (pas de librairie). Elle permet la gestion de groupes d\'utilisateurs et de groupes de machines. Des actions peuvent être configurées pour des groupes d\'utilisateurs sur des groupes de machines. Une page permet de parcourir l\'historique des accès en temps réel.<br><br>De plus, le site permet l\'ajout de nouvelle fonctionnalités en l\'état grâce à un modèle de base de données générique qui permet directement de définir des entrées/sorties du Raspberry Pi. La machine à état est aussi définie dans le modèle générique en base.',
}, },
source: [{ name: 'git.xdrm.io/logauth/smmp', link: 'https://git.xdrm.io/logauth/smmp', commits: 567 }], source: [{ name: 'git.xdrm.io/logauth/smmp', link: 'https://git.xdrm.io/logauth/smmp', commits: 567 }],
doc: null, doc: null,
@ -127,8 +127,8 @@ export const Projects: Project[] = [
started_at: new Date(2017, 0, 18), started_at: new Date(2017, 0, 18),
stopped_at: new Date(2018, 10, 5), stopped_at: new Date(2018, 10, 5),
info: { info: {
[Locales.EN]: 'I conducted the LogAuth project back in 2017 for a French branch of an international carrier and logistics company. The project aims to provide a solution to track their warehouse\'s users and vehicles. The project consists of:<ul><li><b>SMMP</b> : website accessible on the Internet for warehouse management.</li><li><b>SATS</b> : hardware and software for a Raspberry Pi that is embedded on each machine. It provides RFID authentication to users with history capability.</li><li><b>setup</b> : tool to write a functional microSD card for each new Raspberry to add to the system (custom credentials, id, features, plugins).</li></ul><br>The SATS system consists of a shield (electronic board) that attaches to the Raspberry Pi and a firmware. The firmware is a collection of programs that are executed through a complex <b>systemd</b> state machine. It schedules the different phases: boot, network connection, update check, update, I/O initialization, the daemon (main loop).<br><br>It grants or denies access when a RFID card is detected, the access list is updated periodically from the SMMP API. The SATS firmware is capable of updating itself and loading new features from the network. It records all accesses (or attempts), manages and monitors the status of the machine in real time.<br><br>I made several PCBs so that SATS can interface correctly with the Arduino, and in later versions with a Raspberry Pi.<br><br>Through this project, I have designed a customized authentification system, which protects communications between SATS and the SMMP. It avoids key theft, request hijacking, and allows a secure resynchronization protocol after an attack or theft. Source: <a href="https://git.xdrm.io/logauth/schastsp/src/branch/master/PROTOCOL.md">Draft protocol</a>', [Locales.EN]: 'I conducted the LogAuth project back in 2017 for a French branch of an international carrier and logistics company. The project aims to provide a solution to track their warehouse\'s users and vehicles.<br><br>I developed:<ul><li><b>SMMP</b> <i>(Secure Management & Monitoring Platform)</i> : a web interface accessible on the internet to manage the warehouse</li><li><b>SATS</b> <i>(Secure Authentication & Tracking System)</i> : Raspberry Pi hardware & software to interface with vehicles and provide an RFID authentication for users with logging abilities.</li><li><b>setup</b> : A tool project that builds a fully-functional micro sd card for a new SATS (custom credentials, id, features, plugins).</li></ul><br><br>The SATS consists of a hardware and its associated firmware. The firmware is a set of programs launched through a complex systemd state machine to go through the stages : boot, network connection, update check, update, init IO, the daemon (main loop).<br><br>It grants or denies access when an RFID card is detected, the access list is regularly fetched from the SMMP api. It is able to update and fetch new features from the network. It stores every access (or attempt), manages and tracks the machine state over time.<br><br>I made a few PCBs for the SATS in order to interface the Arduino properly, and with a Raspberry in the last properly.<br><br>I also had to design my own authentication system to provide a robust and attack-proof communication between SATS and the SMMP. It avoids key theft, request forgery and allows for resynchronization after an attack or a theft. Source: <a href="https://git.xdrm.io/logauth/schastsp/src/branch/master/PROTOCOL.md">Draft protocol</a>',
[Locales.FR]: 'J\'ai réalisé le projet <b>LogAuth</b> en 2017 pour la branche française d\'une entreprise internationale de transport et logistique. Le projet vise à fournir une solution de suivi et gestion des accès utilisateurs aux machines d\'un entrepôt.<br><br>Le projet consiste en:<ul><li><b>SMMP</b> : site web accessible sur Internet pour la gestion par entrepôt.</li><li><b>SATS</b> : hardware et logiciel pour un Raspberry Pi qui est embarqué sur chaque machine. Il fournit une authentification RFID aux utilisateurs avec historique.</li><li><b>setup</b> : outil permettant d\'écrire un carte microSD fonctionnelle pour chaque nouveau Raspberry à ajouter au système (authentification sur-mesure, id, fonctionnalités, plugins).</li></ul><br>Le système SATS consiste en un shield (carte éléctronique) qui se branche au Raspberry Pi ainsi qu\'un firmware. Le firmware est composé de plusieurs programmes lancés à travers une machine à état complexe basée sur <b>systemd</b>. Elle ordonnance les différentes phases : boot, connexion réseau, vérification de mise à jour, mise à jour, initialisation entrées/sorties, le démon (boucle principale).<br><br>Il autorise ou non les accès quand une carte RFID est détectée, la liste des accès est mise à jour périodiquement depuis l\'api SMMP. Il est capable de se mettre à jour et de charger de nouvelles fonctionnalités depuis le réseau. Il enregistre tous les accès (ou tentatives), gère et monitore l\'état de la machine en temps réel.<br><br>J\'ai réalisé plusieurs PCBs afin que le SATS s\'interface correctement avec l\'Arduino, puis dans les dernières versions avec un Raspberry Pi.<br><br>J\'ai pu lors de ce projet concevoir mon système d\'authentication personnalisé, qui protège les communications entre les SATS et le SMMP. Il évite notamment le vol de clé, le détournement de requêtes, et permet une resynchronisation sécurisée après une attaque ou un vol. Source: <a href="https://git.xdrm.io/logauth/schastsp/src/branch/master/PROTOCOL.md">Définition du protocole</a>', [Locales.FR]: 'J\'ai réalisé le projet <b>LogAuth</b> en 2017 pour la branche française d\'une entreprise internationale de transport et logistique. Le projet vise à fournir une solution afin de suivre et gérer les accès des utilisateurs aux machines d\'un entrepot.<br><br>J\'ai développé:<ul><li><b>SMMP</b> <i>(Secure Management & Monitoring Platform)</i> : un site web accessible sur Internet pour la gestion par entrepôt.</li><li><b>SATS</b> <i>(Secure Authentication & Tracking System)</i> : le hardware et logiciel pour un Raspberry Pi qui est embarqué sur chaque machine. Il fournit une authentification RFID aux utilisateurs avec historique.</li><li><b>setup</b> : Un outil permettant d\'écrire un carte microSD functionnelle pour chaque nouveau Raspberry à ajouter au système (authentification sur-mesure, id, fonctionnalités, plugins).</li></ul><br><br>Le systyème SATS consiste en un shield (carte éléctronique) ajoutée au Raspberry Pi ainsi qu\'un firmware. Le firmware est composé de plusieurs programmes lancés à travers une machine à état complexe dans systemd afin d\'accéder aux différentes phases : boot, connexion réseau, vérification de mise à jour, mise à jour, init E/S, le démon (boucle principale).<br><br>Il autorise ou non les accès quand une carte RFID est détectée, la liste des accès est mise à jour périodiquement depuis l\'api SMMP. Il est capable de se mettre à jour et de charger de nouvelles fonctionnalités depuis le réseau. Il enregistre tous les accès (ou tentatives), gère et monitore l\'état de la machine en temps réel.<br><br>J\'ai du réaliser plusieurs PCBs afin que le SATS s\'interface correctement avec l\'Arduino, puis dans les dernières versions avec un Raspberry.<br><br>J\'ai pu lors de ce projet concevoir mon propre système d\'authentication afin de protéger les communications entre les SATS et le SMMP. Il évite notamment le vol de clé, le détournement de requêtes, et permet une resynchronisation sécurisée après une attaque ou un vol. Source: <a href="https://git.xdrm.io/logauth/schastsp/src/branch/master/PROTOCOL.md">Définition du protocole</a>',
}, },
source: [ source: [
{ name: 'git.xdrm.io/logauth/sats', link: 'https://git.xdrm.io/logauth/sats', commits: 214 }, { name: 'git.xdrm.io/logauth/sats', link: 'https://git.xdrm.io/logauth/sats', commits: 214 },
@ -147,8 +147,8 @@ export const Projects: Project[] = [
started_at: new Date(2016, 0, 12), started_at: new Date(2016, 0, 12),
stopped_at: new Date(2015, 9, 20), stopped_at: new Date(2015, 9, 20),
info: { info: {
[Locales.EN]: 'Tutored project for my DUT degree (BTEC Higher National Dimploma equivalent). The subject was to provide a web-based solution for the management of the IT department (information system): teachers, students, exams, grades, timetables, course units and subunits, etc.<br><br>It was my first experience in analyzing customer needs, the head of the department in this case. I learned to adopt the vision of the client in order to provide a result as close as possible to his expectations.<br><br>The project is mainly done in PHP with a draft of a 2-level web API (not knowing REST yet). It was a complete professional web experience: UI/UX, html/css, js, php, sql, needs analysis, deadlines, etc. The quality of the project is based on skills acquired during my personal web projects. The client appreciated my investment and availability.', [Locales.EN]: 'Tutored project for my DUT degree (BTEC Higher National Dimploma equivalent). The subject was to provide a web-based solution to manage the whole IT department : teachers, students, exams, marks, schedule, course unit and subunits, etc.<br><br>The project was to be made with a team of 4, I quickly took the project lead, and finally did it all by myself, my colleagues lacked motivation and/or experience. It is my first experience with needs analysis by the chief of the IT department ; learning to put my opinion aside when it conflicts with the client\'s needs to keep moving on.<br><br>The project is mainly developped in PHP with a 2-level web API, I did not know REST at the time. It was a first "professional" experience fully featuring web technologies : ui/ux, html/css, js, php, sql, client needs analysis, deadlines, etc. My experience through my personal web projects allowed me not to do like my coworkers who provided a quite minimal but sufficient software. I am actually proud of the final product, it was one of the first projects I brought to completion. The "client" was satisfied too, but the workload made me stay up all night a few times ; 3 months to do everything <i>from scratch</i>. It also helped me test my limits.',
[Locales.FR]: 'Projet tutoré de fin de cycle dans le cadre de l\'IUT informatique. Le sujet était de proposer une solution web pour la gestion du département informatique (système d\'information complet) : enseignants, élèves, examens, notes, emplois du temps, gestion des UE, modules, etc.<br><br>C\'est ma première expérience d\'analyse des besoins clients, le chef du département dans ce cas. J\'ai appris à adopter la vision du client afin de fournir un résultat au plus proche de ses attentes.<br><br>Le projet est principalement fait en PHP avec une ébauche d\'API web à 2 niveaux (ne connaissant pas encore REST). Ce fut une expérience professionnelle web complète : ui/ux, html/css, js, php, sql, analyse besoin client, délais, etc. La qualité du projet repose sur les compétences acquises lors de mes projets web perso. Le client a apprécié mon investissement et ma disponibilité.', [Locales.FR]: 'Projet tutoré de fin de cycle dans le cadre de l\'IUT informatique. Le sujet était de proposer une solution web pour la gestion du département informatique (système d\'information complet) : enseignants, élèves, examens, notes, emplois du temps, gestion des UE, modules, etc.<br><br>Le projet s\'est fait avec une équipe de 4, j\'ai vite pris le lead du projet et finalement développé seul par manque de d\'investissement ou d\'expérience de mes collègues. C\'est ma première expérience avec l\'analyse des besoins donnés par le chef du département dans ce cas; apprendre à mettre son avis de côté quand c\'est incompatible avec la vision du client afin d\'avancer.<br><br>Le projet est principalement fait en PHP avec une ébauche d\'API web à 2 niveaux (je ne connaissait pas encore REST). Ce fut une première expérience "professionnelle" web complète : ui/ux, html/css, js, php, sql, analyse besoin client, délais, etc. Mon expérience via mes projets web perso m\'ont permis de ne pas faire comme la plupart de mes collègues qui ont proposés une solution plus que minimale et suffisante. Je suis assez fier du résultat, ce fut un de mes premiers projets menés à terme, le "client" était satisfait aussi, mais la charge de travail m\'a fait faire pas mal de nuits blanches ; 3 mois pour tout faire <i>from scratch</i>. Ce projet m\'a donc aussi permis de tester mes limites.',
}, },
source: [{ name: 'git.xdrm.io/dut/sid', link: 'https://git.xdrm.io/dut/sid', commits: 401 }], source: [{ name: 'git.xdrm.io/dut/sid', link: 'https://git.xdrm.io/dut/sid', commits: 401 }],
doc: null, doc: null,
@ -162,8 +162,8 @@ export const Projects: Project[] = [
started_at: new Date(2018, 1, 16), started_at: new Date(2018, 1, 16),
stopped_at: new Date(2018, 5, 13), stopped_at: new Date(2018, 5, 13),
info: { info: {
[Locales.EN]: 'Tutored project for my Master\'s degree. The subject was to provide a web-based solution for the management of the IT department (information system): teachers, classes, rooms, grades, timetables, course units and subunits, etc.<br><br>The idea was to replace a set of excel files used by the department chiefs to manage resources and generate schedules. The unavailability of the client was sometimes a hindrance to progress. <br><br>The project has a PHP backend, and a Vue frontend. We used docker-compose with a continuous integration and deployment system. 300 hours of work were invested in a little over 3 months. At the end of the collaboration, the project was adopted.', [Locales.EN]: 'Tutored project for my Master\'s degree in IT. The subject was to provide a web solution to manage the IT department : teachers, classes, classrooms, marks, course unit and subunits, etc.<br><br>The project was made with 2 colleagues, I quickly took the project lead and finally developed almost everything myself. The idea was to replace a set of excel files used by chiefs of the IT department to manage resources and generate schedules for everyone. There has been a few conflicts with "the clients" as they were never available and we had a deadline for this work. At the end, they told us that they would use our work.<br><br>The project features a PHP backend and a Vue frontend. We used docker-compose with continuous integration & deployment mechanisms. I spent 300 hours on it in a bit more than 3 months, I guess I was motivated.',
[Locales.FR]: 'Projet tutoré de fin de cycle dans le cadre du Master Informatique. Le sujet était de proposer une solution web pour la gestion du département informatique (système d\'information complet) : enseignants, classes, salles, notes, emplois du temps, gestion des UE, modules, etc.<br><br>L\'idée était de remplacer un ensemble de fichiers excel utilisés par les chefs de département pour gérer les ressources et générer les plannings. L\'indisponibilité du client a parfois été un frein à l\'avancement. <br><br>Le projet a un backend PHP, et un frontend en Vue. Nous avons utilisé docker-compose avec un système d\'intégration et de déploiement continu. 300 heures de travail ont été investies en un peu plus de 3 mois. Au terme de la collaboration, le projet a été adopté.', [Locales.FR]: 'Projet tutoré de fin de cycle dans le cadre du Master Informatique. Le sujet était de proposer une solution web pour la gestion du département informatique (système d\'information complet) : enseignants, classes, salles, notes, emplois du temps, gestion des UE, modules, etc.<br><br>Le projet s\'est fait avec une équipe de 3, j\'ai vite pris le lead du projet et finalement développé quasiment seul le projet. L\'idée était de remplacer un ensemble de fichiers excel utilisés par les chefs de département "le client" afin de gérer les ressources et générer les plannings. Il y a eu quelques accrochages avec les clients car ils n\'étais jamais disponibles et nous avions un délai pour ces travaux. En fin de projet, ils nous ont finalement dit qu\'ils utiliseraient le projet à l\'avenir.<br><br>Le projet a un backend PHP, et un front en Vue. Nous avons utilisé docker-compose avec un système d\'intégration et de déploiement continu. J\'ai compté 300 heures passées dessus en un peu plus de 3 mois, j\'étais motivé.',
}, },
source: [ source: [
{ name: 'git.xdrm.io/mti/ptut-virtenv', link: 'https://git.xdrm.io/mti/ptut-virtenv', commits: 103 }, { name: 'git.xdrm.io/mti/ptut-virtenv', link: 'https://git.xdrm.io/mti/ptut-virtenv', commits: 103 },

View File

@ -175,8 +175,8 @@ export const Skills: tSkills = {
icon: 'skills/vue.svg', icon: 'skills/vue.svg',
tags: [tTag.Web, tTag.UI], tags: [tTag.Web, tTag.UI],
info: { info: {
[Locales.EN]: 'Web front-end framework that displays components directly from your data, with an extremely low cost. 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.', [Locales.EN]: 'Web front-end framework that displays components directly from your data, with an extremely low cost. 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.',
[Locales.FR]: 'Framework pour front-end web qui affiche des composants graphiques directement depuis les données à un coup relativement bas. J\'ai découvert Vue en 2016, et n\'ai jamais arrêté de l\'utiliser depuis tant pour mes projets perso que professionnels. Je vois Vue comme une meilleure alternative qu\'Angular qui, lui, fournit un cadre de travail strict qui manque de flexibilité aux équipes et projets.<br><br>Vue vous rend la responsabilité de structurer correctement vos projets, ce que j\'apprécie faire moi-même, je trouve que ça pousse à un meilleur workflow (ajusté à chaque projet).', [Locales.FR]: 'Framework pour front-end web qui affiche des composants graphiques directement depuis les données à un coup relativement bas. J\'ai découvert Vue en 2016, et n\'ai jamais arrêté de l\'utiliser depuis tant pour mes projets perso que professionnels. Je vois Vue comme une meilleure alternative qu\'Angular qui, lui, fournit un cadre de travail strict qui manque de flexibilité aux équipes et projets.<br><br>Vue vous rend la responsabilité de structurer correctement vos projets, ce que j\'apprécie faire moi-même, je trouve que ça pousse à un meilleur workflow (ajusté à chaque projet).<br><br>C\'est moi choix de prédilection en tant que framework web pour faire du rendu.',
}, },
}, },
[tID.Angular]: { [tID.Angular]: {

View File

@ -1,10 +1,6 @@
import { Projects, Project } from '@/model/projects'; import { Projects, Project } from '@/model/projects';
import { tID } from '@/model/skills'; import { tID } from '@/model/skills';
export function all(): Project[] {
return Projects;
}
// returns all projects featuring a specified skill. Keeping the order of the // returns all projects featuring a specified skill. Keeping the order of the
// projects model // projects model
export function bySkill(skill: tID): Project[] { export function bySkill(skill: tID): Project[] {