Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
36f41da726 | ||
|
6bfcb74ad9 | ||
|
92cd105ed4 | ||
|
0fc5716da7 | ||
|
c285d3b69e | ||
|
c594577415 | ||
|
3ed686cddd | ||
|
7921d06785 | ||
|
80ec73f3df | ||
|
739b8cacb1 | ||
|
413bea05b9 | ||
|
02afd47f23 | ||
|
2cbaeda4d8 | ||
|
b60da974db |
131
.github/CODE_OF_CONDUCT.md
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
# Code de conduite _Contributor Covenant_
|
||||
|
||||
## Notre engagement
|
||||
|
||||
En tant que membres, contributeur•trice•s et dirigeant•e•s, nous nous
|
||||
engageons à faire de la participation à notre communauté
|
||||
une expérience sans harcèlement, quel que soit l'âge,
|
||||
la taille corporelle, le handicap visible ou invisible, l'appartenance ethnique,
|
||||
les caractéristiques sexuelles, l'identité et l'expression de genre,
|
||||
le niveau d'expérience, l'éducation, le statut socio-économique,
|
||||
la nationalité, l'apparence personnelle, la race, la religion,
|
||||
ou l'identité et l'orientation sexuelle.
|
||||
|
||||
Nous nous engageons à agir et interagir de manière à contribuer à une communauté
|
||||
ouverte, accueillante, diversifiée, inclusive et saine.
|
||||
|
||||
## Nos critères
|
||||
|
||||
Exemples de comportements qui contribuent à créer un environnement positif :
|
||||
|
||||
- Faire preuve d'empathie et de bienveillance envers les autres
|
||||
- Être respectueux des opinions, points de vue et expériences divergents
|
||||
- Donner et recevoir avec grâce les critiques constructives
|
||||
- Assumer ses responsabilités et s'excuser auprès des personnes affectées par nos erreurs et apprendre de ces expériences
|
||||
- Se concentrer sur ce qui est le meilleur non pas uniquement pour nous en tant qu'individu, mais aussi pour l'ensemble de la communauté
|
||||
|
||||
Exemples de comportements inacceptables :
|
||||
|
||||
- L'utilisation de langage ou d'images sexualisés et d'attentions ou d'avances sexuelles de toute nature
|
||||
- Le _trolling_, les commentaires insultants ou désobligeants et les attaques
|
||||
personnelles ou d'ordre politique
|
||||
- Le harcèlement en public ou en privé
|
||||
- La publication d'informations privées d'autrui, telle qu'une
|
||||
adresse postale ou une adresse électronique, sans leur autorisation explicite
|
||||
- Toute autre conduite qui pourrait raisonnablement être considérée comme inappropriée
|
||||
dans un cadre professionnel
|
||||
|
||||
## Responsabilités d'application
|
||||
|
||||
Les dirigeant•e•s de la communauté sont chargé•e•s de clarifier et de faire respecter nos normes de
|
||||
comportements acceptables et prendront des mesures correctives appropriées et équitables en
|
||||
réponse à tout comportement qu'ils ou elles jugent inapproprié, menaçant, offensant ou nuisible.
|
||||
|
||||
Les dirigeant•e•s de la communauté ont le droit et la responsabilité de supprimer, modifier ou rejeter
|
||||
les commentaires, les contributions, le code, les modifications de wikis, les rapports d'incidents ou de bogues et autres contributions qui
|
||||
ne sont pas alignés sur ce code de conduite, et communiqueront les raisons des décisions de modération
|
||||
le cas échéant.
|
||||
|
||||
## Portée d'application
|
||||
|
||||
Ce code de conduite s'applique à la fois au sein des espaces du projet ainsi que
|
||||
dans les espaces publics lorsqu'un individu représente officiellement le projet ou sa
|
||||
communauté. Font parties des exemples de représentation d'un projet ou d'une
|
||||
communauté l'utilisation d'une adresse électronique officielle, la publication sur
|
||||
les réseaux sociaux à l'aide d'un compte officiel ou le fait d'agir en tant que représentant•e désigné•e
|
||||
lors d'un événement en ligne ou hors-ligne.
|
||||
|
||||
## Application
|
||||
|
||||
Les cas de comportements abusifs, harcelants ou tout autre comportement
|
||||
inacceptables peuvent être signalés aux dirigeant•e•s de la communauté responsables de l'application du code de conduite à
|
||||
contact@divlo.fr.
|
||||
Toutes les plaintes seront examinées et feront l'objet d'une enquête rapide et équitable.
|
||||
|
||||
Tou•te•s les dirigeant•e•s de la communauté sont tenu•e•s de respecter la vie privée et la sécurité des
|
||||
personnes ayant signalé un incident.
|
||||
|
||||
## Directives d'application
|
||||
|
||||
Les dirigeant•e•s de communauté suivront ces directives d'application sur l'impact communautaire afin de déterminer
|
||||
les conséquences de toute action qu'ils jugent contraire au présent code de conduite :
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Impact communautaire** : utilisation d'un langage inapproprié ou tout autre comportement jugé
|
||||
non professionnel ou indésirable dans la communauté.
|
||||
|
||||
**Conséquence** : un avertissement écrit et privé de la part des dirigeant•e•s de la communauté, clarifiant
|
||||
la nature du non-respect et expliquant pourquoi
|
||||
le comportement était inapproprié. Des excuses publiques peuvent être demandées.
|
||||
|
||||
### 2. Avertissement
|
||||
|
||||
**Impact communautaire** : un non-respect par un seul incident ou une série d'actions.
|
||||
|
||||
**Conséquence** : un avertissement avec des conséquences dû à la poursuite du comportement.
|
||||
Aucune interaction avec les personnes concernées, y compris l'interaction non sollicitée avec
|
||||
celles et ceux qui sont chargé•e•s de l'application de ce code de conduite, pendant une période déterminée.
|
||||
Cela comprend le fait d'éviter les interactions dans les espaces communautaires ainsi que sur les canaux externes
|
||||
comme les médias sociaux. Le non-respect de ces conditions peut entraîner
|
||||
un bannissement temporaire ou permanent.
|
||||
|
||||
### 3. Bannissement temporaire
|
||||
|
||||
**Impact communautaire** : un non-respect grave des normes communautaires, notamment
|
||||
un comportement inapproprié soutenu.
|
||||
|
||||
**Conséquence** : un bannissement temporaire de toutes formes d'interactions ou de
|
||||
communications avec la communauté pendant une période déterminée. Aucune interaction publique ou
|
||||
privée avec les personnes concernées, y compris les interactions non sollicitées
|
||||
avec celles et ceux qui appliquent ce code de conduite, n'est autorisée pendant cette période.
|
||||
Le non-respect de ces conditions peut entraîner un bannissement permanent.
|
||||
|
||||
### 4. Bannissement permanent
|
||||
|
||||
**Impact communautaire** : démontrer un schéma récurrent de non-respect des normes de la
|
||||
communauté y compris un comportement inapproprié soutenu, le harcèlement d'un individu
|
||||
ainsi que l'agression ou le dénigrement de catégories d'individus.
|
||||
|
||||
**Conséquence** : un bannissement permanent de toutes formes d'interactions publiques au sein de
|
||||
la communauté.
|
||||
|
||||
## Attributions
|
||||
|
||||
Ce code de conduite est adapté du
|
||||
[Contributor Covenant](https://www.contributor-covenant.org), version 2.0,
|
||||
disponible à
|
||||
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
|
||||
|
||||
Les Directives d'application ont été inspirées par le
|
||||
[Code of conduct enforcement ladder][mozilla coc] de Mozilla.
|
||||
|
||||
Pour obtenir des réponses aux questions courantes sur ce code de conduite, consultez la FAQ à
|
||||
[https://www.contributor-covenant.org/faq][faq]. Les traductions sont disponibles
|
||||
sur [https://www.contributor-covenant.org/translations][translations].
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
|
||||
[mozilla coc]: https://github.com/mozilla/diversity
|
||||
[faq]: https://www.contributor-covenant.org/faq
|
||||
[translations]: https://www.contributor-covenant.org/translations
|
14
.github/ISSUE_TEMPLATE/BUG.md
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
name: '🐛 Rapport de bug'
|
||||
about: 'Signalez un problème inattendu ou un comportement involontaire.'
|
||||
labels: 'bug'
|
||||
---
|
||||
|
||||
## Étapes à suivre pour reproduire le bug
|
||||
|
||||
1. Étape 1
|
||||
2. Étape 2
|
||||
|
||||
## Comportement actuel
|
||||
|
||||
## Comportement attendu
|
7
.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
name: '✨ Ajout d'une fonctionnalité'
|
||||
about: 'Suggérer une nouvelle fonctionnalité.'
|
||||
labels: 'feature request'
|
||||
---
|
||||
|
||||
### Description
|
7
.github/ISSUE_TEMPLATE/QUESTION.md
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
name: '🙋 Question'
|
||||
about: 'Des informations complémentaires sont demandées.'
|
||||
labels: 'question'
|
||||
---
|
||||
|
||||
### Question
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
18
.github/workflows/commitlint.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
# For more information see: https://github.com/marketplace/actions/commit-linter
|
||||
|
||||
name: 'Lint Commit Messages'
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
commitlint:
|
||||
runs-on: 'ubuntu-latest'
|
||||
steps:
|
||||
- uses: 'actions/checkout@v2'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: 'wagoid/commitlint-github-action@v2'
|
61
.github/workflows/nodejs.yml
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: 'Node.js CI'
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
ci_website:
|
||||
runs-on: 'ubuntu-latest'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: 'website'
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
steps:
|
||||
- uses: 'actions/checkout@v2'
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: 'actions/setup-node@v2.1.2'
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: 'Cache dependencies'
|
||||
uses: 'actions/cache@v2'
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
|
||||
- run: 'npm install'
|
||||
- run: 'npm run lint'
|
||||
- run: 'npm run build'
|
||||
|
||||
ci_api:
|
||||
runs-on: 'ubuntu-latest'
|
||||
defaults:
|
||||
run:
|
||||
working-directory: 'api'
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x]
|
||||
steps:
|
||||
- uses: 'actions/checkout@v2'
|
||||
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: 'actions/setup-node@v2.1.2'
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: 'Cache dependencies'
|
||||
uses: 'actions/cache@v2'
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
|
||||
|
||||
- run: 'npm install'
|
||||
- run: 'npm run lint'
|
1
.gitignore
vendored
@ -1 +0,0 @@
|
||||
.github/backup
|
23
LICENSE
@ -1,8 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
Copyright © 2020 Divlo
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
Copyright (c) Divlo
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
34
README.md
@ -1,15 +1,21 @@
|
||||
<h1 align="center"><a href="https://function.divlo.fr/">FunctionProject</a></h1>
|
||||
|
||||
<p align="center">
|
||||
<strong>⚠️ Le projet n'est plus maintenu.</strong>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<strong>Apprenez la programmation grâce à l'apprentissage par projet alias fonction.</strong>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/Divlo/FunctionProject/actions?query=workflow%3A%22Node.js+CI%22"><img src="https://github.com/Divlo/FunctionProject/workflows/Node.js%20CI/badge.svg" alt="Node.js CI" /></a>
|
||||
<a href="https://standardjs.com"><img alt="JavaScript Style Guide" src="https://img.shields.io/badge/code_style-standard-brightgreen.svg"/></a>
|
||||
<a href="https://conventionalcommits.org"><img src="https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg" alt="Conventional Commits" /></a>
|
||||
<a href="./LICENSE"><img src="https://img.shields.io/badge/licence-MIT-blue.svg" alt="Licence MIT"/></a>
|
||||
<a href="https://conventionalcommits.org"><img src="https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg" alt="Conventional Commits" /></a>
|
||||
<a href="./.github/CODE_OF_CONDUCT.md"><img src="https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg" alt="Contributor Covenant" /></a>
|
||||
<br/> <br/>
|
||||
<a href="https://function.divlo.fr/"><img src="https://raw.githubusercontent.com/Divlo/FunctionProject/master/.github/FunctionProject.png" alt="FunctionProject" /></a>
|
||||
<a href="https://function.divlo.fr/"><img src="https://raw.githubusercontent.com/Divlo/FunctionProject/master/.github/images/FunctionProject.png" alt="FunctionProject" /></a>
|
||||
</p>
|
||||
|
||||
## ⚙️ À propos
|
||||
@ -22,7 +28,7 @@ Si vous aimez le projet, vous pouvez aider à **le faire connaître** en utilisa
|
||||
|
||||
Les dernières versions publiées : [https://github.com/Divlo/FunctionProject/releases](https://github.com/Divlo/FunctionProject/releases)
|
||||
|
||||
Le projet est disponible sur [function.divlo.fr](https://function.divlo.fr/) (actuellement en version 2.2).
|
||||
Le projet est disponible sur [function.divlo.fr](https://function.divlo.fr/) (actuellement en version 2.3).
|
||||
|
||||
## 🚀 Open Source
|
||||
|
||||
@ -36,13 +42,13 @@ Si vous voulez **contribuer**, avant toute chose écrivez une **"[issue](https:/
|
||||
|
||||
Si vous voulez avoir les données des catégories et des fonctions, vous pouvez d'abord lancer l'API pour que Sequelize crée les tables SQl et ensuite exécuter le fichier SQL [backup.sql](./.github/backup.sql).
|
||||
|
||||
### Prérequis :
|
||||
### Prérequis
|
||||
|
||||
- [Node.js](https://nodejs.org/) >= 14
|
||||
- [npm](https://www.npmjs.com/) >= 6
|
||||
- [MySQL](https://www.mysql.com/) >= 5.7
|
||||
- [npm](https://www.npmjs.com/) >= 7
|
||||
- [MySQL](https://www.mysql.com/) >= 8
|
||||
|
||||
### Commandes (à suivre dans l'ordre) :
|
||||
### Commandes (à suivre dans l'ordre)
|
||||
|
||||
```sh
|
||||
# Cloner le projet
|
||||
@ -58,11 +64,11 @@ cd ../website
|
||||
npm install
|
||||
```
|
||||
|
||||
Vous devrez ensuite configurer l'API en créant un fichier `.env` à la racine du dossier `/api` et prendre exemple du fichier `.env.example` avec votre configuration.
|
||||
Vous devrez ensuite configurer les variables d'environnements en créant un fichier `.env` à la racine du dossier `/api`, `/website` et `s.divlo.fr` pour prendre exemple du fichier `.env.example` avec votre configuration.
|
||||
|
||||
### Lancer l'environnement de développement :
|
||||
### Lancer l'environnement de développement
|
||||
|
||||
#### Avec [docker](https://www.docker.com/) :
|
||||
#### Avec [docker](https://www.docker.com/)
|
||||
|
||||
```sh
|
||||
# Setup and run all the services for you
|
||||
@ -78,7 +84,7 @@ docker-compose up --build
|
||||
- [MailDev](https://maildev.github.io/maildev/) : `http://localhost:1080`
|
||||
- [MySQL database](https://www.mysql.com/) (with PORT 3006)
|
||||
|
||||
#### Sans docker :
|
||||
#### Sans docker
|
||||
|
||||
Dans deux terminals séparés :
|
||||
|
||||
@ -96,8 +102,6 @@ npm run dev # API lancé sur http://localhost:8080
|
||||
|
||||
Enjoy! 😃
|
||||
|
||||
[](https://github.com/standard/standard)
|
||||
## 📄 License
|
||||
|
||||
## 📄 Licence
|
||||
|
||||
Ce projet est sous licence MIT - voir le fichier [LICENSE](./LICENSE) pour plus de détails.
|
||||
[MIT](./LICENSE)
|
||||
|
@ -1,3 +1,4 @@
|
||||
COMPOSE_PROJECT_NAME="function.divlo.fr-api"
|
||||
HOST="http://localhost:8080"
|
||||
FRONT_END_HOST="http://localhost:3000"
|
||||
OpenWeatherMap_API_KEY=""
|
||||
@ -12,4 +13,3 @@ EMAIL_HOST="functionproject-maildev"
|
||||
EMAIL_USER="no-reply@functionproject.fr"
|
||||
EMAIL_PASSWORD="password"
|
||||
EMAIL_PORT=25
|
||||
COMPOSE_PROJECT_NAME="function.divlo.fr-api"
|
||||
|
2
api/.gitignore
vendored
@ -22,7 +22,7 @@
|
||||
# misc
|
||||
.DS_Store
|
||||
/temp
|
||||
/assets/images/
|
||||
/assets/images/users
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM node:14.15.0-alpine3.12
|
||||
FROM node:14.16.1
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
BIN
api/assets/images/functions/armstrongNumber.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
api/assets/images/functions/arrayMethods.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
api/assets/images/functions/calculateAge.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
api/assets/images/functions/chronometerTimer.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
api/assets/images/functions/convertCurrency.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
api/assets/images/functions/convertDistance.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
api/assets/images/functions/convertEncoding.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
api/assets/images/functions/convertMarkdown.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
api/assets/images/functions/convertRomanArabicNumbers.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
api/assets/images/functions/convertTemperature.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
api/assets/images/functions/fibonacci.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
api/assets/images/functions/findLongestWord.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
api/assets/images/functions/heapAlgorithm.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
api/assets/images/functions/isPalindrome.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
api/assets/images/functions/linkShortener.png
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
api/assets/images/functions/randomNumber.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
api/assets/images/functions/randomQuote.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
api/assets/images/functions/rightPrice.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
api/assets/images/functions/sortArray.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
api/assets/images/functions/toDoList.png
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
api/assets/images/functions/weatherRequest.png
Normal file
After Width: | Height: | Size: 16 KiB |
6807
api/package-lock.json
generated
@ -1,38 +1,46 @@
|
||||
{
|
||||
"name": "api",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"description": "Backend REST API for FunctionProject",
|
||||
"standard": {
|
||||
"files": [
|
||||
"./**/*.js"
|
||||
],
|
||||
"envs": [
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node app.js",
|
||||
"dev": "nodemon app.js",
|
||||
"format": "standard \"./**/*.js\" --fix | snazzy"
|
||||
"lint": "standard | snazzy"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.21.0",
|
||||
"axios": "^0.21.1",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^8.2.0",
|
||||
"express": "^4.17.1",
|
||||
"express-fileupload": "^1.2.0",
|
||||
"express-fileupload": "^1.2.1",
|
||||
"express-http-to-https": "^1.1.4",
|
||||
"express-rate-limit": "^5.1.3",
|
||||
"express-validator": "^6.6.1",
|
||||
"helmet": "^4.1.1",
|
||||
"jsdom": "^16.4.0",
|
||||
"express-rate-limit": "^5.2.6",
|
||||
"express-validator": "^6.10.0",
|
||||
"helmet": "^4.4.1",
|
||||
"jsdom": "^16.5.3",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"moment": "^2.29.1",
|
||||
"morgan": "^1.10.0",
|
||||
"ms": "^2.1.2",
|
||||
"ms": "^2.1.3",
|
||||
"mysql2": "^2.2.5",
|
||||
"nodemailer": "^6.4.14",
|
||||
"sequelize": "^6.3.5",
|
||||
"nodemailer": "^6.5.0",
|
||||
"sequelize": "^6.6.2",
|
||||
"smart-request-balancer": "^2.1.1",
|
||||
"uuid": "^8.3.1",
|
||||
"validator": "^13.1.17"
|
||||
"uuid": "^8.3.2",
|
||||
"validator": "^13.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.6",
|
||||
"nodemon": "^2.0.7",
|
||||
"snazzy": "^9.0.0",
|
||||
"standard": "^16.0.0"
|
||||
"standard": "^16.0.3"
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ services:
|
||||
container_name: 'functionproject-website'
|
||||
|
||||
functionproject-phpmyadmin:
|
||||
image: 'phpmyadmin/phpmyadmin:5.0.2'
|
||||
image: 'phpmyadmin/phpmyadmin:5.1.0'
|
||||
environment:
|
||||
PMA_HOST: 'functionproject-database'
|
||||
PMA_USER: 'root'
|
||||
@ -52,7 +52,7 @@ services:
|
||||
container_name: 'functionproject-phpmyadmin'
|
||||
|
||||
functionproject-database:
|
||||
image: 'mysql:5.7'
|
||||
image: 'mysql:8.0.23'
|
||||
command: '--default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci'
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: 'password'
|
||||
|
@ -1,6 +1,6 @@
|
||||
COMPOSE_PROJECT_NAME="s.divlo.fr-website"
|
||||
DATABASE_HOST="functionproject-database"
|
||||
DATABASE_NAME="functionproject"
|
||||
DATABASE_USER="root"
|
||||
DATABASE_PASSWORD="password"
|
||||
DATABASE_PORT=3306
|
||||
COMPOSE_PROJECT_NAME="s.divlo.fr-website"
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM node:14.15.0-alpine3.12
|
||||
FROM node:14.16.1
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
5387
s.divlo.fr/package-lock.json
generated
@ -2,23 +2,31 @@
|
||||
"name": "short.divlo.fr",
|
||||
"version": "1.0.0",
|
||||
"description": "Link shortener for FunctionProject",
|
||||
"standard": {
|
||||
"files": [
|
||||
"./**/*.js"
|
||||
],
|
||||
"envs": [
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node app.js",
|
||||
"dev": "nodemon app.js",
|
||||
"format": "standard \"./**/*.js\" --fix | snazzy || exit 0"
|
||||
"lint": "standard | snazzy"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^8.2.0",
|
||||
"ejs": "^3.1.5",
|
||||
"ejs": "^3.1.6",
|
||||
"express": "^4.17.1",
|
||||
"express-http-to-https": "^1.1.4",
|
||||
"helmet": "^4.1.1",
|
||||
"helmet": "^4.4.1",
|
||||
"morgan": "^1.10.0",
|
||||
"mysql": "^2.18.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.6",
|
||||
"nodemon": "^2.0.7",
|
||||
"snazzy": "^9.0.0",
|
||||
"standard": "^16.0.0"
|
||||
"standard": "^16.0.3"
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,4 @@
|
||||
node_modules
|
||||
build
|
||||
dist
|
||||
.next
|
||||
|
@ -1,3 +1,3 @@
|
||||
NEXT_PUBLIC_API_URL = "http://localhost:8080"
|
||||
CONTAINER_API_URL="http://functionproject-api:8080"
|
||||
COMPOSE_PROJECT_NAME="function.divlo.fr-website"
|
||||
NEXT_PUBLIC_API_URL="http://localhost:8080"
|
||||
CONTAINER_API_URL="http://functionproject-api:8080"
|
||||
|
36
website/.gitignore
vendored
@ -1,22 +1,24 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
node_modules
|
||||
.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
.yarn
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
.next
|
||||
out
|
||||
|
||||
# production
|
||||
/build
|
||||
build
|
||||
dist
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
# PWA
|
||||
**/public/workbox-*.js
|
||||
**/public/sw.js
|
||||
|
||||
# envs
|
||||
.env
|
||||
.env.production
|
||||
|
||||
@ -24,3 +26,17 @@
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# lockfiles
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
pnpm-lock.yaml
|
||||
|
||||
# editors
|
||||
.vscode
|
||||
.theia
|
||||
.idea
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.lighthouseci
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM node:14.15.0-alpine3.12
|
||||
FROM node:14.16.1
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
34
website/components/Footer.jsx
Normal file
@ -0,0 +1,34 @@
|
||||
import Link from 'next/link'
|
||||
|
||||
export default function Footer () {
|
||||
return (
|
||||
<>
|
||||
<footer className='footer'>
|
||||
<p className='footer-text text-center'>
|
||||
<Link href='/about'>
|
||||
<a>FunctionProject</a>
|
||||
</Link>
|
||||
- Version 2.3 <br />
|
||||
<a href='https://divlo.fr/' target='_blank' rel='noopener noreferrer'>
|
||||
Divlo
|
||||
</a>{' '}
|
||||
| Tous droits réservés
|
||||
</p>
|
||||
</footer>
|
||||
|
||||
<style jsx>{`
|
||||
.footer {
|
||||
border-top: var(--border-header-footer);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.footer-text {
|
||||
line-height: 2.5;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</>
|
||||
)
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
.footer {
|
||||
border-top: var(--border-header-footer);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.footer-text {
|
||||
line-height: 2.5;
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
import Link from 'next/link'
|
||||
import './Footer.css'
|
||||
|
||||
export default function Footer () {
|
||||
return (
|
||||
<footer className='footer'>
|
||||
<p className='footer-text text-center'>
|
||||
<Link href='/about'>
|
||||
<a>FunctionProject</a>
|
||||
</Link>
|
||||
- Version 2.2 <br />
|
||||
<a href='https://divlo.fr/' target='_blank' rel='noopener noreferrer'>
|
||||
Divlo
|
||||
</a>{' '}
|
||||
| Tous droits réservés
|
||||
</p>
|
||||
</footer>
|
||||
)
|
||||
}
|
@ -3,7 +3,6 @@ import htmlParser from 'html-react-parser'
|
||||
import Loader from '../Loader'
|
||||
import useAPI from '../../hooks/useAPI'
|
||||
import api from '../../utils/api'
|
||||
import '../../public/css/pages/admin.css'
|
||||
|
||||
const AddEditFunction = props => {
|
||||
const [, categories] = useAPI('/categories')
|
||||
|
@ -3,8 +3,6 @@ import dynamic from 'next/dynamic'
|
||||
import { complex } from '../../utils/sunEditorConfig'
|
||||
import api from '../../utils/api'
|
||||
import FunctionArticle from '../FunctionPage/FunctionArticle'
|
||||
import 'notyf/notyf.min.css'
|
||||
import '../../public/css/suneditor.min.css'
|
||||
|
||||
const SunEditor = dynamic(() => import('suneditor-react'), { ssr: false })
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { useState } from 'react'
|
||||
import api from '../../utils/api'
|
||||
import 'notyf/notyf.min.css'
|
||||
|
||||
const EditFormFunction = props => {
|
||||
const [inputsArray, setInputsArray] = useState(
|
||||
|
@ -1,67 +0,0 @@
|
||||
.FunctionCard {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
word-wrap: break-word;
|
||||
box-shadow: 0px 0px 6px 6px rgba(0, 0, 0, 0.25);
|
||||
border: 1px solid black;
|
||||
border-radius: 1rem;
|
||||
margin: 0 0 50px 0;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
color: var(--text-color);
|
||||
text-decoration: none !important;
|
||||
}
|
||||
.FunctionCard__container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.FunctionCard:hover {
|
||||
transform: translateY(-7px);
|
||||
}
|
||||
/* col-md */
|
||||
@media (min-width: 768px) {
|
||||
.FunctionCard {
|
||||
margin: 0 30px 50px 30px;
|
||||
}
|
||||
}
|
||||
/* col-xl */
|
||||
@media (min-width: 1200px) {
|
||||
.FunctionCard {
|
||||
margin: 0 20px 50px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.FunctionCard__top {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.FunctionCard__image {
|
||||
width: 150px;
|
||||
}
|
||||
.FunctionCard__title {
|
||||
font-size: 1.4em;
|
||||
margin: 0;
|
||||
color: var(--important);
|
||||
font-weight: 300;
|
||||
}
|
||||
.FunctionCard__description {
|
||||
margin: 20px 0 10px 0;
|
||||
}
|
||||
.FunctionCard__info {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
.FunctionCard__category {
|
||||
border-radius: 0.5em;
|
||||
padding: 0.5em;
|
||||
margin-right: 20px;
|
||||
font-size: 16.4px;
|
||||
}
|
@ -3,7 +3,6 @@ import { useState, forwardRef, memo } from 'react'
|
||||
import date from 'date-and-time'
|
||||
import Loader from '../Loader'
|
||||
import { API_URL } from '../../utils/api'
|
||||
import './FunctionCard.css'
|
||||
|
||||
const FunctionCard = memo(
|
||||
forwardRef((props, ref) => {
|
||||
@ -13,66 +12,139 @@ const FunctionCard = memo(
|
||||
setIsLoading(false)
|
||||
}
|
||||
|
||||
const handleError = event => {
|
||||
const handleError = (event) => {
|
||||
event.target.src = API_URL + '/images/functions/default.png'
|
||||
}
|
||||
|
||||
const isFormOrArticle = props.type === 'form' || props.type === 'article'
|
||||
|
||||
return (
|
||||
<Link
|
||||
{...(props.isAdmin
|
||||
? {
|
||||
href: '/admin/[slug]',
|
||||
as: `/admin/${props.slug}`
|
||||
}
|
||||
: {
|
||||
href: isFormOrArticle
|
||||
? '/functions/[slug]'
|
||||
: `/functions/${props.slug}`,
|
||||
as: `/functions/${props.slug}`
|
||||
})}
|
||||
>
|
||||
{/* FunctionCard a une hauteur pendant chargement */}
|
||||
<a
|
||||
ref={ref}
|
||||
style={
|
||||
isLoading ? { height: '360px', justifyContent: 'center' } : null
|
||||
}
|
||||
className='FunctionCard col-sm-24 col-md-10 col-xl-7'
|
||||
<>
|
||||
<Link
|
||||
{...(props.isAdmin
|
||||
? {
|
||||
href: '/admin/[slug]',
|
||||
as: `/admin/${props.slug}`
|
||||
}
|
||||
: {
|
||||
href: isFormOrArticle
|
||||
? '/functions/[slug]'
|
||||
: `/functions/${props.slug}`,
|
||||
as: `/functions/${props.slug}`
|
||||
})}
|
||||
>
|
||||
{isLoading && <Loader width='125px' height='125px' />}
|
||||
|
||||
<div
|
||||
className={`FunctionCard__container ${isLoading ? 'd-none' : ''}`}
|
||||
{/* FunctionCard a une hauteur pendant chargement */}
|
||||
<a
|
||||
ref={ref}
|
||||
style={
|
||||
isLoading ? { height: '360px', justifyContent: 'center' } : null
|
||||
}
|
||||
className='FunctionCard col-sm-24 col-md-10 col-xl-7'
|
||||
>
|
||||
<div className='FunctionCard__top'>
|
||||
<img
|
||||
onLoad={handleLoad}
|
||||
onError={handleError}
|
||||
className='FunctionCard__image'
|
||||
alt={props.title}
|
||||
src={API_URL + props.image}
|
||||
/>
|
||||
<h2 className='FunctionCard__title'>{props.title}</h2>
|
||||
<p className='FunctionCard__description text-center'>
|
||||
{props.description}
|
||||
</p>
|
||||
{isLoading && <Loader width='125px' height='125px' />}
|
||||
|
||||
<div
|
||||
className={`FunctionCard__container ${isLoading ? 'd-none' : ''}`}
|
||||
>
|
||||
<div className='FunctionCard__top'>
|
||||
<img
|
||||
onLoad={handleLoad}
|
||||
onError={handleError}
|
||||
className='FunctionCard__image'
|
||||
alt={props.title}
|
||||
src={API_URL + props.image}
|
||||
/>
|
||||
<h2 className='FunctionCard__title'>{props.title}</h2>
|
||||
<p className='FunctionCard__description text-center'>
|
||||
{props.description}
|
||||
</p>
|
||||
</div>
|
||||
<div className='FunctionCard__info'>
|
||||
<p
|
||||
className='FunctionCard__category'
|
||||
style={{ backgroundColor: props.categorie.color }}
|
||||
>
|
||||
{props.categorie.name}
|
||||
</p>
|
||||
<p className='FunctionCard__publication-date'>
|
||||
{date.format(new Date(props.createdAt), 'DD/MM/YYYY', false)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className='FunctionCard__info'>
|
||||
<p
|
||||
className='FunctionCard__category'
|
||||
style={{ backgroundColor: props.categorie.color }}
|
||||
>
|
||||
{props.categorie.name}
|
||||
</p>
|
||||
<p className='FunctionCard__publication-date'>
|
||||
{date.format(new Date(props.createdAt), 'DD/MM/YYYY', false)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</Link>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<style jsx>{`
|
||||
.FunctionCard {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
flex-direction: column;
|
||||
word-wrap: break-word;
|
||||
box-shadow: 0px 0px 6px 6px rgba(0, 0, 0, 0.25);
|
||||
border: 1px solid black;
|
||||
border-radius: 1rem;
|
||||
margin: 0 0 50px 0;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
color: var(--text-color);
|
||||
text-decoration: none !important;
|
||||
}
|
||||
.FunctionCard__container {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.FunctionCard:hover {
|
||||
transform: translateY(-7px);
|
||||
}
|
||||
/* col-md */
|
||||
@media (min-width: 768px) {
|
||||
.FunctionCard {
|
||||
margin: 0 30px 50px 30px;
|
||||
}
|
||||
}
|
||||
/* col-xl */
|
||||
@media (min-width: 1200px) {
|
||||
.FunctionCard {
|
||||
margin: 0 20px 50px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.FunctionCard__top {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.FunctionCard__image {
|
||||
width: 150px;
|
||||
}
|
||||
.FunctionCard__title {
|
||||
font-size: 1.4em;
|
||||
margin: 0;
|
||||
color: var(--important);
|
||||
font-weight: 300;
|
||||
}
|
||||
.FunctionCard__description {
|
||||
margin: 20px 0 10px 0;
|
||||
}
|
||||
.FunctionCard__info {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
.FunctionCard__category {
|
||||
border-radius: 0.5em;
|
||||
padding: 0.5em;
|
||||
margin-right: 20px;
|
||||
font-size: 16.4px;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</>
|
||||
)
|
||||
})
|
||||
)
|
||||
|
@ -6,7 +6,6 @@ import { UserContext } from '../../../contexts/UserContext'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import CodeBlock from '../../CodeBlock'
|
||||
import api, { API_URL } from '../../../utils/api'
|
||||
import './CommentCard.css'
|
||||
|
||||
const CommentCard = forwardRef((props, ref) => {
|
||||
const { isAuth, user } = useContext(UserContext)
|
||||
|
@ -4,7 +4,6 @@ import { UserContext } from '../../../contexts/UserContext'
|
||||
import CommentCard from '../CommentCard/CommentCard'
|
||||
import Loader from '../../Loader'
|
||||
import api from '../../../utils/api'
|
||||
import './FunctionComments.css'
|
||||
|
||||
const FunctionComments = ({ functionId }) => {
|
||||
// State pour poster un commentaire
|
||||
|
@ -6,7 +6,6 @@ import { faStar as farStar } from '@fortawesome/free-regular-svg-icons'
|
||||
import date from 'date-and-time'
|
||||
import { UserContext } from '../../contexts/UserContext'
|
||||
import api, { API_URL } from '../../utils/api'
|
||||
import '../FunctionCard/FunctionCard.css'
|
||||
|
||||
const FunctionComponentTop = props => {
|
||||
const { isAuth, user } = useContext(UserContext)
|
||||
|
@ -6,7 +6,6 @@ import api from '../../utils/api'
|
||||
import fr from 'date-fns/locale/fr'
|
||||
import { registerLocale } from 'react-datepicker'
|
||||
import date from 'date-and-time'
|
||||
import 'react-datepicker/dist/react-datepicker.css'
|
||||
|
||||
registerLocale('fr', fr)
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import SwipeableViews from 'react-swipeable-views'
|
||||
import './FunctionTabs.css'
|
||||
|
||||
const FunctionTabs = props => {
|
||||
return (
|
||||
|
@ -4,7 +4,6 @@ import FunctionCard from '../FunctionCard/FunctionCard'
|
||||
import Loader from '../Loader'
|
||||
import api from '../../utils/api'
|
||||
import useAPI from '../../hooks/useAPI'
|
||||
import './FunctionsList.css'
|
||||
|
||||
let pageFunctions = 1
|
||||
const FunctionsList = props => {
|
||||
|
@ -1,44 +1,49 @@
|
||||
import Head from 'next/head'
|
||||
|
||||
const HeadTag = ({ title, image, description }) => (
|
||||
<Head>
|
||||
<title>{title || ''}</title>
|
||||
<link rel='icon' type='image/png' href={image} />
|
||||
const HeadTag = (props) => {
|
||||
const {
|
||||
title = 'FunctionProject',
|
||||
image = '/images/FunctionProject_icon_small.png',
|
||||
description = "Apprenez la programmation grâce à l'apprentissage par projet alias fonction.",
|
||||
url = 'https://function.divlo.fr/'
|
||||
} = props
|
||||
|
||||
{/* Meta Tag */}
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
||||
<meta name='description' content={description} />
|
||||
<link rel='canonical' href='function.divlo.fr' />
|
||||
<meta name='Language' content='fr' />
|
||||
<meta name='theme-color' content='#ffd800' />
|
||||
return (
|
||||
<Head>
|
||||
<title>{title}</title>
|
||||
<link rel='icon' type='image/png' href={image} />
|
||||
|
||||
{/* Open Graph Metadata */}
|
||||
<meta property='og:title' content={title} />
|
||||
<meta property='og:type' content='website' />
|
||||
<meta property='og:url' content='https://function.divlo.fr/' />
|
||||
<meta property='og:image' content={image} />
|
||||
<meta property='og:description' content={description} />
|
||||
<meta property='og:locale' content='fr_FR' />
|
||||
<meta property='og:site_name' content='FunctionProject' />
|
||||
{/* Meta Tag */}
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
||||
<meta name='description' content={description} />
|
||||
<meta name='Language' content='fr' />
|
||||
<meta name='theme-color' content='#ffd800' />
|
||||
|
||||
{/* Twitter card Metadata */}
|
||||
<meta name='twitter:card' content='summary' />
|
||||
<meta name='twitter:description' content={description} />
|
||||
<meta name='twitter:title' content={title} />
|
||||
<meta name='twitter:site' content='@Divlo_FR' />
|
||||
<meta name='twitter:image:src' content={image} />
|
||||
<meta name='twitter:creator' content='@Divlo_FR' />
|
||||
{/* Open Graph Metadata */}
|
||||
<meta property='og:title' content={title} />
|
||||
<meta property='og:type' content='website' />
|
||||
<meta property='og:url' content={url} />
|
||||
<meta property='og:image' content={image} />
|
||||
<meta property='og:description' content={description} />
|
||||
<meta property='og:locale' content='fr_FR' />
|
||||
<meta property='og:site_name' content={title} />
|
||||
|
||||
{/* Preloader script */}
|
||||
<script src='/js/preloader.js' />
|
||||
</Head>
|
||||
)
|
||||
{/* Twitter card Metadata */}
|
||||
<meta name='twitter:card' content='summary' />
|
||||
<meta name='twitter:description' content={description} />
|
||||
<meta name='twitter:title' content={title} />
|
||||
<meta name='twitter:image:src' content={image} />
|
||||
|
||||
HeadTag.defaultProps = {
|
||||
title: 'FunctionProject',
|
||||
description:
|
||||
"Apprenez la programmation grâce à l'apprentissage par projet alias fonction.",
|
||||
image: '/images/FunctionProject_icon_small.png'
|
||||
{/* PWA Data */}
|
||||
<link rel='manifest' href='/manifest.json' />
|
||||
<meta name='apple-mobile-web-app-capable' content='yes' />
|
||||
<meta name='mobile-web-app-capable' content='yes' />
|
||||
<link rel='apple-touch-icon' href={image} />
|
||||
|
||||
{/* Preloader script */}
|
||||
<script src='/js/preloader.js' />
|
||||
</Head>
|
||||
)
|
||||
}
|
||||
|
||||
export default HeadTag
|
||||
|
@ -3,7 +3,6 @@ import { UserContext } from '../../contexts/UserContext'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import NavigationLink from './NavigationLink'
|
||||
import './Header.css'
|
||||
|
||||
export default function Header () {
|
||||
const { isAuth, logoutUser, user } = useContext(UserContext)
|
||||
|
@ -1,6 +1,5 @@
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import './Header.css'
|
||||
|
||||
export default function NavigationLink (props) {
|
||||
const { pathname } = useRouter()
|
||||
|
@ -1,7 +1,6 @@
|
||||
import Link from 'next/link'
|
||||
import { forwardRef, memo } from 'react'
|
||||
import { API_URL } from '../../utils/api'
|
||||
import './UserCard.css'
|
||||
|
||||
const UserCard = memo(
|
||||
forwardRef((props, ref) => {
|
||||
|
@ -1,3 +1,11 @@
|
||||
const withCSS = require('@zeit/next-css')
|
||||
const withFonts = require('next-fonts')
|
||||
module.exports = withFonts(withCSS())
|
||||
const withPWA = require('next-pwa')
|
||||
|
||||
module.exports = withFonts(
|
||||
withPWA({
|
||||
pwa: {
|
||||
disable: process.env.NODE_ENV !== 'production',
|
||||
dest: 'public'
|
||||
}
|
||||
})
|
||||
)
|
||||
|
18582
website/package-lock.json
generated
@ -1,8 +1,16 @@
|
||||
{
|
||||
"name": "website",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"description": "Website frontend for FunctionProject",
|
||||
"main": "server.js",
|
||||
"standard": {
|
||||
"files": [
|
||||
"./**/*.{js,jsx}"
|
||||
],
|
||||
"envs": [
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"dev:custom": "cross-env NODE_ENV=development node server",
|
||||
"start:custom": "cross-env NODE_ENV=production node server",
|
||||
@ -10,40 +18,40 @@
|
||||
"start": "next start",
|
||||
"build": "next build",
|
||||
"export": "next export",
|
||||
"format": "standard \"./**/*.{js,jsx}\" --fix | snazzy"
|
||||
"lint": "standard | snazzy"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.32",
|
||||
"@fortawesome/free-brands-svg-icons": "^5.15.1",
|
||||
"@fortawesome/free-regular-svg-icons": "^5.15.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.1",
|
||||
"@fortawesome/react-fontawesome": "^0.1.12",
|
||||
"@zeit/next-css": "^1.0.1",
|
||||
"axios": "^0.21.0",
|
||||
"date-and-time": "^0.14.1",
|
||||
"date-fns": "^2.16.1",
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.35",
|
||||
"@fortawesome/free-brands-svg-icons": "^5.15.3",
|
||||
"@fortawesome/free-regular-svg-icons": "^5.15.3",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.15.3",
|
||||
"@fortawesome/react-fontawesome": "^0.1.14",
|
||||
"axios": "^0.21.1",
|
||||
"date-and-time": "^1.0.0",
|
||||
"date-fns": "^2.21.1",
|
||||
"express": "^4.17.1",
|
||||
"express-http-to-https": "^1.1.4",
|
||||
"html-react-parser": "^0.14.0",
|
||||
"next": "^10.0.0",
|
||||
"next-fonts": "^1.4.0",
|
||||
"html-react-parser": "^1.2.5",
|
||||
"next": "^10.1.3",
|
||||
"next-fonts": "^1.5.1",
|
||||
"next-pwa": "^5.2.9",
|
||||
"notyf": "^3.9.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"react": "17.0.1",
|
||||
"react-codepen-embed": "^1.0.1",
|
||||
"react": "16.13.1",
|
||||
"react-codepen-embed": "^1.0.2",
|
||||
"react-color": "^2.19.3",
|
||||
"react-datepicker": "^3.3.0",
|
||||
"react-dom": "17.0.1",
|
||||
"react-markdown": "^5.0.2",
|
||||
"react-dom": "16.13.1",
|
||||
"react-markdown": "^5.0.3",
|
||||
"react-swipeable-views": "^0.13.9",
|
||||
"react-swipeable-views-utils": "^0.13.9",
|
||||
"react-syntax-highlighter": "^15.3.0",
|
||||
"react-syntax-highlighter": "^15.4.3",
|
||||
"suneditor-react": "^2.8.0",
|
||||
"universal-cookie": "^4.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^7.0.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"snazzy": "^9.0.0",
|
||||
"standard": "^16.0.0"
|
||||
"standard": "^16.0.3"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
import Link from 'next/link'
|
||||
import HeadTag from '../components/HeadTag'
|
||||
import '../public/css/pages/404.css'
|
||||
|
||||
const Error404 = () => (
|
||||
<>
|
||||
|
@ -4,17 +4,36 @@ import NProgress from 'nprogress'
|
||||
|
||||
/* Components Imports */
|
||||
import Header from '../components/Header/Header'
|
||||
import Footer from '../components/Footer/Footer'
|
||||
import Footer from '../components/Footer'
|
||||
|
||||
/* Contexts Imports */
|
||||
import UserContextProvider from '../contexts/UserContext'
|
||||
|
||||
/* CSS Imports */
|
||||
import 'notyf/notyf.min.css'
|
||||
import 'react-datepicker/dist/react-datepicker.css'
|
||||
import '../public/fonts/Montserrat/Montserrat.css'
|
||||
import '../public/css/normalize.css'
|
||||
import '../public/css/grid.css'
|
||||
import '../public/css/general.css'
|
||||
import '../public/css/nprogress.css'
|
||||
import '../styles/suneditor.min.css'
|
||||
import '../styles/normalize.css'
|
||||
import '../styles/grid.css'
|
||||
import '../styles/general.css'
|
||||
import '../styles/nprogress.css'
|
||||
import '../styles/pages/admin.css'
|
||||
import '../styles/pages/404.css'
|
||||
import '../styles/pages/index.css'
|
||||
import '../styles/pages/profile.css'
|
||||
import '../styles/pages/register-login.css'
|
||||
import '../styles/pages/users.css'
|
||||
import '../styles/pages/FunctionComponent.css'
|
||||
import '../styles/pages/functions/chronometerTimer.css'
|
||||
import '../styles/pages/functions/rightPrice.css'
|
||||
import '../styles/pages/functions/toDoList.css'
|
||||
import '../styles/components/Header.css'
|
||||
import '../styles/components/FunctionTabs.css'
|
||||
import '../styles/components/CommentCard.css'
|
||||
import '../styles/components/FunctionComments.css'
|
||||
import '../styles/components/FunctionsList.css'
|
||||
import '../styles/components/UserCard.css'
|
||||
|
||||
Router.events.on('routeChangeStart', () => NProgress.start())
|
||||
Router.events.on('routeChangeComplete', () => NProgress.done())
|
||||
|
@ -7,8 +7,6 @@ import EditArticleFunction from '../../components/FunctionAdmin/EditArticleFunct
|
||||
import EditFormFunction from '../../components/FunctionAdmin/EditFormFunction'
|
||||
import redirect from '../../utils/redirect'
|
||||
import api, { API_URL } from '../../utils/api'
|
||||
import '../../components/FunctionPage/FunctionTabs.css'
|
||||
import '../../public/css/pages/admin.css'
|
||||
|
||||
const AdminFunctionComponent = props => {
|
||||
const [slideIndex, setSlideIndex] = useState(0)
|
||||
|
@ -8,7 +8,6 @@ import Modal from '../../components/Modal'
|
||||
import FunctionsList from '../../components/FunctionsList/FunctionsList'
|
||||
import AddEditFunction from '../../components/FunctionAdmin/AddEditFunction'
|
||||
import redirect from '../../utils/redirect'
|
||||
import '../../public/css/pages/admin.css'
|
||||
|
||||
const Admin = props => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
|
@ -11,7 +11,6 @@ import htmlParser from 'html-react-parser'
|
||||
import Loader from '../../components/Loader'
|
||||
import useAPI from '../../hooks/useAPI'
|
||||
import api from '../../utils/api'
|
||||
import '../../public/css/pages/admin.css'
|
||||
|
||||
const defaultCategoryState = { name: '', color: '#ffffff' }
|
||||
|
||||
|
@ -6,7 +6,6 @@ import { faCheck, faTrash } from '@fortawesome/free-solid-svg-icons'
|
||||
import redirect from '../../utils/redirect'
|
||||
import HeadTag from '../../components/HeadTag'
|
||||
import api from '../../utils/api'
|
||||
import '../../public/css/pages/admin.css'
|
||||
|
||||
const manageQuotes = props => {
|
||||
const [quotesData, setQuotesData] = useState({
|
||||
|
@ -5,7 +5,6 @@ import FunctionComments from '../../components/FunctionPage/FunctionComments/Fun
|
||||
import FunctionPage from '../../components/FunctionPage/FunctionPage'
|
||||
import redirect from '../../utils/redirect'
|
||||
import api from '../../utils/api'
|
||||
import '../../public/css/pages/FunctionComponent.css'
|
||||
|
||||
const FunctionTabManager = props => {
|
||||
if (props.type === 'form') {
|
||||
|
@ -9,8 +9,6 @@ import Loader from '../../components/Loader'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faPlay, faPause, faSync } from '@fortawesome/free-solid-svg-icons'
|
||||
import api from '../../utils/api'
|
||||
import '../../public/css/pages/FunctionComponent.css'
|
||||
import '../../public/css/pages/functions/chronometerTimer.css'
|
||||
|
||||
let interval
|
||||
function convertSeconds (seconds) {
|
||||
|
@ -12,9 +12,6 @@ import FunctionArticle from '../../components/FunctionPage/FunctionArticle'
|
||||
import FunctionComments from '../../components/FunctionPage/FunctionComments/FunctionComments'
|
||||
import Modal from '../../components/Modal'
|
||||
import api from '../../utils/api'
|
||||
import 'notyf/notyf.min.css'
|
||||
import '../../public/css/pages/FunctionComponent.css'
|
||||
import '../../public/css/pages/admin.css'
|
||||
|
||||
const CreateLink = ({ linksData, setLinksData }) => {
|
||||
const { isAuth, user } = useContext(UserContext)
|
||||
|
@ -12,8 +12,6 @@ import FunctionArticle from '../../components/FunctionPage/FunctionArticle'
|
||||
import FunctionComments from '../../components/FunctionPage/FunctionComments/FunctionComments'
|
||||
import api from '../../utils/api'
|
||||
import copyToClipboard from '../../utils/copyToClipboard'
|
||||
import 'notyf/notyf.min.css'
|
||||
import '../../public/css/pages/FunctionComponent.css'
|
||||
|
||||
const GenerateQuote = () => {
|
||||
const [quote, setQuote] = useState({ quote: '', author: '' })
|
||||
|
@ -6,8 +6,6 @@ import FunctionArticle from '../../components/FunctionPage/FunctionArticle'
|
||||
import FunctionComments from '../../components/FunctionPage/FunctionComments/FunctionComments'
|
||||
import Loader from '../../components/Loader'
|
||||
import api from '../../utils/api'
|
||||
import '../../public/css/pages/FunctionComponent.css'
|
||||
import '../../public/css/pages/functions/rightPrice.css'
|
||||
|
||||
const PlayRightPrice = () => {
|
||||
const [isPlaying, setIsPlaying] = useState(false)
|
||||
|
@ -9,8 +9,6 @@ import FunctionTabs from '../../components/FunctionPage/FunctionTabs'
|
||||
import FunctionArticle from '../../components/FunctionPage/FunctionArticle'
|
||||
import FunctionComments from '../../components/FunctionPage/FunctionComments/FunctionComments'
|
||||
import api from '../../utils/api'
|
||||
import '../../public/css/pages/FunctionComponent.css'
|
||||
import '../../public/css/pages/functions/toDoList.css'
|
||||
|
||||
const ManageToDo = () => {
|
||||
const { isAuth, user } = useContext(UserContext)
|
||||
|
@ -4,7 +4,6 @@ import { autoPlay } from 'react-swipeable-views-utils'
|
||||
import Link from 'next/link'
|
||||
import HeadTag from '../components/HeadTag'
|
||||
import Loader from '../components/Loader'
|
||||
import '../public/css/pages/index.css'
|
||||
|
||||
const AutoPlaySwipeableViews = autoPlay(SwipeableViews)
|
||||
|
||||
|
@ -13,7 +13,6 @@ import Loader from '../../components/Loader'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import CodeBlock from '../../components/CodeBlock'
|
||||
import api, { API_URL } from '../../utils/api'
|
||||
import '../../public/css/pages/profile.css'
|
||||
|
||||
const Profile = props => {
|
||||
const { isAuth, user, logoutUser } = useContext(UserContext)
|
||||
|
@ -4,7 +4,6 @@ import Loader from '../../components/Loader'
|
||||
import HeadTag from '../../components/HeadTag'
|
||||
import api from '../../utils/api'
|
||||
import withoutAuth from '../../hoc/withoutAuth'
|
||||
import '../../public/css/pages/register-login.css'
|
||||
|
||||
const forgotPassword = () => {
|
||||
const [inputState, setInputState] = useState({})
|
||||
|
@ -3,7 +3,6 @@ import HeadTag from '../../components/HeadTag'
|
||||
import Loader from '../../components/Loader'
|
||||
import UserCard from '../../components/UserCard/UserCard'
|
||||
import api from '../../utils/api'
|
||||
import '../../public/css/pages/users.css'
|
||||
|
||||
const Users = () => {
|
||||
let pageUsers = 1
|
||||
|
@ -6,7 +6,6 @@ import Loader from '../../components/Loader'
|
||||
import HeadTag from '../../components/HeadTag'
|
||||
import { UserContext } from '../../contexts/UserContext'
|
||||
import withoutAuth from '../../hoc/withoutAuth'
|
||||
import '../../public/css/pages/register-login.css'
|
||||
|
||||
const Login = () => {
|
||||
const router = useRouter()
|
||||
|
@ -5,7 +5,6 @@ import HeadTag from '../../components/HeadTag'
|
||||
import api from '../../utils/api'
|
||||
import redirect from '../../utils/redirect'
|
||||
import withoutAuth from '../../hoc/withoutAuth'
|
||||
import '../../public/css/pages/register-login.css'
|
||||
|
||||
const newPassword = (props) => {
|
||||
const [inputState, setInputState] = useState({})
|
||||
|
@ -4,7 +4,6 @@ import Loader from '../../components/Loader'
|
||||
import HeadTag from '../../components/HeadTag'
|
||||
import api from '../../utils/api'
|
||||
import withoutAuth from '../../hoc/withoutAuth'
|
||||
import '../../public/css/pages/register-login.css'
|
||||
|
||||
const Register = () => {
|
||||
const [inputState, setInputState] = useState({ name: '', email: '', password: '' })
|
||||
|
BIN
website/public/images/icons/icon-128x128.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
website/public/images/icons/icon-144x144.png
Normal file
After Width: | Height: | Size: 9.6 KiB |
BIN
website/public/images/icons/icon-152x152.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
website/public/images/icons/icon-192x192.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
website/public/images/icons/icon-384x384.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
website/public/images/icons/icon-512x512.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
website/public/images/icons/icon-72x72.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
website/public/images/icons/icon-96x96.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
51
website/public/manifest.json
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "FunctionProject",
|
||||
"short_name": "FunctionProject",
|
||||
"icons": [
|
||||
{
|
||||
"src": "images/icons/icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icons/icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icons/icon-128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icons/icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icons/icon-152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icons/icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "images/icons/icon-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "images/icons/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffd800",
|
||||
"background_color": "#181818",
|
||||
"start_url": "/",
|
||||
"display": "standalone"
|
||||
}
|