diff --git a/api/assets/functions/main/armstrongNumber.js b/api/assets/functions/main/armstrongNumber.js index 4a37d00..edf0f95 100644 --- a/api/assets/functions/main/armstrongNumber.js +++ b/api/assets/functions/main/armstrongNumber.js @@ -23,7 +23,7 @@ function armstrongNumber(number) { const isArmstrongNumber = (result === number); return { isArmstrongNumber, - htmlExplanation: `${formattedNumber} ${isArmstrongNumber ? "" : "n'"}est pas un nombre d'Armstrong, car ${resultString.slice(2)} = ${formatNumberResult(result)}.` + resultHTML: `

${formattedNumber} ${isArmstrongNumber ? "" : "n'"}est pas un nombre d'Armstrong, car ${resultString.slice(2)} = ${formatNumberResult(result)}.

` } } @@ -35,7 +35,7 @@ exports.armstrongNumberOutput = ({ res, next }, argsObject) => { if (!(number)) { return errorHandling(next, requiredFields); } - + // Si ce n'est pas un nombre number = parseInt(number); if (isNaN(number) || number <= 0) { diff --git a/api/assets/functions/main/calculateAge.js b/api/assets/functions/main/calculateAge.js index 2cb7293..5ce806a 100644 --- a/api/assets/functions/main/calculateAge.js +++ b/api/assets/functions/main/calculateAge.js @@ -6,7 +6,7 @@ function calculateAge(currentDate, { birthDateDay, birthDateMonth, birthDateYear const day = currentDate.getDate(); const month = currentDate.getMonth(); const currentDateMoment = moment([currentDate.getFullYear(), month, day]); - const birthDateMoment = moment([birthDateYear, birthDateMonth - 1, birthDateDay]); + const birthDateMoment = moment([birthDateYear, birthDateMonth, birthDateDay]); // Calcule l'âge - Moment.js const ageYears = currentDateMoment.diff(birthDateMoment, 'year'); @@ -15,28 +15,36 @@ function calculateAge(currentDate, { birthDateDay, birthDateMonth, birthDateYear birthDateMoment.add(ageMonths, 'months'); const ageDays = currentDateMoment.diff(birthDateMoment, 'days'); - const isBirthday = (birthDateDay === day && birthDateMonth === (month + 1)); + const isBirthday = (birthDateDay === day && birthDateMonth === month); return { ageYears, ageMonths, ageDays, isBirthday }; } /* OUTPUTS */ exports.calculateAgeOutput = ({ res, next }, argsObject) => { - let { birthDateDay, birthDateMonth, birthDateYear } = argsObject; - birthDateDay = parseInt(birthDateDay); - birthDateMonth = parseInt(birthDateMonth); - birthDateYear = parseInt(birthDateYear); + let { birthDate } = argsObject; // S'il n'y a pas les champs obligatoire - if (!(birthDateDay && birthDateMonth && birthDateYear)) { + if (!(birthDate)) { return errorHandling(next, requiredFields); } + + const birthDateDay = parseInt(birthDate.substring(0, 2)); + const birthDateMonth = parseInt((birthDate.substring(3, 5)) - 1); + const birthDateYear = parseInt(birthDate.substring(6, 10)); // Si ce n'est pas une date valide - const currentDate = new Date(); - const birthDate = new Date(birthDateYear, birthDateMonth - 1, birthDateDay); - if (!(currentDate > birthDate)) { + const currentDate = new Date(); + const birthDateObject = new Date(birthDateYear, birthDateMonth, birthDateDay); + const result = calculateAge(currentDate, { birthDateYear, birthDateMonth, birthDateDay }); + if ((currentDate < birthDateObject) || isNaN(result.ageYears)) { return errorHandling(next, { message: "Veuillez rentré une date valide...", statusCode: 400 }); } - - return res.status(200).json(calculateAge(currentDate, { birthDateYear, birthDateMonth, birthDateDay })); + + let resultHTML; + if (result.isBirthday) { + resultHTML = `

Vous avez ${result.ageYears} ans. Joyeux Anniversaire! 🥳

`; + } else { + resultHTML = `

Vous avez ${result.ageYears} ans, ${result.ageMonths} mois et ${result.ageDays} jour(s).

`; + } + return res.status(200).json({ ...result, resultHTML }); } \ No newline at end of file diff --git a/api/assets/functions/main/convertCurrency.js b/api/assets/functions/main/convertCurrency.js index 110b766..7ae55ec 100644 --- a/api/assets/functions/main/convertCurrency.js +++ b/api/assets/functions/main/convertCurrency.js @@ -1,6 +1,7 @@ const axios = require('axios'); const errorHandling = require('../../utils/errorHandling'); const { requiredFields } = require('../../config/errors'); +const formatNumberResult = require('../secondary/formatNumberResult'); /* OUTPUTS */ exports.convertCurrencyOutput = ({ res, next }, argsObject) => { @@ -10,7 +11,7 @@ exports.convertCurrencyOutput = ({ res, next }, argsObject) => { if (!(number && baseCurrency && finalCurrency)) { return errorHandling(next, requiredFields); } - + // Si ce n'est pas un nombre number = parseFloat(number); if (isNaN(number)) { @@ -23,12 +24,14 @@ exports.convertCurrencyOutput = ({ res, next }, argsObject) => { if (!rate) { return errorHandling(next, { message: "La devise n'existe pas.", statusCode: 404 }); } - const result = rate * number; + const result = rate * number; const dateObject = new Date(response.data.date); - const year = dateObject.getFullYear(); - const day = ('0'+(dateObject.getDate())).slice(-2); - const month = ('0'+(dateObject.getMonth()+1)).slice(-2); - return res.status(200).json({ date: `${day}/${month}/${year}`, result }); + const year = dateObject.getFullYear(); + const day = ('0'+(dateObject.getDate())).slice(-2); + const month = ('0'+(dateObject.getMonth()+1)).slice(-2); + const date = `${day}/${month}/${year}`; + const resultHTML = `

${formatNumberResult(number)} ${response.data.base} = ${formatNumberResult(result).toFixed(2)} ${finalCurrency}

Dernier rafraîchissement du taux d'échange : ${data}

`; + return res.status(200).json({ date, result, resultHTML }); }) .catch(() => errorHandling(next, { message: "La devise n'existe pas.", statusCode: 404 })); } \ No newline at end of file diff --git a/api/assets/functions/main/convertDistance.js b/api/assets/functions/main/convertDistance.js index 3ce5d73..60adeda 100644 --- a/api/assets/functions/main/convertDistance.js +++ b/api/assets/functions/main/convertDistance.js @@ -1,5 +1,6 @@ const errorHandling = require('../../utils/errorHandling'); const { requiredFields, generalError } = require('../../config/errors'); +const formatNumberResult = require('../secondary/formatNumberResult'); const correspondancesDistance = ["pm", null, null, "nm", null, null, "µm", null, null, "mm", "cm", "dm", "m", "dam", "hm", "km", null, null, "Mm", null, null, "Gm", null, null, "Tm"]; @@ -19,8 +20,8 @@ function convertDistance(firstValue, unitFirstValue, unitFinalValue) { const difference = index1 - index2; const result = firstValue * Math.pow(10, difference); return { - resultNumber: result, - resultString: `${result} ${unitFinalValue}` + result, + resultHTML: `

Conversion de longueur : ${formatNumberResult(firstValue)} ${unitFirstValue} = ${formatNumberResult(result)} ${unitFinalValue}

` }; } return false; @@ -34,7 +35,7 @@ exports.convertDistanceOutput = ({ res, next }, argsObject) => { if (!(number && numberUnit && finalUnit)) { return errorHandling(next, requiredFields); } - + // Si ce n'est pas un nombre number = parseInt(number); if (isNaN(number)) { diff --git a/api/assets/functions/main/convertEncoding.js b/api/assets/functions/main/convertEncoding.js index b60236d..72c4927 100644 --- a/api/assets/functions/main/convertEncoding.js +++ b/api/assets/functions/main/convertEncoding.js @@ -239,5 +239,5 @@ exports.convertEncodingOutput = ({ res, next }, argsObject) => { return errorHandling(next, generalError); } - return res.status(200).json({ result }); + return res.status(200).json({ result, resultHTML: `

${result}

` }); } \ No newline at end of file diff --git a/api/assets/functions/main/convertRomanArabicNumbers.js b/api/assets/functions/main/convertRomanArabicNumbers.js index afd52ac..9b5842c 100644 --- a/api/assets/functions/main/convertRomanArabicNumbers.js +++ b/api/assets/functions/main/convertRomanArabicNumbers.js @@ -76,12 +76,7 @@ exports.convertRomanToArabicOutput = ({ res, next }, argsObject) => { } // Formate le paramètre - try { - romanNumber = romanNumber.toUpperCase(); - } - catch { - return errorHandling(next, generalError); - } + romanNumber = romanNumber.toUpperCase(); const result = convertRomanToArabic(romanNumber); if (result === 0) { diff --git a/api/assets/functions/main/convertTemperature.js b/api/assets/functions/main/convertTemperature.js index dfadd24..d40eb83 100644 --- a/api/assets/functions/main/convertTemperature.js +++ b/api/assets/functions/main/convertTemperature.js @@ -1,36 +1,34 @@ const errorHandling = require('../../utils/errorHandling'); const { requiredFields, generalError } = require('../../config/errors'); +const formatNumberResult = require('../secondary/formatNumberResult'); /** * @description Convertis des °C en °F et l'inverse aussi. * @param {Number} degree - Nombre de degrès - * @param {String} unit - Unité du nombre (°C ou °F) + * @param {String} unit - Unité du nombre (°C ou °F) après conversion * @returns {Object} false si arguments non valides et sinon un objet contenant la string et le nombre résultat - * @examples convertTemperature(23, '°C') → { resultNumber: 73.4, resultString: "73.4 °F" } + * @examples convertTemperature(23, '°C') → { result: 73.4, resultHTML: "73.4 °F" } */ function convertTemperature(degree, unit) { let temperatureValue = 0; - let temperatureUnit; if (unit === "°C") { - temperatureUnit = "°F"; - temperatureValue = ((degree * 9/5) + 32); + temperatureValue = (degree - 32) * 5/9; } else if (unit === "°F") { - temperatureUnit = "°C"; - temperatureValue = (degree - 32) * 5/9; + temperatureValue = ((degree * 9/5) + 32); } else { return false; } return { - resultNumber: temperatureValue, - resultString: `${temperatureValue} ${temperatureUnit}` + result: temperatureValue, + resultHTML: `

${formatNumberResult(temperatureValue)} ${unit}

` }; } /* OUTPUTS */ exports.convertTemperatureOutput = ({ res, next }, argsObject) => { - let { degree, unit } = argsObject; + let { degree, unitToConvert } = argsObject; // S'il n'y a pas les champs obligatoire if (!(degree && unit)) { @@ -43,7 +41,7 @@ exports.convertTemperatureOutput = ({ res, next }, argsObject) => { return errorHandling(next, { message: "Veuillez rentré un nombre valide.", statusCode: 400 }); } - const result = convertTemperature(degree, unit); + const result = convertTemperature(degree, unitToConvert); if (!result) { return errorHandling(next, generalError); } diff --git a/api/assets/functions/main/heapAlgorithm.js b/api/assets/functions/main/heapAlgorithm.js index dc505a4..90d08b1 100644 --- a/api/assets/functions/main/heapAlgorithm.js +++ b/api/assets/functions/main/heapAlgorithm.js @@ -1,5 +1,6 @@ const errorHandling = require('../../utils/errorHandling'); const { requiredFields } = require('../../config/errors'); +const formatNumberResult = require('../secondary/formatNumberResult'); /** * @description Retourne un tableau contenant toutes les possibilités d'anagramme d'un mot. @@ -36,11 +37,16 @@ exports.heapAlgorithmOutput = ({ res, next }, argsObject) => { } // Si la chaîne de caractère dépasse LIMIT_CHARACTERS caractères - const LIMIT_CHARACTERS = 8; + const LIMIT_CHARACTERS = 7; if (string.length > LIMIT_CHARACTERS) { return errorHandling(next, { message: `Par souci de performance, vous ne pouvez pas exécuter cette fonction avec un mot dépassant ${LIMIT_CHARACTERS} caractères.`, statusCode: 400 }); } const result = heapAlgorithm(string); - return res.status(200).json(result); + let resultHTML = `

Il y a ${formatNumberResult(result.length)} possibilités d'anagramme pour le mot "${string}" qui contient ${string.length} caractères, la liste :

`; + result.forEach((string) => { + resultHTML += string + "
"; + }); + resultHTML += "

"; + return res.status(200).json({ result, resultHTML }); } \ No newline at end of file diff --git a/api/assets/functions/main/randomNumber.js b/api/assets/functions/main/randomNumber.js index 9d7563a..78571a0 100644 --- a/api/assets/functions/main/randomNumber.js +++ b/api/assets/functions/main/randomNumber.js @@ -1,5 +1,6 @@ const errorHandling = require('../../utils/errorHandling'); const { requiredFields } = require('../../config/errors'); +const formatNumberResult = require('../secondary/formatNumberResult'); /** * @description Génère un nombre aléatoire entre un minimum inclus et un maximum inclus. @@ -28,5 +29,6 @@ exports.randomNumberOutput = ({ res, next }, argsObject) => { return errorHandling(next, { message: "Les paramètres min et max doivent être des nombres...", statusCode: 400 }); } - return res.status(200).json({ result: randomNumber(min, max) }); + const result = randomNumber(min, max); + return res.status(200).json({ result, resultHTML: `

${formatNumberResult(result)}

` }); } \ No newline at end of file diff --git a/api/assets/functions/main/weatherRequest.js b/api/assets/functions/main/weatherRequest.js index ff8c543..7ef48a1 100644 --- a/api/assets/functions/main/weatherRequest.js +++ b/api/assets/functions/main/weatherRequest.js @@ -3,6 +3,8 @@ const Queue = require('smart-request-balancer'); const errorHandling = require('../../utils/errorHandling'); const { requiredFields } = require('../../config/errors'); const { WEATHER_API_KEY } = require('../../config/config'); +const { dateTimeUTC } = require('../secondary/dateTimeManagement'); +const capitalize = require('../secondary/capitalize'); const queue = new Queue({ /* @@ -20,7 +22,7 @@ const queue = new Queue({ }); /* OUTPUTS */ -exports.weatherRequestOutput = async ({ res, next }, argsObject) => { +exports.weatherRequestOutput = ({ res, next }, argsObject) => { let { cityName } = argsObject; // S'il n'y a pas les champs obligatoire @@ -28,10 +30,17 @@ exports.weatherRequestOutput = async ({ res, next }, argsObject) => { return errorHandling(next, requiredFields); } + cityName = cityName.split(' ').join('+'); + // Récupère les données météo grâce à l'API : openweathermap.org. (→ avec limite de 50 requêtes par minute) queue.request(() => { axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${cityName}&lang=fr&units=metric&appid=${WEATHER_API_KEY}`) - .then((response) => res.status(200).json(response.data)) + .then((response) =>{ + const json = response.data; + const showDateTimeValue = dateTimeUTC((json.timezone / 60 / 60).toString()).showDateTimeValue; + const resultHTML = `

🌎 Position : ${json.name}, ${json.sys.country}
⏰ Date et heure : ${showDateTimeValue}
☁️ Météo : ${capitalize(json.weather[0].description)}
🌡️ Température : ${json.main.temp} °C
💧 Humidité : ${json.main.humidity}%

`; + return res.status(200).json({ result: json, resultHTML }); + }) .catch(() => errorHandling(next, { message: "La ville n'existe pas (dans l'API de openweathermap.org).", statusCode: 404 })); }, 'everyone', 'weatherRequest'); } \ No newline at end of file diff --git a/api/assets/functions/secondary/capitalize.js b/api/assets/functions/secondary/capitalize.js new file mode 100644 index 0000000..858e2d4 --- /dev/null +++ b/api/assets/functions/secondary/capitalize.js @@ -0,0 +1,12 @@ +/** + * @description Majuscule à la 1ère lettre d'une string. + * @param {String} s + * @returns {String} + * @examples capitalize('hello world!') → 'Hello world!' + */ +function capitalize(s) { + if (typeof s !== 'string') return '' + return s.charAt(0).toUpperCase() + s.slice(1) +} + +module.exports = capitalize; \ No newline at end of file diff --git a/api/assets/functions/secondary/dateTimeManagement.js b/api/assets/functions/secondary/dateTimeManagement.js new file mode 100644 index 0000000..f05a707 --- /dev/null +++ b/api/assets/functions/secondary/dateTimeManagement.js @@ -0,0 +1,45 @@ +const timeNow = new Date(); +const utcOffset = timeNow.getTimezoneOffset(); +timeNow.setMinutes(timeNow.getMinutes() + utcOffset); + +/** + * @description Donne la date et l'heure selon l'UTC (Universal Time Coordinated). + * @param {String} utc Heure de décalage par rapport à l'UTC + * @returns {Function} → showDateTime(enteredOffset) → Retourne l'exécution de la fonction showDateTime + * @examples dateTimeUTC('0') + */ +function dateTimeUTC(utc) { + const enteredOffset = parseFloat(utc)*60; + timeNow.setMinutes(timeNow.getMinutes() + enteredOffset); + return showDateTime(enteredOffset); +} + +/** + * @description Affiche la date et l'heure (format : dd/mm/yyyy - 00:00:00). + * @requires {@link fonctions_annexes.js: showDateTime} + * @param {String} utc Heure de décalage par rapport à l'UTC + * @returns {Object} Retourne un objet contenant l'année, le mois, le jour, l'heure, les minutes, les secondes et la date formaté + * @examples dateTimeUTC('0') → dateTimeUTC vous renvoie l'exécution de showDateTime + */ +function showDateTime(enteredOffset) { + const year = timeNow.getFullYear(); + const month = ('0'+(timeNow.getMonth()+1)).slice(-2); + const day = ('0'+timeNow.getDate()).slice(-2); + const hour = ('0'+timeNow.getHours()).slice(-2); + const minute = ('0'+timeNow.getMinutes()).slice(-2); + const second = ('0'+timeNow.getSeconds()).slice(-2); + const showDateTimeValue = day + "/" + month + "/" + year + " - " + hour + ":" + minute + ":" + second; + const objectDateTime = { + year: year, + month: month, + day: day, + hour: hour, + minute: minute, + second: second, + showDateTimeValue: showDateTimeValue + }; + timeNow.setMinutes(timeNow.getMinutes() - enteredOffset); + return objectDateTime; +} + +module.exports = { showDateTime, dateTimeUTC }; \ No newline at end of file diff --git a/api/controllers/functions.js b/api/controllers/functions.js index 9b6f234..7299019 100644 --- a/api/controllers/functions.js +++ b/api/controllers/functions.js @@ -11,12 +11,11 @@ function helperQueryNumber(value, defaultValue) { } exports.getFunctions = (req, res, next) => { - const page = helperQueryNumber(req.query.page, 1); - const limit = helperQueryNumber(req.query.limit, 10); + const page = helperQueryNumber(req.query.page, 1); + const limit = helperQueryNumber(req.query.limit, 10); const categoryId = helperQueryNumber(req.query.categoryId, 0); - let search = req.query.search; - try { search = search.toLowerCase(); } catch {} - const offset = (page - 1) * limit; + const search = req.query.search.toLowerCase(); + const offset = (page - 1) * limit; Functions.findAndCountAll({ limit, offset, diff --git a/website/components/FunctionForm/FunctionForm.css b/website/components/FunctionForm/FunctionForm.css new file mode 100644 index 0000000..b2c64f6 --- /dev/null +++ b/website/components/FunctionForm/FunctionForm.css @@ -0,0 +1,41 @@ +.FunctionForm__control { + display: block; + width: 100%; + height: calc(1.5em + .75rem + 2px); + padding: .375rem .75rem; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + border-radius: .25rem; +} +.FunctionForm__label { + display: inline-block; + margin-bottom: .5em; + font-size: 16px; +} +.FunctionForm__submit, .FunctionForm__result { + margin-top: 25px; +} +.btn { + cursor: pointer; + border: 1px solid transparent; + padding: .375rem .75rem; + font-size: 1rem; + line-height: 1.5; + border-radius: .25rem; + transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; +} +.btn-dark:hover { + color: #fff; + background-color: #23272b; + border-color: #1d2124; +} +.btn-dark { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} \ No newline at end of file diff --git a/website/components/FunctionForm/FunctionForm.js b/website/components/FunctionForm/FunctionForm.js new file mode 100644 index 0000000..5041227 --- /dev/null +++ b/website/components/FunctionForm/FunctionForm.js @@ -0,0 +1,80 @@ +import { useState } from 'react'; +import Loader from '../Loader'; +import './FunctionForm.css'; +import htmlParser from 'html-react-parser'; +import api from '../../utils/api'; + +const FunctionForm = (props) => { + // console.log(props); + + const [inputState, setInputState] = useState({}); + const [message, setMessage] = useState(""); + const [isLoading, setIsLoading] = useState(false); + + const handleSubmit = (event) => { + event.preventDefault(); + api.post(`/functions/${props.slug}`, inputState) + .then((response) => { + setMessage(response.data.resultHTML); + }) + .catch((error) => { + setMessage(error.response.data.message); + }); + setIsLoading(false); + } + + const handleChange = (event) => { + const inputStateNew = { ...inputState }; + inputStateNew[event.target.name] = event.target.value; + if (event.target.value !== "") { + setIsLoading(true); + } else { + setIsLoading(false); + } + setInputState(inputStateNew); + } + + if (props.inputArray.length <= 0) { + return ( +
+

La fonction n'est pas encore disponible.

+
+ ); + } + return ( +
+
+ {props.inputArray.map((input, index) => { + let inputResult; + switch(input.type) { + case "text" || "number": + inputResult = (); + break; + default: + inputResult = (

Erreur, l'input n'est pas valide...

); + } + return ( +
+ + {inputResult} +
+ ); + })} + +
+ +
+
+
+ { + (isLoading) ? + + : + htmlParser(message) + } +
+
+ ); +} + +export default FunctionForm; \ No newline at end of file diff --git a/website/package-lock.json b/website/package-lock.json index 3f20b3e..a659d31 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -1267,6 +1267,11 @@ "resolved": "https://registry.npmjs.org/@next/polyfill-nomodule/-/polyfill-nomodule-9.3.1.tgz", "integrity": "sha512-4mP4m7cuobjLcjltQzPrv9/b/C/AQR3Q1PwQw/0VLkZTsC8HxCt/gbafXdyDmalDPsp6EEZ6IaHUpuFBz+QBmw==" }, + "@types/domhandler": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/domhandler/-/domhandler-2.4.1.tgz", + "integrity": "sha512-cfBw6q6tT5sa1gSPFSRKzF/xxYrrmeiut7E0TxNBObiLSBTuFEHibcfEe3waQPEDbqBsq+ql/TOniw65EyDFMA==" + }, "@webassemblyjs/ast": { "version": "1.8.5", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz", @@ -3757,11 +3762,84 @@ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" }, + "html-dom-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-0.2.3.tgz", + "integrity": "sha512-GdzE63/U0IQEvcpAz0cUdYx2zQx0Ai+HWvE9TXEgwP27+SymUzKa7iB4DhjYpf2IdNLfTTOBuMS5nxeWOosSMQ==", + "requires": { + "@types/domhandler": "2.4.1", + "domhandler": "2.4.2", + "htmlparser2": "3.10.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "html-entities": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=" }, + "html-react-parser": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-0.10.2.tgz", + "integrity": "sha512-CXAtbO0bMB8/TuMXgClap6C7SIcZvA5AP0inTJ93JZTryNiHUkCo5shsNBfegW9aqfdh1iWNGSy/dCku5vwdcw==", + "requires": { + "@types/domhandler": "2.4.1", + "html-dom-parser": "0.2.3", + "react-property": "1.0.1", + "style-to-object": "0.3.0" + } + }, "htmlparser2": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.0.0.tgz", @@ -3897,6 +3975,11 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" + }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -5968,6 +6051,11 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==" }, + "react-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-property/-/react-property-1.0.1.tgz", + "integrity": "sha512-1tKOwxFn3dXVomH6pM9IkLkq2Y8oh+fh/lYW3MJ/B03URswUTqttgckOlbxY2XHF3vPG6uanSc4dVsLW/wk3wQ==" + }, "react-swipeable-views": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/react-swipeable-views/-/react-swipeable-views-0.13.9.tgz", @@ -6818,6 +6906,14 @@ "schema-utils": "^2.0.1" } }, + "style-to-object": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", + "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==", + "requires": { + "inline-style-parser": "0.1.1" + } + }, "styled-jsx": { "version": "3.2.5", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-3.2.5.tgz", diff --git a/website/package.json b/website/package.json index ef98aba..cd55d8f 100644 --- a/website/package.json +++ b/website/package.json @@ -10,6 +10,7 @@ "dependencies": { "@zeit/next-css": "^1.0.1", "axios": "^0.19.2", + "html-react-parser": "^0.10.2", "next": "9.3.1", "next-fonts": "^1.0.3", "nprogress": "^0.2.0", diff --git a/website/pages/functions/[slug].js b/website/pages/functions/[slug].js index 0d1d967..1cb29b7 100644 --- a/website/pages/functions/[slug].js +++ b/website/pages/functions/[slug].js @@ -3,6 +3,7 @@ import HeadTag from '../../components/HeadTag'; import FunctionComponentTop from '../../components/FunctionComponentTop'; import FunctionTabsTop from '../../components/FunctionTabs/FunctionTabsTop'; import FunctionTabs from '../../components/FunctionTabs/FunctionTabs'; +import FunctionForm from '../../components/FunctionForm/FunctionForm'; import redirect from '../../utils/redirect'; import api from '../../utils/api'; import { API_URL } from '../../utils/config'; @@ -24,7 +25,11 @@ const FunctionComponent = (props) => { -
Slide 1
+ {(props.type !== "article") ? + + : +
Slide 1
+ }
Slide 2
Slide 3
diff --git a/website/public/css/general.css b/website/public/css/general.css index dc8f532..688f30c 100644 --- a/website/public/css/general.css +++ b/website/public/css/general.css @@ -96,23 +96,4 @@ a, .important { background-clip: padding-box; border: 1px solid #ced4da; border-radius: .5em; -} -.btn { - cursor: pointer; - border: 1px solid transparent; - padding: .375rem .75rem; - font-size: 1rem; - line-height: 1.5; - border-radius: .25rem; - transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; -} -.btn-dark:hover { - color: #fff; - background-color: #23272b; - border-color: #1d2124; -} -.btn-dark { - color: #fff; - background-color: #343a40; - border-color: #343a40; } \ No newline at end of file