Compare commits

..

No commits in common. "master" and "2023.1.001" have entirely different histories.

41 changed files with 2991 additions and 4439 deletions

View File

@ -1,19 +0,0 @@
when:
- event: cron
cron: update browserlist
steps:
- name: update browserlist
image: node:20-slim
commands:
- npm ci
- npx update-browserslist-db@latest
- npm run test
- name: push commit
image: appleboy/drone-git-push
settings:
branch: master
remote: git@forge.adm.ink:adamas/curriculum.git
force: false
commit: true
commit_message: "dep: updatebrowserslist"

View File

@ -1,28 +0,0 @@
when:
- event: push
branch: master
- event: manual
steps:
- name: test
image: node:20-slim
commands:
- npm ci
- npm run test
- name: build
image: node:20-slim
commands:
- npm run build
- name: publish
image: woodpeckerci/plugin-docker-buildx:5.2.2
settings:
username: adamas
registry: https://forge.adm.ink
password:
from_secret: DOCKER_PASSWORD
repo: forge.adm.ink/adamas/curriculum
purge: true
compress: true
tags: ${CI_COMMIT_TAG}

View File

@ -1 +0,0 @@
* @AdamasFR

View File

@ -1,14 +0,0 @@
FROM node:20-slim
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
RUN npm install --silent
RUN npm install react-scripts@5.0.1 -g --silent
# add app
COPY . ./
# start app
CMD ["npm", "start"]

View File

@ -67,4 +67,4 @@ This section has moved here: [https://facebook.github.io/create-react-app/docs/d
### `npm run build` fails to minify
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)

View File

@ -1,11 +1,12 @@
# anthony-dumas.fr
```
Bonjour,
Vous trouverez ci-joint le code source de mon portefolio en ligne.
Je vous souhaite une excellente journée,
**Anthony Yvon Dumas**
**Anthony Dumas**
Senior Engineer @ Sopra Steria
Software Developer @ harvest.fr
```

View File

@ -1,30 +0,0 @@
version: '2'
services:
server:
image: forge.adm.ink/adamas/curriculum:latest
container_name: anthony-dumas.fr-server
networks:
- traefik_default
labels:
- "traefik.enable=true"
- "traefik.http.routers.portfolio.rule=Host(`anthony-dumas.fr`)"
- "traefik.http.routers.portfolio.entrypoints=websecure"
- "traefik.http.routers.portfolio.tls.certresolver=myresolver"
- "traefik.http.services.portfolio.loadbalancer.server.port=3000"
- "traefik.http.middlewares.redirect-to-non-www.redirectregex.regex=^https?://www.anthony-dumas.fr/(.*)"
- "traefik.http.middlewares.redirect-to-non-www.redirectregex.replacement=https://anthony-dumas.fr/$${1}"
- "traefik.http.middlewares.redirect-to-non-www.redirectregex.permanent=true"
- "traefik.http.routers.portfolio.rule=Host(`anthony-dumas.fr`) || Host(`www.anthony-dumas.fr`)"
- "traefik.http.routers.portfolio.middlewares=redirect-to-non-www"
watchtower:
image: containrrr/watchtower
container_name: watchtower-anthony-dumas.fr
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: --interval 30 anthony-dumas.fr-server
networks:
traefik_default:
external: true

View File

@ -1,14 +0,0 @@
{
"usesTypeScript": false,
"usesStyledComponents": true,
"testLibrary": "None",
"component": {
"default": {
"path": "src/components",
"withStyle": true,
"withTest": false,
"withStory": false,
"withLazy": false
}
}
}

6512
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,13 +6,13 @@
"@testing-library/jest-dom": "^5.11.6",
"@testing-library/react": "^11.2.2",
"@testing-library/user-event": "^12.5.0",
"bulma": "^1.0.0",
"bulma": "^0.9.4",
"powerglitch": "^2.3.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-intl": "^5.10.9",
"react-scripts": "^5.0.1",
"sass": "^1.71.1",
"react-scripts": "5.0.1",
"sass": "^1.30.0",
"web-vitals": "^0.2.4"
},
"scripts": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -7,7 +7,7 @@
<meta name="theme-color" content="#326273" />
<meta
name="description"
content="Anthony Dumas - Programmeur de les Internet."
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
@ -24,7 +24,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>Anthony Dumas - Portfolio</title>
<title>Anthony Dumas</title>
<!-- Matomo -->
<script>
var _paq = (window._paq = window._paq || []);
@ -49,18 +49,15 @@
<noscript>
<h1>Ce site requiert Javascript (désolé !)</h1>
Dirigez vous vers
<a
href="https://adamas-cdn.s3.fr-par.scw.cloud/portfolio/anthony-dumas-cv.pdf"
>ce lien</a
<a href="https://files.adm.ink/anthony-dumas-cv.pdf"
>https://files.adm.ink/anthony-dumas-cv.pdf</a
>
pour une version PDF. Pour me parler directement, n'hésitez pas à
m'envoyer un message sur
<a rel="me" href="https://social.adm.ink/@adamas">Mastodon</a>!
pour une version PDF.
Pour me parler directement, n'hésitez pas à m'envoyer un message sur <a rel="me" href="https://imaginair.es/@adamas">Mastodon</a>!
</noscript>
<div id="root"></div>
<script src="https://unpkg.com/ionicons@7.4.0/dist/ionicons.js"></script>
<a style="display: none" rel="me" href="https://social.adm.ink/@adamas"
>Mastodon</a
>
<script src="https://unpkg.com/ionicons@latest/dist/ionicons.js"></script>
<a style="display:none" rel="me" href="https://imaginair.es/@adamas">Mastodon</a>
</body>
</html>

View File

@ -1,5 +0,0 @@
User-agent: GPTBot
Disallow: /
User-agent: ClaudeBot
Disallow: /

37
src/App.sass Normal file
View File

@ -0,0 +1,37 @@
@charset "utf-8"
// Import a Google Font
@import url('https://fonts.googleapis.com/css?family=Nunito:400,700')
// Set your brand colors
$purple: #8a4d76
$pink: #fa7c91
$brown: #757763
$beige-light: #d0d1cd
$beige-lighter: #eff0eb
// Update Bulma's global variables
$family-sans-serif: 'Nunito', sans-serif
$grey-dark: $brown
$grey-light: $beige-light
$primary: $purple
$link: $pink
$widescreen-enabled: false
$fullhd-enabled: false
// Update some of Bulma's component variables
$body-background-color: $beige-lighter
$control-border-width: 2px
$input-border-color: transparent
$input-shadow: none
// Import only what you need from Bulma
@import '../node_modules/bulma/sass/utilities/_all.sass'
@import '../node_modules/bulma/sass/base/_all.sass'
@import '../node_modules/bulma/sass/elements/button.sass'
@import '../node_modules/bulma/sass/elements/container.sass'
@import '../node_modules/bulma/sass/elements/form.sass'
@import '../node_modules/bulma/sass/elements/title.sass'
@import '../node_modules/bulma/sass/components/navbar.sass'
@import '../node_modules/bulma/sass/layout/hero.sass'
@import '../node_modules/bulma/sass/layout/section.sass'

View File

@ -1,18 +1,8 @@
import React from 'react';
import { IntlProvider } from 'react-intl';
import { render, screen } from '@testing-library/react';
import App from './App';
import MenuComponent from './App';
import { getTexts } from './services/message.service';
test('renders Anthony Yvon Dumas', async () => {
render(<IntlProvider locale={"fr"}
defaultLocale={"fr"}
messages={getTexts("fr")}>
<MenuComponent />
</IntlProvider>);
expect(await screen.findByText("Anthony Yvon Dumas")).toBeInTheDocument();
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

View File

@ -1 +1 @@
@use "main.scss";
@import "main.scss";

View File

@ -7,29 +7,40 @@ $deep-koamaru: #152528;
$myrtle-green: #1d353a;
$cadet-blue: #25444b;
$neon-carrot: #142225;
$admink-brand: #f38d68;
$white: #ffffff;
@use "bulma/sass" with (
$primary: $cadet-blue,
$info: $myrtle-green,
$footer-color: $deep-koamaru,
$success: $deep-koamaru,
$link: $neon-carrot
);
/**
Variables Bulma
**/
$primary: $cadet-blue;
$primary-invert: #fff;
$info: $myrtle-green;
$info-invert: #fff;
$footer-color: $deep-koamaru;
$success: $deep-koamaru;
$link: $neon-carrot;
$link-hover: "";
html {
background-color: $myrtle-green;
background-color: $primary;
}
body {
overflow-x: hidden;
}
@import "../../node_modules/bulma/bulma";
#idCard {
.hero-body {
padding-bottom: 2rem;
padding-top: 2rem;
}
// permet de re-aligner les tags avec les subtitles
.tags {
margin-top: -1.25rem;
}
}
// retire les barres de scroll des panneaux experience/education
@ -38,7 +49,7 @@ body {
}
footer {
background-color: $deep-koamaru !important;
background-color: $footer-color !important;
color: #fff;
}
@ -77,12 +88,12 @@ section#contact .button {
//
footer small {
color: #fff;
color: $white;
}
// Photo de Profil
#photoProfil {
background-color: $myrtle-green;
background-color: $primary;
}
.tile.is-vertical {
@ -100,7 +111,3 @@ footer small {
text-align: left;
font-size: 20px;
}
p.title a {
color: $admink-brand !important;
}

View File

@ -11,7 +11,7 @@ export default class ButtonIcon extends Component {
render() {
return <a rel="noopener noreferrer me" href={this.props.lien} target="_blank">
<button className="button" aria-label="Bouton {this.props.aria-label}">
<span className="icon">
<span class="icon">
<ion-icon name={this.props.icon}></ion-icon>
</span>
</button>

View File

@ -13,10 +13,10 @@ export default class ContactButton extends Component {
// }
render() {
const data = this.props.data;
return <div className="column is-3">
<a target="_blank" rel="noreferrer noopener" href={data.url} className="hide button is-large is-fullw-mobile"
return <div class="column is-3">
<a target="_blank" rel="noreferrer noopener" href={data.url} class="hide button is-large is-fullw-mobile"
title={`Go to ${data.title}`}>
<span className="icon">
<span class="icon">
<ion-icon name={data.icon}></ion-icon>
</span>
<span>{data.title}</span>

View File

@ -1,40 +1,39 @@
import './ContactCard.scss';
import React, { Component } from 'react';
import React, {Component} from 'react';
import { injectIntl } from 'react-intl';
import ContactButton from '../ContactButton/index';
import './ContactCard.scss'
import ContactButton from '../ContactButton/index';
// import { connect } from "react-redux";
// import { bindActionCreators } from "redux";
// import * as contactCardActions from "../../store/contactCard/actions";
class ContactCard extends Component {
// constructor(props) {
// super(props);
// this.state = {};
// }
render() {
const contactCardMessage = this.props.intl.messages.contactCard;
return <section className="hero is-info dontPrint" id="contact">
<div className="hero-body">
<div className="container">
<h1 className="title">
{contactCardMessage.title}
</h1>
<h2 className="subtitle">
{contactCardMessage.subtitle}
</h2>
<div className="columns">
{contactCardMessage.ways.map(function (button, index) {
return <ContactButton key={index}
data={button} />;
})}
// constructor(props) {
// super(props);
// this.state = {};
// }
render() {
const contactCardMessage = this.props.intl.messages.contactCard;
return <section class="hero is-info dontPrint" id="contact">
<div class="hero-body">
<div class="container">
<h1 class="title">
{contactCardMessage.title}
</h1>
<h2 class="subtitle">
{contactCardMessage.subtitle}
</h2>
<div class="columns">
{contactCardMessage.ways.map(function(button, index){
return <ContactButton
data={button}/>;
})}
</div>
</div>
</div>
</div>
</section>;
</section>;
}
}
}
export default injectIntl(ContactCard)
export default injectIntl(ContactCard)

View File

@ -1,9 +1,9 @@
import './ExperienceCard.scss';
import React, { Component } from 'react';
import './ExperienceCard.scss'
import ExperienceSlimSpanWrapper from '../ExperienceSlimSpan/ExperienceSlimSpan';
// import { connect } from "react-redux";
// import { bindActionCreators } from "redux";
// import * as MenuComponentActions from "../../store/MenuComponent/actions";
export default class ExperienceCard extends Component {
// constructor(props) {
@ -13,39 +13,36 @@ export default class ExperienceCard extends Component {
render() {
var data = this.props.data;
var imgSrc = data.logo;
return <div className="card-content">
<div className="media">
<div className="media-left">
return <div class="card-content">
<div class="media">
<div class="media-left">
<a href={data.url} target="_blank" rel="noreferrer">
<figure className="image is-48x48">
<figure class="image is-48x48">
<img src={imgSrc} alt="Logo Entreprise" />
</figure>
</a>
</div>
<div className="media-content">
<p className="title is-4">{data.occupation}</p>
<p className="subtitle is-6"><strong>{data.entreprise}</strong> - {data.location} - {data.duration}</p>
<div className="tags">
<div class="media-content">
<p class="title is-4">{data.occupation}</p>
<p class="subtitle is-6">{data.entreprise} - {data.location} - {data.duration}</p>
<div class="tags">
{data.tags.map(function (name, index) {
return <span key={index} className="tag">{name}</span>;
return <span key={index} class="tag">{name}</span>;
})}
</div>
<div className='description content'>
<div dangerouslySetInnerHTML={{ __html: data.description }} />
</div>
{data.missions ?
data.missions.map(function (mission, index) {
return <ExperienceSlimSpanWrapper key={index}
data={mission} />;
}) : ''
}
{data.commentaire ? <div className="comment">
{data.commentaire}
</div> : ''}
</div>
</div>
<div class="content">
{data.description}
</div>
{data.commentaire ? <div class="comment">
{data.commentaire}
</div> : ''}
</div>
}
}
}
// export default connect(
// ({ MenuComponent }) => ({ ...MenuComponent }),
// dispatch => bindActionCreators({ ...MenuComponentActions }, dispatch)
// )( MenuComponent );

View File

@ -1,28 +1,4 @@
.comment {
font-style: italic;
margin-top: -25px;
}
// permet de re-aligner les tags avec les subtitles
.tags,
.description,
.comment {
margin-top: -1.25rem;
}
.card-content {
margin-top: 1rem;
}
.mission.card-content {
margin-top: 0;
}
.mission .media {
border-top-style: none;
align-items: self-end;
}
.mission div.media {
padding-top: 2px;
}
.comment{
font-style: italic;
margin-top: -25px;
}

View File

@ -1,23 +0,0 @@
import React, { Component } from 'react';
export default class ExperienceSlimSpan extends Component {
render() {
var data = this.props.data;
var imgSrc = data.logo;
return <div className="mission card-content">
<div className="media">
<div className="media-left">
<a href={data.url} target="_blank" rel="noreferrer">
<figure className="image is-24x24">
<img src={imgSrc} alt="Logo Entreprise" />
</figure>
</a>
</div>
<div className="media-content">
<p className="subtitle is-6">{data.occupation} {data.situation} <strong>{data.entreprise}</strong> - {data.duration}</p>
</div>
</div>
</div>
}
};

View File

@ -1,10 +1,9 @@
import './FooterCard.scss';
import React, { Component } from 'react';
import { injectIntl } from 'react-intl';
import React, { Component } from 'react';
import bulmaLogo from '../../images/made-with-bulma.webp';
import scalewayLogo from '../../images/scaleway_logo.webp';
// import { connect } from "react-redux";
@ -17,17 +16,17 @@ class FooterCard extends Component {
// }
render() {
const footerMessage = this.props.intl.messages.footer;
return <footer className="footer has-text-centered dontPrint">
<div className="container">
<div className="columns">
<div className="column is-8-desktop is-offset-2-desktop">
return <footer class="footer has-text-centered dontPrint">
<div class="container">
<div class="columns">
<div class="column is-8-desktop is-offset-2-desktop">
<p>
<strong className="has-text-weight-semibold">
<strong class="has-text-weight-semibold">
anthony-dumas.fr
</strong>
</p>
<p>
<small className="sosumi">
<small class="sosumi">
{footerMessage.legalNotice}
</small>
</p>
@ -38,8 +37,8 @@ class FooterCard extends Component {
<img src={bulmaLogo} alt="Made with Bulma" width="128" height="24" />
</a>
<br />
<a rel="noopener noreferrer" href="https://www.scaleway.com/fr/" aria-label="Link to scaleway.com" id="scaleway-logo" target="_blank">
<img src={scalewayLogo} alt="Powered by Scaleway" width="128" height="24" />
<a rel="noopener noreferrer" href="https://www.linode.com/" aria-label="Link to Linode.com" id="linode-logo" target="_blank">
<svg viewBox="0 0 230 90" width="115" height="30"><g fill="#FFF"><path d="M93.8 27.8l5.8-1.4v28c0 3.1.9 4.9 2.7 5.5-.9 1.7-2.4 2.6-4.6 2.6-2.6 0-4-1.8-4-5.5V27.8zM108.4 62V41.8h-3.2V37h9.1v25h-5.9zm3-34.6c.9 0 1.7.3 2.4 1s1 1.5 1 2.4c0 .9-.3 1.7-1 2.4s-1.5 1-2.4 1c-.9 0-1.7-.3-2.4-1s-1-1.5-1-2.4c0-.9.3-1.7 1-2.4s1.5-1 2.4-1zM137.1 62V47.6c0-2.1-.4-3.7-1.2-4.6-.8-1-2.1-1.5-4-1.5-.9 0-1.8.2-2.7.7-1 .5-1.7 1.1-2.3 1.8v18h-5.8V37.1h4.2l1.1 2.3c1.6-1.9 3.9-2.8 7-2.8 3 0 5.3.9 7 2.7 1.7 1.8 2.6 4.3 2.6 7.4V62h-5.9zM147.5 49.5c0-3.8 1.1-6.9 3.3-9.3 2.2-2.4 5.1-3.6 8.7-3.6 3.8 0 6.7 1.1 8.8 3.4 2.1 2.3 3.1 5.4 3.1 9.4s-1.1 7.1-3.2 9.5c-2.1 2.3-5 3.5-8.8 3.5-3.8 0-6.7-1.2-8.8-3.5-2-2.4-3.1-5.5-3.1-9.4zm6.1 0c0 5.5 2 8.2 5.9 8.2 1.8 0 3.2-.7 4.3-2.1 1.1-1.4 1.6-3.5 1.6-6.1 0-5.4-2-8.1-5.9-8.1-1.8 0-3.3.7-4.3 2.1-1.1 1.4-1.6 3.4-1.6 6zM192.1 62v-1.5c-.5.5-1.3 1-2.4 1.4-1.1.4-2.3.6-3.6.6-3.5 0-6.2-1.1-8.2-3.3-2-2.2-3-5.3-3-9.2 0-3.9 1.1-7.1 3.4-9.6s5.1-3.7 8.6-3.7c1.9 0 3.6.4 5.2 1.2v-10l5.8-1.4V62h-5.8zm0-19c-1.2-1-2.5-1.5-3.9-1.5-2.3 0-4.1.7-5.4 2.1-1.3 1.4-1.9 3.5-1.9 6.1 0 5.2 2.5 7.8 7.5 7.8.6 0 1.2-.2 2.1-.5.8-.3 1.3-.7 1.6-1V43zM226 51.3h-17.8c.1 2 .8 3.5 2 4.6 1.3 1.1 2.9 1.7 5.1 1.7 2.6 0 4.7-.7 6-2.1l2.3 4.4c-2 1.7-5.1 2.5-9.2 2.5-3.8 0-6.8-1.1-9-3.3-2.2-2.2-3.3-5.3-3.3-9.3 0-3.9 1.2-7.1 3.6-9.5 2.4-2.4 5.3-3.6 8.7-3.6 3.6 0 6.5 1.1 8.7 3.2 2.2 2.2 3.3 4.9 3.3 8.2.1.7-.1 1.7-.4 3.2zm-17.6-4.4h12.2c-.4-3.6-2.4-5.5-6-5.5-3.3.1-5.4 1.9-6.2 5.5z"></path></g><path fill="#004712" d="M65.9 47.4l-1 11.5-3.3-2.3.4-5.8v-.1-.1l-.1-.1-.1-.1-7.1-4.7.1-5.1 11.1 6.8zM48.5 59.9L43.4 56v.9c0 .2-.1.4-.2.5L39.4 60l4.2 3.4.1.1v.2l.2 4 4.7 3.9-.1-11.7zm-32.1 5l2.4 11.5 9.9 10.5L27 75.3 16.4 64.9zm9.3 1.7l-2.4-16.1-12-10 3.2 15.6 11.2 10.5zm-3.8-26l-3.3-22.8L4.8 9.2l4.5 21.5 12.6 9.9z"></path><path fill="#00B259" d="M75.7 41.2l-1.5 10.9-8.2 6.6 1-11.2 8.7-6.3zM49.6 59.9l.1 11.8 10.5-8.4.7-11.5-11.3 8.1zm-6.8 4.8L28 75.3l1.8 12.2 13.4-10.7-.4-12.1zm-.4-8l-.7-16-17.3 9.9 2.4 16.6 15.6-10.5zm-1.1-25.3l-.9-21.6-20.8 8L23 41l18.3-9.6z"></path><path d="M76.9 40c0-.1 0-.1 0 0v-.2s0-.1-.1-.1c0 0-.1 0-.1-.1l-12-6.7c-.2-.1-.4-.1-.5 0L54 39.1h-.1v.6l-.1 5.4-4.1-2.7c-.2-.1-.4-.1-.6 0L43 45.8l-.3-6v-.1-.1-.1-.1-.1h-.1l-6.2-4.1 5.8-3c.2-.1.3-.3.3-.5L41.4 9v-.1s0-.1-.1-.1c0 0 0-.1-.1-.1L25.5 1.1c-.1-.1-.2-.1-.3-.1L3.9 7.6s-.1 0-.1.1c0 0-.1 0-.1.1v.6l4.7 22.9c0 .1.1.2.2.3l6.4 5-4.7 2.2s-.1 0-.1.1c0 0 0 .1-.1.1v.2l3.6 17.2c0 .1.1.2.2.3l4.5 4.2-3 1.8-.1.1s0 .1-.1.1V63.2L18 76.5c0 .1.1.2.1.3l10.9 12h.1s.1 0 .1.1h.5l14.4-11.5c.1-.1.2-.3.2-.4l-.3-7.9 4.8 4s.1 0 .1.1h.5L61 64c.1-.1.2-.2.2-.4l.4-5.8 3.5 2.4h.4s.1 0 .1-.1l9.4-7.5c.1-.1.2-.2.2-.3L76.9 40c0 .1 0 .1 0 0zM66 58.7l1-11.2 8.8-6.3-1.5 10.9-8.3 6.6zm-4.4-2.1l.4-5.8v-.1-.1l-.1-.1-.1-.1-7.1-4.7.1-5.1 11.1 6.9-1 11.5-3.3-2.4zm-1.5 6.7l-10.5 8.4-.1-11.8 11.3-8.1-.7 11.5zM43.3 76.8L29.8 87.5 28 75.3l14.7-10.5.6 12zm-24.6-.4l-2.4-11.5L27 75.3l1.7 11.6-10-10.5zm-.2-58.6l3.3 22.8-12.5-9.9L4.8 9.2l13.7 8.6zm21.9-8l.9 21.6L23 41l-3.4-23.2 20.8-8zm2 46.9L26.8 67.1l-2.4-16.6 17.3-9.9.7 16.1zm-19.1-6.1l2.4 16.1-11.2-10.6-3.2-15.6 12 10.1zm20.5 13.1v-.1-.1l-.1-.1-4.2-3.4 3.8-2.6c.2-.1.2-.3.2-.5V56l5.1 3.9.1 11.8-4.7-3.9-.2-4.1z"></path></svg>
</a>
</p>
</div>

View File

@ -1,94 +1,66 @@
import './MainCard.scss';
import { PowerGlitch } from 'powerglitch';
import React, { Component } from 'react';
import { FormattedMessage, injectIntl } from 'react-intl';
import React, { Component } from 'react';
import headshotFond from '../../images/headshot_fond.webp';
import headshotMain from '../../images/headshot_main.webp';
import ButtonIcon from '../ButtonIcon/index';
import ExperienceCard from '../ExperienceCard/index';
import { PowerGlitch } from 'powerglitch';
class MainCard extends Component {
componentDidMount() {
PowerGlitch.glitch('#photoProfil img',
{
playMode: 'hover',
hideOverflow: true,
timing: {
duration: 1000,
iterations: 15,
easing: 'ease-in-out',
},
glitchTimeSpan: {
start: 0.0,
end: 0.7,
},
shake: {
velocity: 10,
amplitudeX: 0.4,
amplitudeY: 0.4,
},
slice: {
count: 4,
velocity: 10,
minHeight: 0.02,
maxHeight: 0.40,
hueRotate: true,
},
}
);
glitching() {
PowerGlitch.glitch('#photoProfil');
}
render() {
var metaThemeColor = document.querySelector("meta[name=theme-color]");
if (metaThemeColor !== null) {
metaThemeColor.setAttribute("content", window.matchMedia('(prefers-color-scheme: dark)').matches ? "#25444b" : "#5c9ead");
}
metaThemeColor.setAttribute("content", window.matchMedia('(prefers-color-scheme: dark)').matches ? "#25444b" : "#5c9ead");
const experienceCardMessage = this.props.intl.messages.experienceCard;
return <section id="idCard" className="hero is-medium is-info">
<div className="hero-body">
<div className="container">
<div className="columns">
<div className="column is-1 is-hidden-touch is-hidden-desktop-only dontPrint"></div>
<div id="photosAndButtons" className="column is-3-widescreen is-4-tablet is-success">
<div className="card">
<div className="card-image">
<figure id="photoProfil" className="image" onMouseOver={this.glitching} >
<img fetchpriority="high" className="background" src={headshotFond} alt="Anthony Dumas" />
<img fetchpriority="high" className="actor" src={headshotMain} alt="Anthony Dumas" />
return <section id="idCard" class="hero is-medium is-info">
<div class="hero-body">
<div class="container">
<div class="columns">
<div class="column is-2 is-hidden-touch is-hidden-desktop-only dontPrint"></div>
<div id="photosAndButtons" class="column is-3-widescreen is-4-tablet is-success">
<div class="card">
<div class="card-image">
<figure id="photoProfil" class="image" onMouseOver={this.glitching} >
<img fetchpriority="high" class="background" src={headshotFond} alt="Anthony Dumas" />
<img fetchpriority="high" class="actor" src={headshotMain} alt="Anthony Dumas" />
</figure>
</div>
<div className="card-content">
<div className="media">
<div className="media-content">
<div id="buttonsUnderPhoto" className="field is-grouped">
<p className="control">
<div class="card-content">
<div class="media">
<div class="media-content">
<p id="buttonsUnderPhoto" class="field is-grouped">
<p class="control">
<ButtonIcon
icon="logo-github"
aria-label="Github"
lien="https://github.com/AdamasFR" />
</p>
<p className="control">
<p class="control">
<ButtonIcon
icon="logo-linkedin"
aria-label="Linkedin"
lien="https://www.linkedin.com/in/anthonyyvondumas/" />
</p>
<p className="control">
<p class="control">
<ButtonIcon
icon="logo-mastodon"
aria-label="Mastodon"
lien="https://social.adm.ink/@adamas" />
lien="https://imaginair.es/@adamas" />
</p>
</div>
<p id="boutonCV" className="field">
</p>
<p id="boutonCV" class="field">
<a rel="noreferrer noopener" target="_blank"
href="https://adamas-cdn.s3.fr-par.scw.cloud/portfolio/anthony-dumas-cv.pdf" >
<button className="button is-fullwidth" aria-label="Bouton Curriculum Vitæ">
<span className="icon">
href="https://files.adm.ink/anthony-dumas-cv.pdf" >
<button class="button is-fullwidth" aria-label="Bouton Curriculum Vitæ">
<span class="icon">
<ion-icon name="document-attach-outline"></ion-icon>
</span>
<span><FormattedMessage id="curriculumVitaeLink" /></span>
@ -98,22 +70,22 @@ class MainCard extends Component {
</div>
</div>
<div className="content">
<div class="content">
</div>
</div>
</div>
</div>
<div className="column is-9-tablet is-7-widescreen" id="experiences">
<span className="title">{experienceCardMessage.title.experience}</span>
<div class="column is-9-tablet is-7-widescreen" id="experiences">
<span class="title">{experienceCardMessage.title.experience}</span>
{experienceCardMessage.experiences.map(function (experience, index) {
return <ExperienceCard key={index}
return <ExperienceCard
data={experience} />;
})}
<span className="title">{experienceCardMessage.title.education}</span>
<span class="title">{experienceCardMessage.title.education}</span>
{experienceCardMessage.education.map(function (education, index) {
return <ExperienceCard key={index}
return <ExperienceCard
data={education} />;
})}
</div>

View File

@ -1,3 +1,5 @@
@import "../../_sass/main.scss";
#photoProfil {
overflow: clip;
border: 1px solid #3c3c3c;

View File

@ -1,8 +1,8 @@
import './MenuComponent.scss';
import React, { Component } from 'react';
import { FormattedMessage, injectIntl } from 'react-intl';
import React, { Component } from 'react';
import { URL_add_parameter } from '../../services/parameters.service';
@ -22,22 +22,21 @@ class MenuComponent extends Component {
render() {
const buttonsLanguagesMessage = this.props.intl.messages.global.buttons.languages;
const currentJob = this.props.intl.messages.experienceCard.experiences[0];
return <section id="menu" className="hero is-primary dontPrint">
<div className="hero-body">
<div className="container">
<div className="columns">
<div className="column">
<h1 className="title">
return <section id="menu" class="hero is-primary dontPrint">
<div class="hero-body">
<div class="container">
<div class="columns">
<div class="column">
<h1 class="title">
<FormattedMessage id="title" />
</h1>
<h2 className="subtitle">
{currentJob.occupation} @ {currentJob.entreprise}
<h2 class="subtitle">
<FormattedMessage id="subtitle" />
</h2>
</div>
<div className="column is-hidden-touch">
<div class="column is-hidden-touch">
<div id="langButtons">
<div className="buttons">
<div class="buttons">
<span className="button is-light" onClick={this.honhonhon} aria-label="Visiter le site en Français">
{buttonsLanguagesMessage.fr}
</span>

View File

@ -1,29 +1,25 @@
import './ProjectCard.scss';
import React, { Component } from 'react';
import React, {Component} from 'react';
import './ProjectCard.scss'
export default class ProjectCard extends Component {
render() {
const data = this.props.data;
return <div className="tile is-vertical is-4">
<div className="tile">
<div className="cell">
<article className="box notification is-info">
<p className="title">
<a href={data.url} rel="noopener noreferrer" target="_blank">{data.title}</a>
</p>
<a href={data.url} rel="noopener noreferrer" target="_blank">
<figure className="image is-4by3">
<img src={data.image}
alt={data.imgAlt}
title={data.imgTitle} />
</figure>
</a>
</article>
</div>
</div>
</div>;
return <div class="tile is-vertical is-4">
<div class="tile">
<div class="tile is-parent">
<article class="tile is-child notification is-info">
<p class="title">{data.title}</p>
<a href={data.url} rel="noopener noreferrer" target="_blank">
<figure class="image is-4by3">
<img src={data.image}
alt={data.imgAlt}
title={data.imgTitle} />
</figure>
</a>
</article>
</div>
</div>
</div>;
}
}
}

View File

@ -1,20 +1,20 @@
import './ProjectsCard.scss';
import React, { Component } from 'react';
import { injectIntl } from 'react-intl';
import React, { Component } from 'react';
import ProjectCard from '../ProjectCard/index';
class ProjectsCard extends Component {
render() {
const projectCardsMessage = this.props.intl.messages.projectCard;
return <section id="projets" className="hero is-success">
<div className="hero-body">
<div className="container">
<div className="grid">
return <section id="projets" class="hero is-success">
<div class="hero-body">
<div class="container">
<div class="tile is-ancestor">
{projectCardsMessage.projects.map(function (projects, index) {
return <ProjectCard key={index}
return <ProjectCard
data={projects}
/>;
})}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 347 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

View File

@ -1,5 +1,6 @@
{
"title": "Anthony Yvon Dumas",
"subtitle": "Software Developer @ Harvest",
"curriculumVitaeLink": "CV (in .pdf)",
"experienceCard": {
"title": {
@ -7,36 +8,16 @@
"education": "Education"
},
"experiences": [
{
"occupation": "Senior Engineer",
"logo": "../../images/logos/soprasteria.co.uk.webp",
"url": "https://www.soprasteria.com/",
"duration": "since June 2023",
"entreprise": "Sopra Steria Group",
"location": "Clermont-Ferrand",
"description": "Fullstack Developer @ Michelin [since 02/24]<br/>Developer for Imprimerie Nationale [06/23 - 02/24]",
"tags": ["Java", "Angular", "Spring", "DevOps", "Linux", "Azure", "Scrum"]
},
{
"occupation": "Distribution Coordinator",
"logo": "../../images/logos/laclameur.org.webp",
"url": "https://www.laclameur.org",
"duration": "since 2021",
"entreprise": "La Clameur (Non-Profit Law 1901)",
"location": "remote",
"description": "",
"tags": ["Notion", "CPanel", "Wordpress", "RSS", "Podcast Distribution"]
},
{
"occupation": "Software Developer",
"logo": "../../images/logos/harvest.fr.webp",
"url": "https://www.harvest.fr",
"duration": "July 2016 - June 2023",
"entreprise": "Harvest Group",
"duration": "(since 2016)",
"entreprise": "Harvest",
"location": "Clermont-Ferrand",
"description": "Development of responsive websites and APIs for wealth management and finance professionals.",
"tags": [
"Java",
"Java EE",
"Angular",
"OpenAPI",
"jQuery",
@ -44,6 +25,16 @@
"Scrum Environment"
]
},
{
"occupation": "Event Coordinator",
"logo": "../../images/logos/laclameur.org.webp",
"url": "https://www.laclameur.org",
"duration": "since 2021",
"entreprise": "La Clameur (Non-Profit Law 1901)",
"location": "remote",
"description": "",
"tags": ["Notion", "CPanel", "Wordpress", "RSS"]
},
{
"occupation": "Internship as IOT Developer",
"logo": "../../images/logos/michelin.webp",
@ -84,13 +75,6 @@
"image": "../../images/portfolio/admPhotos.webp",
"imgAlt": "A picture of a beautiful town.",
"imgTitle": "A picture of a beautiful town."
},
{
"title": "Blog",
"url": "https://blog.adm.ink/?referer=portfolio",
"image": "../../images/portfolio/blog.webp",
"imgAlt": "Screenshot of blog.adm.ink, you can see the title of the blog and various links. You can also see a plate of food, I think it was hummous.",
"imgTitle": "Screenshot of blog.adm.ink, you can see the title of the blog and various links. You can also see a plate of food, I think it was hummous."
}
]
},
@ -111,20 +95,20 @@
"aria-label": "LinkedIn"
},
{
"title": "Signal",
"url": "https://signal.me/#eu/cpQOzblF-DM6sltmP6s58NYmnxMUEQHE-IxRnLPHXXaE7oQJc_JHGrIlVulPwGgu",
"title": "Telegram",
"url": "https://t.me/adamas_FR",
"icon": "call-outline",
"aria-label": "Signal"
"aria-label": "Telegram"
},
{
"title": "Mastodon",
"url": "https://social.adm.ink/@adamas",
"url": "https://imaginair.es/@adamas",
"icon": "logo-mastodon",
"aria-label": "Mastodon"
}
]
},
"footer": {
"legalNotice": "© 2014 - 2024 Anthony Dumas."
"legalNotice": "© 2014 - 2023 Anthony Dumas."
}
}

View File

@ -1,5 +1,6 @@
{
"title": "Anthony Yvon Dumas",
"subtitle": "Software Developer @ Harvest",
"curriculumVitaeLink": "CV (.pdf)",
"experienceCard": {
"title": {
@ -8,72 +9,31 @@
},
"experiences": [
{
"occupation": "Senior Engineer",
"logo": "../../images/logos/soprasteria.co.uk.webp",
"url": "https://www.soprasteria.com/",
"duration": "depuis 06/2023",
"entreprise": "Sopra Steria Group",
"occupation": "Software Developer",
"logo": "../../images/logos/harvest.fr.webp",
"url": "https://www.harvest.fr",
"duration": "depuis 2016",
"entreprise": "Harvest",
"location": "Clermont-Ferrand",
"description": "Développement de simulateurs dédiés au conseil et à la vente de produits bancaires.",
"tags": [
"Java",
"Java EE",
"Angular",
"OpenAPI",
"jQuery",
"Spring",
"DevOps",
"Linux",
"Azure",
"Scrum"
],
"missions": [
{
"entreprise": "Sprint Break",
"logo": "../../images/logos/soprasteria.co.uk.webp",
"url": "https://www.michelin.fr",
"occupation": "Trésorier",
"duration": "depuis 03/2025",
"situation": "@"
},
{
"entreprise": "Michelin",
"logo": "../../images/logos/michelin.webp",
"url": "https://www.michelin.fr",
"occupation": "Fullstack Developer",
"duration": "depuis 02/2024",
"situation": "@"
},
{
"entreprise": "IN Groupe",
"logo": "../../images/logos/ingroupe.webp",
"url": "https://ingroupe.com/fr/",
"occupation": "Maintenance Applicative",
"duration": "06/2023 - 02/2024",
"situation": "pour"
}
"Environnement Scrum"
]
},
{
"occupation": "Responsable Distribution",
"occupation": "Coordinateur événementiel",
"logo": "../../images/logos/laclameur.org.webp",
"url": "https://www.laclameur.org",
"duration": "depuis 2021",
"entreprise": "La Clameur (Association Loi 1901)",
"location": "en distanciel",
"description": "Maintenance du site Internet et des fluxs RSS, communication interne.",
"tags": [
"CPanel",
"Wordpress",
"Distribution de Podcast",
"NoCode (n8n, Make.com)"
]
},
{
"occupation": "Software Developer",
"logo": "../../images/logos/harvest.fr.webp",
"url": "https://www.harvest.fr",
"duration": "2016 - 2023",
"entreprise": "Harvest Groupe",
"location": "Clermont-Ferrand",
"description": "Développement de simulateurs Web dédiés au conseil et à la vente de produits bancaires.",
"tags": ["Java", "Angular", "OpenAPI", "Accessibilité", "jQuery", "Spring", "Scrum"]
"description": "Coordination des événements de l'association, maintenance du site Internet et des fluxs RSS.",
"tags": ["Notion", "CPanel", "Wordpress", "RSS"]
},
{
"occupation": "Stagiaire Développeur Internet des Objets",
@ -87,7 +47,6 @@
"MongoDB",
"Node.js",
"Word",
"IBM Bluemix",
"Powerpoint",
"Environnement Scrum"
]
@ -102,18 +61,28 @@
"entreprise": "Université d'Auvergne",
"location": "Le Puy-en-Velay",
"description": "Programmation 3D temps réel, Web, infographie 3D, retouche d'image.",
"tags": ["Web Design", "Unity", "3DSMax", "Photoshop", "C++", "Python", "Gestion de Projet"]
"tags": ["Unity", "3DSMax", "Photoshop", "C++", "Python", "Web Design"]
},
{
"occupation": "L2 Informatique",
"logo": "../../images/logos/www.uca.fr.webp",
"url": "https://www.uca.fr",
"duration": "2016",
"entreprise": "Université Clermont-Auvergne",
"location": "Clermont-Ferrand",
"description": "",
"tags": ["Python", "Linux"]
}
]
},
"projectCard": {
"projects": [
{
"title": "adamas.dev",
"url": "https://adamas.dev/?referer=portfolio",
"image": "../../images/portfolio/blog.webp",
"imgAlt": "Capture d'écran de adamas.dev. On peut y voir le logo du blog, ainsi que quelques liens de navigations, ainsi que la photo accompagnant un article, une assiete de houmous.",
"imgTitle": "Capture d'écran de adamas.dev. On peut y voir le logo du blog, ainsi que quelques liens de navigations, ainsi que la photo accompagnant un article, une assiete de houmous"
"title": "IOT@Michelin",
"url": "https://prezi.com/m/o8ey8mmpnkvp/",
"image": "../../images/portfolio/computerNonSense.webp",
"imgAlt": "Une photo d'un micro ordinateur dans ma main",
"imgTitle": "Une photo d'un micro ordinateur dans ma main"
},
{
"title": "ADM Photographie",
@ -121,13 +90,6 @@
"image": "../../images/portfolio/admPhotos.webp",
"imgAlt": "Une photo du village de mon enfance",
"imgTitle": "Une photo du village de mon enfance"
},
{
"title": "IOT@Michelin",
"url": "https://prezi.com/m/o8ey8mmpnkvp/",
"image": "../../images/portfolio/computerNonSense.webp",
"imgAlt": "Une photo d'un micro ordinateur dans ma main",
"imgTitle": "Une photo d'un micro ordinateur dans ma main"
}
]
},
@ -148,20 +110,20 @@
"aria-label": "LinkedIn"
},
{
"title": "Signal",
"url": "https://signal.me/#eu/cpQOzblF-DM6sltmP6s58NYmnxMUEQHE-IxRnLPHXXaE7oQJc_JHGrIlVulPwGgu",
"title": "Telegram",
"url": "https://t.me/adamas_FR",
"icon": "call-outline",
"aria-label": "Signal"
"aria-label": "Telegram"
},
{
"title": "Mastodon",
"url": "https://social.adm.ink/@adamas",
"url": "https://imaginair.es/@adamas",
"icon": "logo-mastodon",
"aria-label": "Mastodon"
}
]
},
"footer": {
"legalNotice": "© 2014 - 2025 Anthony Yvon Dumas."
"legalNotice": "© 2014 - 2023 Anthony Dumas."
}
}

View File

@ -1,138 +0,0 @@
{
"title": "Anthony Yvon Dumas",
"curriculumVitaeLink": "CV (.pdf)",
"experienceCard": {
"title": {
"experience": "Expériences professionnelles",
"education": "Études et diplômes"
},
"experiences": [
{
"occupation": "Ingénieur Logiciel",
"logo": "../../images/logos/soprasteria.co.uk.webp",
"url": "https://www.soprasteria.com/",
"duration": "depuis Juin 2023",
"entreprise": "Sopra Steria",
"location": "Clermont-Ferrand",
"description": "",
"tags": ["Java EE"]
},
{
"occupation": "Software Developer",
"logo": "../../images/logos/harvest.fr.webp",
"url": "https://www.harvest.fr",
"duration": "Juillet 2016 - Juin 2023",
"entreprise": "Harvest Groupe",
"location": "Clermont-Ferrand",
"description": "Développement de simulateurs dédiés au conseil et à la vente de produits bancaires.",
"tags": [
"Java EE",
"Angular",
"OpenAPI",
"jQuery",
"Spring",
"Environnement Scrum"
]
},
{
"occupation": "Coordinateur événementiel",
"logo": "../../images/logos/laclameur.org.webp",
"url": "https://www.laclameur.org",
"duration": "depuis 2021",
"entreprise": "La Clameur (Association Loi 1901)",
"location": "en distanciel",
"description": "Coordination des événements de l'association, maintenance du site Internet et des fluxs RSS.",
"tags": ["Notion", "CPanel", "Wordpress", "RSS"]
},
{
"occupation": "Stagiaire Développeur Internet des Objets",
"logo": "../../images/logos/michelin.webp",
"url": "https://www.michelin.fr",
"duration": "2015",
"entreprise": "Michelin",
"location": "Clermont-Ferrand",
"description": "Stage de fin d'étude DUT, etude du marché des objets connectés, création d'un prototype embarqué.",
"tags": [
"MongoDB",
"Node.js",
"Word",
"Powerpoint",
"Environnement Scrum"
]
}
],
"education": [
{
"occupation": "DUT Informatique - Imagerie Numérique",
"logo": "../../images/logos/www.iut-clermont.webp",
"url": "https://www.iut-clermont.fr/",
"duration": "Promotion 2015",
"entreprise": "Université d'Auvergne",
"location": "Le Puy-en-Velay",
"description": "Programmation 3D temps réel, Web, infographie 3D, retouche d'image.",
"tags": ["Unity", "3DSMax", "Photoshop", "C++", "Python", "Web Design"]
},
{
"occupation": "L2 Informatique",
"logo": "../../images/logos/www.uca.fr.webp",
"url": "https://www.uca.fr",
"duration": "2016",
"entreprise": "Université Clermont-Auvergne",
"location": "Clermont-Ferrand",
"description": "",
"tags": ["Python", "Linux"]
}
]
},
"projectCard": {
"projects": [
{
"title": "IOT@Michelin",
"url": "https://prezi.com/m/o8ey8mmpnkvp/",
"image": "../../images/portfolio/computerNonSense.webp",
"imgAlt": "Une photo d'un micro ordinateur dans ma main",
"imgTitle": "Une photo d'un micro ordinateur dans ma main"
},
{
"title": "ADM Photographie",
"url": "https://photos.adm.ink/",
"image": "../../images/portfolio/admPhotos.webp",
"imgAlt": "Une photo du village de mon enfance",
"imgTitle": "Une photo du village de mon enfance"
}
]
},
"contactCard": {
"title": "Contact",
"subtitle": "Vous pouvez me contacter de nombreuses façons !",
"ways": [
{
"title": "Courriel",
"url": "mailto:anthony@dumas.cc",
"icon": "mail-outline",
"aria-label": "Email"
},
{
"title": "LinkedIn",
"url": "https://www.linkedin.com/in/anthonyyvondumas/",
"icon": "logo-linkedin",
"aria-label": "LinkedIn"
},
{
"title": "Telegram",
"url": "https://t.me/adamas_FR",
"icon": "call-outline",
"aria-label": "Telegram"
},
{
"title": "Mastodon",
"url": "https://imaginair.es/@adamas",
"icon": "logo-mastodon",
"aria-label": "Mastodon"
}
]
},
"footer": {
"legalNotice": "© 2014 - 2023 Anthony Dumas."
}
}

View File

@ -23,11 +23,7 @@ export const language = function () {
};
export const langJson = function () {
return getTexts(language());
};
export const getTexts = function (lang) {
const messageLocalized = i18nConfig.messages[lang];
const messageLocalized = i18nConfig.messages[language()];
const messageGlobal = i18nConfig.messages[GLOBAL_MESSAGE_KEY];
const messageMerged = {
...messageLocalized,

0
test
View File