From cfe04fb455e6df02e990f79f38e09eaf28eaabf2 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Sun, 17 Mar 2024 20:27:51 +0100 Subject: [PATCH 01/66] Changed the way of selecting the language and changes in the css for home --- webapp/src/components/Home/Home.js | 33 ++- webapp/src/components/fragments/NavBar.js | 37 ++- webapp/src/custom.css | 345 ++++------------------ webapp/src/translations/en/global.json | 5 +- webapp/src/translations/es/global.json | 5 +- 5 files changed, 113 insertions(+), 312 deletions(-) diff --git a/webapp/src/components/Home/Home.js b/webapp/src/components/Home/Home.js index 0faf09e7..70f0df79 100644 --- a/webapp/src/components/Home/Home.js +++ b/webapp/src/components/Home/Home.js @@ -11,17 +11,20 @@ function Home() { return (
-

+

{t("home.welcome")}

- -

- {/* Button to the login view */} - -

- {/* Link to the registration view */} - -

+
+ +

+ {/* Button to the login view */} + +

+ {/* Link to the registration view */} + +

+
+
); @@ -29,10 +32,10 @@ function Home() { function ButtonHowToPlay() { return ( - - + + ); } @@ -41,7 +44,9 @@ function Home() { function ButtonLogin() { return ( - + ); diff --git a/webapp/src/components/fragments/NavBar.js b/webapp/src/components/fragments/NavBar.js index d65ef527..00d3714f 100644 --- a/webapp/src/components/fragments/NavBar.js +++ b/webapp/src/components/fragments/NavBar.js @@ -1,26 +1,47 @@ -// NavBar.js -import React from 'react'; +import React, { useState } from 'react'; import Typography from "@mui/material/Typography"; import { Link } from 'react-router-dom'; +import MenuItem from '@mui/material/MenuItem'; +import Menu from '@mui/material/Menu'; import "../../custom.css"; -import {useTranslation} from "react-i18next"; +import { useTranslation } from "react-i18next"; function Navbar() { - const[t, i18n] = useTranslation("global"); + const [t, i18n] = useTranslation("global"); + const [anchorEl, setAnchorEl] = useState(null); + + const handleLanguageMenuOpen = (event) => { + setAnchorEl(event.currentTarget); + }; + + const handleLanguageMenuClose = () => { + setAnchorEl(null); + }; + + const changeLanguage = (language) => { + i18n.changeLanguage(language); + handleLanguageMenuClose(); + }; return (
- {t("navBar.title")} + {t("navBar.title")}
- - + + + changeLanguage("en")}> {t("navBar.en")} + changeLanguage("es")}>{t("navBar.es")} +
-
); } diff --git a/webapp/src/custom.css b/webapp/src/custom.css index 4964935c..ed18b894 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -1,59 +1,10 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - } - - code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; - } - .App { - text-align: center; - } - - .App-logo { - height: 40vmin; - pointer-events: none; - } - - @media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } - } - - .App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; - } - - .App-link { - color: #61dafb; - } - - @keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } - } - .navbar-container { +/*---------------------------Navbar---------------------------*/ + +.navbar-container { display: flex; justify-content: space-between; align-items: center; - background-color: blue; + background-color: rgb(23, 23, 151); width: 100%; padding: 10px; box-sizing: border-box; @@ -83,7 +34,7 @@ body { } - .en-button, .es-button{ + .language-button{ margin-right: 10px; background: rgb(171, 171, 221); border: none; @@ -125,251 +76,69 @@ body { text-align: center; } - .countdown { - font-weight: 500; - margin: 3em; + /*---------------------------Home---------------------------*/ + + .button { + height: 50px; + width: 200px; + position: relative; + background-color: transparent; + cursor: pointer; + border: 2px solid #252525; + overflow: hidden; + border-radius: 30px; + color: #333; + transition: all 0.5s ease-in-out; } - .topPanel{ - display: flex; - flex-direction: row; - align-items: center; - } - .divMenu { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100vh; + .btn-txt { + z-index: 1; + font-weight: 800; + letter-spacing: 4px; } - .menuButton{ - width: 200px; - height: 45px; - background: darkblue; + .type1::after { + content: ""; + position: absolute; + left: 0; + top: 0; + transition: all 0.5s ease-in-out; + background-color: rgb(23, 23, 151); + border-radius: 30px; + visibility: hidden; + height: 10px; + width: 10px; + z-index: -1; + } + + .button:hover { + box-shadow: 1px 1px 200px #190b44; + color: #fff; border: none; - outline: none; - border-radius: 40px; - box-shadow: 0 0 10px black; - cursor: pointer; - font-size: 16px; - color: white; - font-weight: 700; - margin: 0.5em; - text-decoration: none; - } - - .linkButton { - display: flex; - justify-content: center; - align-items: center; - width: 200px; - height: 45px; - background: darkblue; - border: none; - outline: none; - border-radius: 40px; - box-shadow: 0 0 10px black; - cursor: pointer; - font-size: 16px; - color: white; - font-weight: 700; - margin: 0.5em; - text-decoration: none; -} - - - - - .wrapper { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - height: 100vh; } - .wrapper button{ - width: 100%; - height: 45px; - background: darkblue; - border: none; - outline: none; - border-radius: 40px; - box-shadow: 0 0 10px black; - cursor:pointer; - font-size: 16px; - color: white; - font-weight: 700; + .type1:hover::after { + visibility: visible; + transform: scale(100) translateX(2px); } - .wrapper link{ - font-size: 14.5px; - text-align: center; - margin: 20px 0 15px; + .title-home{ + font-weight: bold; + text-align: center; } - -.wrapper{ + .buttons-home { display: flex; - justify-content: center; + flex-direction: column; align-items: center; - min-height: 100vh; - background-color: lightblue; -} - -.wrapper2{ - width: 420px; - background-color: blue; - color: white; - border-style: 10px; - padding: 30px 40px; - border-radius: 15%; -} - -.wrapper2 h1{ - font-size: 36px; - text-align: center; -} - -.wrapper2 .input-box{ - position: relative; - width: 100%; - height: 50px; - margin: 30px 0; -} - -.input-box input{ - width: 100%; - height: 100%; - background: lightblue; - border: none; - outline: none; - border: 2px solid gray; - border-radius: 40px; - font-size: 14.5px; - color: black; -} - -.input-box input::placeholder{ - background-color: lightblue; -} - -.input-box .icon{ - position: absolute; - right: 20px; - top: 50%; - transform: translateY(-50%); - font-size: 16px; -} - -.wrapper2 .remember-forgot{ - display: flex; - justify-content: space-between; - font-size: 14.5px; - margin: -15px 0 15px; -} - -.remember-forgot label input{ - accent-color: white; - margin-right: 4px; -} - -.remember-forgot a { - color: white; - text-decoration: none; -} - -.remember-forgot a:hover{ - text-decoration: underline; -} - -.wrapper2 button{ - width: 100%; - height: 45px; - background: white; - border: none; - outline: none; - border-radius: 40px; - box-shadow: 0 0 10px black; - cursor:pointer; - font-size: 16px; - color: black; - font-weight: 700; -} - -.button-register { - color: aliceblue; - } - - .button-login { - color: aliceblue; + justify-content: center; + margin-top: 100px; + border: 2px solid #333; + padding: 20px; + border-radius: 10px; + width: 30%; + margin-left: auto; + margin-right: auto; } - -.register-link p a { - color: white; - text-decoration: none; - font-weight: 600; -} - -.register-link p a:hover{ - text-decoration: underline; -} - -.answerButton { - width: 100%; - height: 45px; - background: darkblue; - border: none; - outline: none; - border-radius: 40px; - box-shadow: 0 0 10px black; - cursor:pointer; - font-size: 16px; - color: white; - font-weight: 700; -} - -.answerPanel { - display: grid; - grid-template-columns: repeat(2, 1fr); /* 2 columns */ - grid-template-rows: repeat(2, 1fr); /* 2 rows */ - gap: 10px; /* Adjust the gap between grid items */ - -} - -/* Adjust width of child elements */ -.answerPanel div > * { - width: 100%; /* Adjust as needed */ - margin:1em; -} - -p{ - text-align: center; -} - - -.question-view-container, .answerPanel { - background-color: lightblue; - padding: 20px; -} - -.Instructions-container { - background-color: #eaf6ff; /* Cambia este valor al color de azul que prefieras */ - padding: 20px; /* Añade un poco de espacio alrededor del contenido */ -} - -.instructions_title{ - background-color: darkblue; - color: white; -} - -.ins_ul p{ - background-color: blue; - color: white; -} - -.Instructions{ - background-color: lightblue; -} - + + /*---------------------------Login---------------------------*/ diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json index b7f7248d..022332d3 100644 --- a/webapp/src/translations/en/global.json +++ b/webapp/src/translations/en/global.json @@ -6,7 +6,10 @@ "register": "Don't have an account? Register here." }, "navBar": { - "title": "Know and win!" + "title": "Know and win!", + "en": "English", + "es": "Spanish", + "language": "Language" }, "instructions": { "title": "WIQ Instructions", diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json index 3277d13a..386ee9af 100644 --- a/webapp/src/translations/es/global.json +++ b/webapp/src/translations/es/global.json @@ -7,7 +7,10 @@ }, "navBar": { - "title": "¡Saber y ganar!" + "title": "¡Saber y ganar!", + "en": "Inglés", + "es": "Español", + "language": "Idioma" }, "instructions": { From 3db9f12afa94fa5c732b83585a1dcef21d00fe00 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Mon, 18 Mar 2024 12:04:04 +0100 Subject: [PATCH 02/66] turkish language added --- webapp/src/components/fragments/NavBar.js | 2 + webapp/src/custom.css | 2 +- webapp/src/index.js | 5 ++ webapp/src/translations/en/global.json | 1 + webapp/src/translations/es/global.json | 1 + webapp/src/translations/tk/global.json | 67 +++++++++++++++++++++++ 6 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 webapp/src/translations/tk/global.json diff --git a/webapp/src/components/fragments/NavBar.js b/webapp/src/components/fragments/NavBar.js index 00d3714f..e2c1e70e 100644 --- a/webapp/src/components/fragments/NavBar.js +++ b/webapp/src/components/fragments/NavBar.js @@ -39,6 +39,8 @@ function Navbar() { > changeLanguage("en")}> {t("navBar.en")} changeLanguage("es")}>{t("navBar.es")} + changeLanguage("tk")}>{t("navBar.tk")} + diff --git a/webapp/src/custom.css b/webapp/src/custom.css index ed18b894..deaf3d87 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -141,4 +141,4 @@ margin-right: auto; } - /*---------------------------Login---------------------------*/ + diff --git a/webapp/src/index.js b/webapp/src/index.js index f5d8ebec..409a8681 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -7,6 +7,8 @@ import {I18nextProvider} from "react-i18next"; import i18next from "i18next"; import global_es from "./translations/es/global.json" import global_en from "./translations/en/global.json" +import global_tk from "./translations/tk/global.json" + i18next.init({ @@ -21,6 +23,9 @@ i18next.init({ }, en:{ global:global_en, + }, + tk:{ + global:global_tk, } }, }) diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json index 022332d3..139e1d8c 100644 --- a/webapp/src/translations/en/global.json +++ b/webapp/src/translations/en/global.json @@ -9,6 +9,7 @@ "title": "Know and win!", "en": "English", "es": "Spanish", + "tk": "Turkish", "language": "Language" }, "instructions": { diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json index 386ee9af..e8d7d5d4 100644 --- a/webapp/src/translations/es/global.json +++ b/webapp/src/translations/es/global.json @@ -10,6 +10,7 @@ "title": "¡Saber y ganar!", "en": "Inglés", "es": "Español", + "tk": "Turco", "language": "Idioma" }, diff --git a/webapp/src/translations/tk/global.json b/webapp/src/translations/tk/global.json new file mode 100644 index 00000000..5f46ffe6 --- /dev/null +++ b/webapp/src/translations/tk/global.json @@ -0,0 +1,67 @@ +{ + "home": { + "welcome": "WIQ'e hoş geldiniz!", + "how_to_play": "Nasıl oynanır?", + "login": "Giriş yap", + "register": "Hesabınız yok mu? Buradan kaydolun." + }, + + "navBar": { + "title": "Bil ve Kazan!", + "en": "İngilizce", + "es": "İspanyolca", + "tk": "Türkçe", + "language": "Dil" + }, + + "instructions": { + "title": "WIQ Talimatları", + "objective": "Amaç:", + "objective_p1": "Oyunun amacı mümkün olduğunca çok soruyu doğru cevaplamaktır.", + "how_to_play": "Nasıl Oynanır:", + "how_to_play_p1": "Oyun bir dizi sorudan oluşur.", + "how_to_play_p2": "Her soruyu dikkatlice oku.", + "how_to_play_p3": "Verilen seçeneklerden doğru cevabı seç.", + "how_to_play_p4": "Seçtiğin cevabı göndermek için tıkla veya dokun.", + + "scoring": "Puanlama:", + "scoring_p1": "Her doğru cevap x puan kazandırır.", + "scoring_p2": "Yanlış cevaplar puanları düşürmez.", + "time_limit": "Zaman Sınırlaması:", + "time_limit_p1": "Bazı oyun modları her soruya cevap verme için bir zaman sınırlamasına sahip olabilir. Puanını maksimize etmek için hızlı ve doğru ol.", + "have_fun": "İyi Eğlenceler!", + "have_fun_p1": "Oyunun tadını çıkar ve bilgilerini test et. İyi şanslar!" + }, + + "login": { + "title": "Giriş Yap", + "username_placeholder": "Kullanıcı adı", + "password_placeholder": "Şifre", + "remember_me": "Beni hatırla", + "forgot_password": "Şifrenizi mi unuttunuz?", + "login_button": "Giriş yap", + "register_link": "Hesabınız yok mu? Buradan kaydolun." + }, + + "addUser": { + "title": "Kaydol", + "username_placeholder": "Kullanıcı adı", + "password_placeholder": "Şifre", + "repeat_password_placeholder": "Şifreyi tekrar girin", + "register_button": "Kaydol", + "login_link": "Zaten bir hesabınız mı var? Buradan giriş yapın." + }, + + "gameMenu": { + "history_button": "Geçmişi Görüntüle", + "new_game_button": "Yeni oyun oluştur", + "title": "Oyun Menüsü" + }, + + "questionView": { + "seconds": "saniye", + "question_counter": "Soru numarası: ", + "end_countdown": "Süre doldu!" + } + } + \ No newline at end of file From a8d25273b2c2633388f8dde5365033c773dfd147 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Mon, 18 Mar 2024 15:09:57 +0100 Subject: [PATCH 03/66] New interface of home --- webapp/public/casa.png | Bin 0 -> 6066 bytes webapp/public/instrucciones.png | Bin 0 -> 9911 bytes webapp/public/login.png | Bin 0 -> 9158 bytes webapp/public/signup.png | Bin 0 -> 10872 bytes webapp/src/App.js | 4 +- webapp/src/components/Home/Home.js | 90 +-- webapp/src/components/fragments/NavBar.js | 5 +- webapp/src/custom.css | 888 ++++++++++++++++++++-- 8 files changed, 874 insertions(+), 113 deletions(-) create mode 100644 webapp/public/casa.png create mode 100644 webapp/public/instrucciones.png create mode 100644 webapp/public/login.png create mode 100644 webapp/public/signup.png diff --git a/webapp/public/casa.png b/webapp/public/casa.png new file mode 100644 index 0000000000000000000000000000000000000000..e8d69b74a1eaaf025f1bf75dde51383d1a769303 GIT binary patch literal 6066 zcmeHLdpy(q+n>Ww%lRPYCTDk{ln|oZu+1Tg z8ml%e8;TJ#A*b2)`+n#5+|U2N*Ynr&JbUf+_4!=a`+8sR>%eQ4b;8M3e5>+S2m~T- zZ)fcSfd~ReL5P?T@S~$bvj?~oojCS~4RDo_(UgWGrIZj-ipb5kG#mj~z>5G6ib!!4jemoc)FtFKU<&Gh3$(zIs;a6|ir`gR5dlFW0S5k+&kSVYGswvy zB;ksbM@ma;NWp=#x&)s=M&ZBp{5uyvH6R0`tNUN+)Hn4=!jWJJn;Q5q z;3}!8E-$Yu3EwWM1nP%qYRamrO2ajPt2DnN03d|~&zt-*Dw-gS{{k$MO56D^1W?pw zb0h(^@J-nuAsh||TrzxeP_`0MMsYhx1y|n&z?2Yja%zAbKuRisHG&6a@E{G8se)8i zR^IFe5Vfg65@>}Ia+{(iNCLt%qyP(87gAOUAqm$2iUPX2=>-A6Ae6Oal>yC$fE}n5 zbb({y!$2@FDHR~EIG7hK1Z)L3(0@n}lH0dS0rL2EK&P}4IQq>L09by(hAW?95p@lQ%QHw))t0o5uBbqAL1-_T-+H zs${mQHVFyP3mhVDz74+jK##?xPw8^yGDSyEp{ z8^8D!n=$5xczQAY(6y}5{lQ)yCTe%CgogMZ$iBIKpUdrZcUl_+B0FhsZS_a|FtdoA z{>ZiUo#1yLnLM(y-*gUy=j$ z$YNT(LUtRiy}s;JUv9l;I}ztH?I!2QD(w1NO*!an((N^U!+`f)rB?ICxAMprF@z|Z zo?2i|wDS!^oIxT?xzP5hPFYS`Iz!LgSUfQ7``W>39j(!oNPl=Ezvn% zhr8^${ir^C2sNb2frbn{mWkv(`Y>GU@v_N6HkPoiC_B$3h9n%J$ySYUj}1a+&W87` zo!LFpuA_e*qcxirvj;UNSS4BhnFM-ALbI_Dv($6L)RHaOQeBmCl%=oYBNUT(&Aa~| z_bqIX)ZwRLY{RqgXpOmzbiI_T{ImLk;6AS0i8K5Q61aE?&P0IZr!~;{cOnyC=^%H6 zwNJ`T6&VHvyxhz(<mGCI9e8bu!N@8`QRO?X_#jg0+d@D?T;BY^r%`5FR} zSK0TiMQ&emm4Cv?tA&w~;~T{Imo?A#fck1peof-W4V>)>!+>@_*C!t_^(=*<9aSe1M>*pUxX=euK0u zVNx|9OhPnRz@N`{wp0(_$n>fI_PS%{EVap=AtBTw7~hD~t;t_LP$OCgD;D+_I7FrQ zEyf+#&&+51CIrP2&RDrYh|5h^*Rrnra$;+)*TdQb@n94$o_V2T3Dzp%2Uk6uC~%0y zX?>css?I8$i4kMLKA=;A*=*v=zJQ8W+KghX)fjaC0;b-!xDz#%H3h~u`JQ6dhONY_ zRkXq!P?jD1VTt|?6$2(p>q5C1`NKx3+^rTNJ;3=eOsblbH=A!X8dW`x+EouJX0n>Y zW^LM*@k(^W4lWnD`(Pl;P`q@M0^u{f)?;?ia~JHLlU&Nr7)HrxvlkZH7da3Pl9e_zjXd^vc*JeHv0qG!1Pj>OG+19~?ETq>xw zFND4v7i*WxqR;F+d<1^072?m|0EJ6%d=qCxk+uu#7xM&_a*=H~)Qxhxoe4woH}Iu& zqyQ4!j?s`O`Vc!XtEx>I6vChLj!b?tgp9h3T3G2mBnK)qKo97>%4+|tTz1?@;>|nF zb+H67u#yY62f^LEE}blZ1UoRQa~K>`SQd?Y%zQ%{owsu~Efo%V3$9I@Lq8OM0i%Vz zFt;?|(Tq~OEHKKCkrIF-)4|f>ReK}D#ElU@s9f{i)5YGk?-!2$G^a$>g@WaN>~gyL z&FOt5C+|5cEu!nFk%`(k0Mue8XRbIe$oS@<27SU8{c{Zysr2shk0q9I@NZu{&(%@J zSeU>e?y*1O2$ePp)Y&`424L{)Yq?o2(S&O9un7AVhBr{p8PNiIvoDU|{)Xdy{%Sax zN&NBPK}*%cQdsQD7lWpuULov#@%@dT@X$9nnZ^INiz3KOYuHFg{D2h?0-~3l2tl6b~IruV`jGD4O zNCo+(QX<*xmWKKD)gJ=rg0(m+m7PGF6R>{LJ0royJ)Muhz{)b%m)P)@*_=k$dH(iv zoCG#`?i~D3RzAP?g2ZJ?ZXnxmZCuHR-1`-3My2N(@c$^aF(YZH(23N?PqDBU;TWwK z*izDRu)*_2*m@%_oz#BhX#?y9kWm?1x(?W%QM7O0!j=NRtP2{UW3Nw;p+nrGe^tWj zIIcFw;pf;d2~6K#Tea#@J#aVDsk?06nw|q*^S~^uEg^7Pv%P zHR42iaIl0%T#YUuGcOJ>{CRLmyhcpD8A;fMv2N2-*V-TQ9 zyYCH9!H)TO_X7*kzI?{=C_swdIs}s1{TP5IQR%IuUz2$24b;>Sw=KrbgnDQ&wo{jO z4#b)CgHHiG_}n6Ei3PG5AhD&9Y}4IELD}J0qV8;_cR!Y6Z=0tZMPB`(_6q3IPDXMW zYKqG3w5YplXbglpXJ)DS5U$Uqg=74YKw^uNonU*YQLmye2aa(AeT2lm0$Mxo&8D?6 zS!Sfa9^H&|jIjb1u;?i%>(T9U`fp|Hbbv@wEEQClGlDL1J$S{ho?^TKNJ1zU^VF}# z0{A!~s;{+7ERey@B?fr9-H#@GMJx^1vySID*$O?tG4>aV&crJ}o>wc;o#lNwI~^W< zagfzifk?owZKbaq#C@ld2vdX_n9oY>_g@zC?t300ss;!J#9u=xl6|oziSzf?@64HL zsbw9=UQ3Moaq`(yj2n*-j+y>7oo1TdTNF&)2d5#OWMCL;J+^)p-^IwEY5ouRuZ9P_)g-J;>9vdMRxRl${Pq{(7Ecn zP-Zv=@`VB|X+W$7GCEEl+8I&2?bnyBE6~+Ejxi%Q*BMK5*SvRSHIxC3?@7)Nczuq2 zr2TK0$suUrWV93&p-}BTugX5@d{8xtpwPAmdpD-<M-Y`6HF21l2IdIg0~m}=^? zSP|CqEA3F+Id=NwJo;vH=}dR*Tynr|q2#V*QQ{Tci-SC(G0%;)@N>VPDb-ixP)qB( zjmVM7BgAoq;cZo z%+fvVNonWtR>Z<%`c7Qy<+=WJPxSf-#?e$G=JMxq{b%p!3l=m?CG&fnPy1x9cDg8r z*E#ozHsZX&E#8OwYO(nNk(@KxxcrMW*((;`_TX7`@jCih)NZ=I#J2dh&%u5B9BpT+ zE`%Nr6f~n(uRZmRUDCUI+I4&Xq8YZ_B_rF0)cip(q0QU%x7wK=oQ#_AQX*E{^?Yr3 zb3>y6q$HA{oq5_JOjl@X&8gVkb5!{*uk5mjIbG+GAlcz%FJdXNJ6d7OtW8VsBl-EY z>{oJiP9DB_f?Lk{{ae%df-7*&`yMkW~B_nXeB@{`Sg9KL}YfE`R&7nR&3Kek$?|L{(MZyu5>A7 zV51_>;I8Gg!2cAHWy4yA>@Ky;1GtNVI-YW>5khoBHJJjIMg6S^@kFyg*t~7;#B%3ySYW-)SQ0;|_>I@xlfmRy zhayhCom{V_e0~F=)V%hZvkS+aP7Zeb;Wjuk?U7;|k?W~Mt$AcIq-lQHcOebvT3zAb=!u_hak^w{;l?IttXg@k;CQKC@eOC|zAtto0H>$i?&q~xAz zfEX2p-d?UAj8$8`=^7ZwaveiG3l{Jh3~-J;8jh9t7Lw~8x@J||Tj`!MVPq_P)fq7A z6-^_fM;lHw2|d)q|HOHe@a`DOmJ06MpG3Br{-rVBv`4qpU!WQ{w7$-gufD}3Z<+ac zY@>0!aO!3*UaaYkbVsosJRJB|GF zX{f+q+`we78Ods!?PtMnx@K! zw`yaOji&f+1;4XXHQz+W^z})9Z~N=4z&cmQZ02W6gPTd-jT=z6#M?_{VS5KA0*+nE z;wD|8veY}D@j6IR)yJ``oYJ;I1tUAtZ#buf4>lV!2gc$P{7u6Z4h-H|-0tUU&RoCL zXcvAfqV_nMK8|*99(?CmR|7?5Gi$uR&?pl)Sja?%HdN^6h#Zwx;bV36qokcPC8Gn~ zJ0kBiukikly-_cNu5l`o4qbSd5d55Xe|56iBcm^3_4$(5$iaQClNPCtrydvV^pC($ zPfk~oyS~bxa}P*X)RISb_%ZP%<=P%-Q{Q7;`vG}JlACA$z2TuFM5`oj@4cdc&&j@i zU4fN_`VLrutHV*MJSps)+5Nez=>@VJHp1V&IXKmG4jY%dq^fdu`n9NcvPJ3H^(M_L zT#NUkA2geUg3MRPU8c7j__UgiMr3Yion);G*YJ+zRNZb7WU~_1kew_G;j&aGwc S%AN$jYPPp=vaUYtm-a7LI{Hxn literal 0 HcmV?d00001 diff --git a/webapp/public/instrucciones.png b/webapp/public/instrucciones.png new file mode 100644 index 0000000000000000000000000000000000000000..b3e1d33b50684914adb15ed9d25a33bd80804e7c GIT binary patch literal 9911 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 literal 0 HcmV?d00001 diff --git a/webapp/public/login.png b/webapp/public/login.png new file mode 100644 index 0000000000000000000000000000000000000000..7f8e7dccde273f4eefd03e9e69fcb4f7a0a48cc6 GIT binary patch literal 9158 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 literal 0 HcmV?d00001 diff --git a/webapp/public/signup.png b/webapp/public/signup.png new file mode 100644 index 0000000000000000000000000000000000000000..60e761bda7fcb4e8f928a9229925479205f4fbc3 GIT binary patch literal 10872 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 ba(c5(W*=zId=ZDMC - - + + {/* */} } /> } /> diff --git a/webapp/src/components/Home/Home.js b/webapp/src/components/Home/Home.js index 70f0df79..12291a89 100644 --- a/webapp/src/components/Home/Home.js +++ b/webapp/src/components/Home/Home.js @@ -2,69 +2,45 @@ import React from "react"; import Button from "@mui/material/Button"; import { Link } from 'react-router-dom'; import "../../custom.css"; -import {useTranslation} from "react-i18next"; - +import { useTranslation } from "react-i18next"; +import { FaUser, FaLock } from "react-icons/fa"; // Importar los iconos necesarios function Home() { - - const[t, i18n] = useTranslation("global"); + const [t] = useTranslation("global"); return ( -
-

- {t("home.welcome")} -

-
- -

- {/* Button to the login view */} - -

- {/* Link to the registration view */} - -

-
- +
+ + +
+
+

+ + + + W + + Instructions + + + + I + + Login + + + + Q + + Add user + + + +

+
+
); - - - function ButtonHowToPlay() { - return ( - - - - ); - - } - - -function ButtonLogin() { - return ( - - - - ); - } -function LinkRegister() { - return ( - - {t("home.register")} - - ); - -} -} - - export default Home; diff --git a/webapp/src/components/fragments/NavBar.js b/webapp/src/components/fragments/NavBar.js index e2c1e70e..f941719c 100644 --- a/webapp/src/components/fragments/NavBar.js +++ b/webapp/src/components/fragments/NavBar.js @@ -38,9 +38,8 @@ function Navbar() { onClose={handleLanguageMenuClose} > changeLanguage("en")}> {t("navBar.en")} - changeLanguage("es")}>{t("navBar.es")} - changeLanguage("tk")}>{t("navBar.tk")} - + changeLanguage("es")}> {t("navBar.es")} + changeLanguage("tk")}> {t("navBar.tk")}
diff --git a/webapp/src/custom.css b/webapp/src/custom.css index deaf3d87..8d8f62d1 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -52,8 +52,6 @@ display: flex; } - - .help-button img { width: 40px; height: 40px; @@ -77,68 +75,856 @@ } /*---------------------------Home---------------------------*/ + /* Transitions aren't quite as smooth on firefox */ + +:root { + --gradient: conic-gradient( + from 240deg at 50% 50%, + #00ffc3, + #00fad9, + #00f4f0, + #00eeff, + #00e6ff, + #00dcff, + #00d2ff, + #00c5ff, + #00b8ff, + #6da8ff, + #9f97ff, + #c285ff + ); +} + +* +, *::before +, *::after { + box-sizing: border-box; + font-family: "Poppins", sans-serif; +} + +body +, html { + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: transparent; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; +} + +body { + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100vh; + overflow: hidden; + margin: 0; + font-size: 100%; + background: black; + color: white; + backface-visibility: hidden; +} + +input { + display: none; +} + +#welcomeMessage { + font-size: 130%; +} + +#welcomeMessage +, #welcomeMessage + figcaption +, #welcomeMessage + figcaption + h1 +, #welcomeMessage + figcaption + h1 + b { + position: relative; + display: flex; + align-items: center; + justify-content: center; + width: 100%; + margin: 0; +} + +#welcomeMessage +figcaption { + width: auto; + z-index: 1; +} + +#welcomeMessage +figcaption::before +, #welcomeMessage + figcaption::after { + position: absolute; + background: #222; + width: 0%; + height: 0%; + content: ""; + z-index: -1; +} + +#welcomeMessage +figcaption::after { + background: var(--gradient); + width: calc(100% + 3.1em); + height: calc(100% + 3.1em); + z-index: -2; +} + +#welcomeMessage +figcaption +h1 { + text-transform: lowercase; + background: #555; + box-shadow: rgba(0, 0, 0, 0.19) 0px 0.625em 1.25em, rgba(0, 0, 0, 0.23) 0px 0.375em 0.375em; + transition: all 0.1s ease-in-out; +} + +#welcomeMessage +figcaption +h1:active { + transform: scale(0.93); + transition: all 0.05s ease-in-out; +} + +#welcomeMessage +figcaption +h1::before +, #welcomeMessage + figcaption + h1::after { + position: absolute; + white-space: nowrap; + font-size: 0.7em; + font-weight: 200; + transition: all 0.7s ease-in-out; +} + +#welcomeMessage +figcaption +h1::before { + top: -4.3em; + right: 2em; + content: "Click to close"; + font-weight: 400; + color: #666; + opacity: 0; +} + +#welcomeMessage +figcaption +h1::after { + bottom: -3em; + content: "Click to continue"; + transition: all 0.3s ease-in-out; +} + +#welcomeMessage +figcaption +h1 +label { + position: absolute; + width: 100%; + height: 100%; + z-index: 999; +} + +#welcomeMessage +figcaption +h1 +label:nth-child(2) { + display: flex; + align-items: center; + justify-content: center; + width: 1em; + height: 1em; + right: 0; + top: -3em; + background: transparent; + color: #666; + outline: 1px solid #666; + padding: 5px; + opacity: 0; + z-index: 998; +} + +#welcomeMessage +figcaption +h1 +label:hover { + cursor: pointer; +} + +#welcomeMessage +figcaption +h1 +b { + width: 2em; + height: 2em; + background: #555; + user-select: none; +} + +#welcomeMessage +figcaption +h1 +b +a { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + z-index: 1; + transition: all 0.35s ease-in-out; +} + +#welcomeMessage +figcaption +h1 +b +a:focus::before { + position: absolute; + width: 100%; + height: 100%; + background: #555; + border-radius: 0.3em; + content:""; + z-index: -1; +} + +#welcomeMessage +figcaption +h1 +b +a:focus::after { + position: absolute; + width: calc(100% + 0.05em); + height: calc(100% + 0.05em); + background: var(--gradient); + border-radius: 0.3em; + content:""; + z-index: -2; + animation: spinny 5s linear infinite; +} + +#welcomeMessage +figcaption +h1 +b +a:active::after { + filter: blur(5px); +} + +@keyframes spinny { + 0% { + transform: rotateZ(0deg); + border-radius: 0.3em; + } + 50% { + border-radius: 1em; + } + 100% { + transform: rotateZ(360deg); + border-radius: 0.3em; + } +} + +#welcomeMessage +figcaption +h1 +b +a +svg { + position: relative; + width: 55%; + height: auto; + fill: url(#svgGradient); + filter: grayscale(100%) brightness(1.2); + transform: rotateY(-180deg); + transition: all 200ms linear; +} + +#welcomeMessage +figcaption +h1 +b +a:hover +svg { + filter: grayscale(0%) brightness(1); + transition: all 200ms ease-in-out; +} + +#welcomeMessage +figcaption +h1 +b +a:focus +svg { + filter: grayscale(0%) brightness(1); + transform: rotateY(-180deg) scale(0.9); + transition: all 70ms linear; +} + +#toggleOpen:checked + ~ #welcomeMessage { + font-size: 100%; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption::before { + width: calc(100% + 3em); + height: calc(100% + 3em); + border-radius: 0.7em; + transition: all 0.7s ease-in-out; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption::after { + width: calc(100% + 6em); + height: calc(100% + 6em); + border-radius: 1em; + transition: all 0.7s ease-in-out; +} + +#toggleClose:checked + ~ #welcomeMessage + figcaption::before + , #toggleClose:checked + ~ #welcomeMessage + figcaption::after { + transition: all 0.7s ease-in-out; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption + h1 { + background: transparent; + box-shadow: none; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption + h1:active { + transform: none; +} + +#toggleClose:checked + ~ #welcomeMessage + figcaption + h1 { + background: transparent; + transition: all 0.05s ease-in-out; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption + h1::before { + opacity: 1; + transition: all 0.7s ease-in-out; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption + h1::after { + opacity: 0; + transition: all 0.7s ease-in-out; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption + h1 + label:first-of-type { + display: none; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption + h1 + label:last-of-type { + z-index: 999; + opacity: 1; + transition: all 0.7s ease-in-out; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption + h1 + b { + color: #555; + border-radius: 0.3em; + box-shadow: rgba(0, 0, 0, 0.19) 0px 0.625em 1.25em, rgba(0, 0, 0, 0.23) 0px 0.375em 0.375em; + transition: all 0.35s ease-in-out; +} + +#toggleClose:checked + ~ #welcomeMessage + figcaption + h1 + b { + transition: all 0.35s ease-in-out; + transition-delay: 0.35s; + animation: welcomeClose 0.7s ease-in-out 1; + animation-fill-mode: forwards; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption + h1 + b:not(:first-of-type, :last-of-type) { + animation: welcome 0.7s ease-in-out 1; + animation-fill-mode: forwards; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption + h1 + b:first-of-type { + animation: welcomeFirst 0.7s ease-in-out 1; + animation-fill-mode: forwards; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption + h1 + b:last-of-type { + animation: welcomeLast 0.7s ease-in-out 1; + animation-fill-mode: forwards; +} + +#toggleClose:checked + ~ #welcomeMessage + figcaption + h1 + b:first-of-type { + animation: welcomeCloseFirst 0.7s ease-in-out 1; + animation-fill-mode: forwards; +} + +#toggleClose:checked + ~ #welcomeMessage + figcaption + h1 + b:last-of-type { + animation: welcomeCloseLast 0.7s ease-in-out 1; + animation-fill-mode: forwards; +} + +#toggleClose:checked + ~ #welcomeMessage + figcaption + h1 + b::after { + opacity: 0; + transition: all 0.35s ease-in-out; +} + +#toggleOpen:checked + ~ #welcomeMessage + figcaption + h1 + b + a { + opacity: 1; + transition: all 0.35s ease-in-out; + transition-delay: 0.35s; +} - .button { - height: 50px; - width: 200px; - position: relative; - background-color: transparent; - cursor: pointer; - border: 2px solid #252525; - overflow: hidden; - border-radius: 30px; - color: #333; - transition: all 0.5s ease-in-out; +@keyframes welcome { + 0% { + margin: 0 0; + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 20% { + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 80% { + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 100% { + margin: 0 1.5em; + transform: rotateY(180deg); + width: 3em; + height: 3em; + } +} + +@keyframes welcomeFirst { + 0% { + margin: 0 0; + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 20% { + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 80% { + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 100% { + margin: 0 1.5em 0 0; + transform: rotateY(180deg); + width: 3em; + height: 3em; + } +} + +@keyframes welcomeLast { + 0% { + margin: 0 0; + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 20% { + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 80% { + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 100% { + margin: 0 0 0 1.5em; + transform: rotateY(180deg); + width: 3em; + height: 3em; + } +} + +@keyframes welcomeClose { + 0% { + margin: 0 1.5em; + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 20% { + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 80% { + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 100% { + margin: 0 0; + transform: rotateY(0deg); + width: 2em; + height: 2em; + } +} + +@keyframes welcomeCloseFirst { + 0% { + margin: 0 1.5em 0 0; + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 20% { + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 80% { + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 100% { + margin: 0 0; + transform: rotateY(0deg); + width: 2em; + height: 2em; + } +} + +@keyframes welcomeCloseLast { + 0% { + margin: 0 0 0 1.5em; + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 20% { + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 80% { + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 100% { + margin: 0 0; + transform: rotateY(0deg); + width: 2em; + height: 2em; + } +} + +@media (max-width: 1270px) { + #toggleOpen:checked + ~ #welcomeMessage { + font-size: 80%; + } +} + +@media (max-width: 1000px) { + #toggleOpen:checked + ~ #welcomeMessage { + font-size: 60%; + } +} + +@media (max-width: 800px) { + body { + height: auto; + min-height: 100vh; + overflow-x: hidden; + overflow-y: auto; + align-items: flex-start; } - .btn-txt { - z-index: 1; - font-weight: 800; - letter-spacing: 4px; + #welcomeMessage { + margin-top: 10em; } - .type1::after { - content: ""; - position: absolute; - left: 0; - top: 0; - transition: all 0.5s ease-in-out; - background-color: rgb(23, 23, 151); - border-radius: 30px; - visibility: hidden; - height: 10px; - width: 10px; - z-index: -1; + #toggleOpen:checked + ~ #welcomeMessage { + margin-top: 8em; + font-size: 100%; } - .button:hover { - box-shadow: 1px 1px 200px #190b44; - color: #fff; - border: none; + #toggleOpen:checked + ~ #welcomeMessage + figcaption + h1 { + flex-direction: column; + } + + #welcomeMessage figcaption h1::before { + content: "Close"; } - .type1:hover::after { - visibility: visible; - transform: scale(100) translateX(2px); + @keyframes welcome { + 0% { + margin: 0 0; + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 20% { + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 80% { + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 100% { + margin: 1em 0; + transform: rotateY(180deg); + width: 3em; + height: 3em; + } } - .title-home{ - font-weight: bold; - text-align: center; + @keyframes welcomeFirst { + 0% { + margin: 0 0; + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 20% { + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 80% { + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 100% { + margin: 0 0 1em 0; + transform: rotateY(180deg); + width: 3em; + height: 3em; + } } - .buttons-home { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - margin-top: 100px; - border: 2px solid #333; - padding: 20px; - border-radius: 10px; - width: 30%; - margin-left: auto; - margin-right: auto; + @keyframes welcomeLast { + 0% { + margin: 0 0; + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 20% { + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 80% { + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 100% { + margin: 1em 0 0 0; + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + } + + @keyframes welcomeClose { + 0% { + margin: 1em 0em; + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 20% { + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 80% { + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 100% { + margin: 0 0; + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + } + + @keyframes welcomeCloseFirst { + 0% { + margin: 0 0 1em 0 !important; + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 20% { + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 80% { + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 100% { + margin: 0 0; + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + } + + @keyframes welcomeCloseLast { + 0% { + margin: 1em 0 0 0 !important; + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 20% { + transform: rotateY(180deg); + width: 3em; + height: 3em; + } + 80% { + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + 100% { + margin: 0 0; + transform: rotateY(0deg); + width: 2em; + height: 2em; + } + } +} + +@media (max-width: 650px) { + #welcomeMessage { + font-size: 100%; + } +} + +@media (max-width: 500px) { + #welcomeMessage { + font-size: 80%; } + #toggleOpen:checked + ~ #welcomeMessage { + font-size: 100%; + } +} + +@media (max-width: 400px) { + #welcomeMessage { + font-size: 65%; + } +} + +/* Estilos para el icono FaUser */ +.icon { + /* Agrega tus estilos personalizados aquí */ + color: #fff; /* Cambia el color del icono a blanco */ + font-size: 20px; /* Cambia el tamaño del icono */ +} + + From 3fdce44024dfc9dd8a9fff9bcf2a331655f14245 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Mon, 18 Mar 2024 16:48:47 +0100 Subject: [PATCH 04/66] login done with the new interface --- webapp/src/App.js | 2 +- webapp/src/components/Home/Home.js | 4 +- .../components/loginAndRegistration/Login.js | 55 +++++----- webapp/src/custom.css | 101 ++++++++++++++++-- 4 files changed, 124 insertions(+), 38 deletions(-) diff --git a/webapp/src/App.js b/webapp/src/App.js index fca3ea1e..b1007ca1 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -15,7 +15,7 @@ function App() { return ( - {/* */} + {/* */} } /> } /> diff --git a/webapp/src/components/Home/Home.js b/webapp/src/components/Home/Home.js index 12291a89..5b4acf67 100644 --- a/webapp/src/components/Home/Home.js +++ b/webapp/src/components/Home/Home.js @@ -10,8 +10,8 @@ function Home() { return (
- - + +

diff --git a/webapp/src/components/loginAndRegistration/Login.js b/webapp/src/components/loginAndRegistration/Login.js index 167b5ca8..fb1227c3 100644 --- a/webapp/src/components/loginAndRegistration/Login.js +++ b/webapp/src/components/loginAndRegistration/Login.js @@ -1,5 +1,4 @@ import React from "react"; -import { FaUser, FaLock } from "react-icons/fa"; import { Link } from "react-router-dom"; import Button from "@mui/material/Button"; import { useTranslation } from "react-i18next"; @@ -9,30 +8,35 @@ const Login = () => { const { t } = useTranslation("global"); return ( -
-
-
-

{t("login.title")}

-
- - -
-
- - -
- -
- - {t("login.forgot_password")} -
- - - -
-
+
+
+
+ +

{t("login.title")}

+
+ +
+
+ +
+ +
+ + {t("login.remember_me")} +
+ + + + +
); }; @@ -57,7 +61,6 @@ function LinkRegister() { export default Login; - // // src/components/Login.js // import React, { useState } from 'react'; // import axios from 'axios'; diff --git a/webapp/src/custom.css b/webapp/src/custom.css index 8d8f62d1..a0b7815b 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -1,5 +1,6 @@ -/*---------------------------Navbar---------------------------*/ + +/*---------------------------Navbar---------------------------*/ .navbar-container { display: flex; justify-content: space-between; @@ -73,6 +74,94 @@ margin: 0.5em; text-align: center; } + +/*---------------------------Login---------------------------*/ + .form { + display: flex; + flex-direction: column; + gap: 10px; + padding-left: 2em; + padding-right: 2em; + padding-bottom: 0.4em; + background-color: #171717; + border-radius: 25px; + transition: 0.4s ease-in-out; + align-items: center; + } + + .card { + background-image: linear-gradient(163deg, #00ff75 0%, #3700ff 100%); + border-radius: 22px; + transition: all 0.3s; + } + + .card2 { + border-radius: 0; + transition: all 0.2s; + } + + .card2:hover { + transform: scale(0.98); + border-radius: 20px; + } + + .card:hover { + box-shadow: 0px 0px 30px 1px rgba(0, 255, 117, 0.3); + } + + + .input-box input{ + width: 100%; + height: 100%; + background: lightblue; + border: none; + outline: none; + border: 2px solid gray; + border-radius: 40px; + font-size: 14.5px; + color: black; +} + +.input-box input::placeholder{ + background-color: rgb(255, 255, 255); +} + + + +.remember-forgot { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; +} + +.button-menu { + text-decoration: none; +} + +.button-menu Button { + background-color: #007bff; + color: white; + padding: 10px 20px; + border-radius: 5px; + cursor: pointer; + outline: none; + border: none; +} + +.button-menu Button:hover { + background-color: #0056b3; +} + +.button-register { + text-decoration: none; + color: #007bff; +} + +.button-register:hover { + text-decoration: underline; +} + /*---------------------------Home---------------------------*/ /* Transitions aren't quite as smooth on firefox */ @@ -124,7 +213,7 @@ body { backface-visibility: hidden; } -input { +.input-home { display: none; } @@ -919,12 +1008,6 @@ svg { } } - -/* Estilos para el icono FaUser */ -.icon { - /* Agrega tus estilos personalizados aquí */ - color: #fff; /* Cambia el color del icono a blanco */ - font-size: 20px; /* Cambia el tamaño del icono */ -} + From c78b74385e04d7b0813805b99c07d9beb53014e6 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Mon, 18 Mar 2024 17:04:52 +0100 Subject: [PATCH 05/66] Register improved --- .../loginAndRegistration/AddUser.js | 35 ++++++---- .../components/loginAndRegistration/Login.js | 44 ++++++------- webapp/src/custom.css | 64 ++++++++++++------- 3 files changed, 82 insertions(+), 61 deletions(-) diff --git a/webapp/src/components/loginAndRegistration/AddUser.js b/webapp/src/components/loginAndRegistration/AddUser.js index 5911c7f5..65e26d88 100644 --- a/webapp/src/components/loginAndRegistration/AddUser.js +++ b/webapp/src/components/loginAndRegistration/AddUser.js @@ -1,5 +1,4 @@ import React from "react"; -import { FaUser, FaLock } from "react-icons/fa"; import "../../custom.css"; import { Link } from "react-router-dom"; import { useTranslation } from "react-i18next"; @@ -8,28 +7,37 @@ const AddUser = () => { const { t } = useTranslation("global"); return ( -
-
-
+
+
+

{t("addUser.title")}

- - +
- - +
- - +
-
- + +
); }; @@ -37,7 +45,7 @@ const AddUser = () => { function LinkLogin() { const { t } = useTranslation("global"); return ( - + {t("addUser.login_link")} ); @@ -95,4 +103,3 @@ export default AddUser; // // ); // }; - diff --git a/webapp/src/components/loginAndRegistration/Login.js b/webapp/src/components/loginAndRegistration/Login.js index fb1227c3..b3adbf44 100644 --- a/webapp/src/components/loginAndRegistration/Login.js +++ b/webapp/src/components/loginAndRegistration/Login.js @@ -11,30 +11,24 @@ const Login = () => {
- -

{t("login.title")}

-
- -
-
- -
- -
- - {t("login.remember_me")} -
- - - +

{t("login.title")}

+
+ +
+
+ +
+
+ +
+ + +
@@ -45,7 +39,7 @@ function ButtonMenu() { const { t } = useTranslation("global"); return ( - + ); } diff --git a/webapp/src/custom.css b/webapp/src/custom.css index a0b7815b..6cd04138 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -75,7 +75,7 @@ text-align: center; } -/*---------------------------Login---------------------------*/ +/*---------------------------Login and Register---------------------------*/ .form { display: flex; flex-direction: column; @@ -113,7 +113,7 @@ .input-box input{ width: 100%; height: 100%; - background: lightblue; + background: rgb(177, 233, 188); border: none; outline: none; border: 2px solid gray; @@ -126,7 +126,6 @@ background-color: rgb(255, 255, 255); } - .remember-forgot { display: flex; @@ -134,35 +133,56 @@ align-items: center; margin-bottom: 20px; } + -.button-menu { - text-decoration: none; -} - -.button-menu Button { - background-color: #007bff; +button[type="submit"] { + width: 10em; + position: relative; + height: 3.5em; + border: 3px ridge #149CEA; + outline: none; + background-color: transparent; color: white; - padding: 10px 20px; - border-radius: 5px; + transition: 1s; + border-radius: 0.3em; + font-size: 16px; + font-weight: bold; cursor: pointer; - outline: none; - border: none; } -.button-menu Button:hover { - background-color: #0056b3; +button[type="submit"]::after { + content: ""; + position: absolute; + top: -10px; + left: 3%; + width: 95%; + height: 40%; + background-color: #171717; + transition: 0.5s; + transform-origin: center; +} + +button[type="submit"]::before { + content: ""; + transform-origin: center; + position: absolute; + top: 80%; + left: 3%; + width: 95%; + height: 40%; + background-color: #171717; + transition: 0.5s; } -.button-register { - text-decoration: none; - color: #007bff; +button[type="submit"]:hover::before, button:hover::after { + transform: scale(0) } -.button-register:hover { - text-decoration: underline; +button[type="submit"]:hover { + box-shadow: inset 0px 0px 25px #3700ff; } - - + + /*---------------------------Home---------------------------*/ /* Transitions aren't quite as smooth on firefox */ From 0afcb150c54472a450fdb1d07caf383cc17bd37c Mon Sep 17 00:00:00 2001 From: lauratbg Date: Mon, 18 Mar 2024 17:21:01 +0100 Subject: [PATCH 06/66] Added way to internationalize without nav --- webapp/public/idioma.png | Bin 0 -> 9289 bytes webapp/src/components/Home/Home.js | 25 ++++++++++++++---- .../components/loginAndRegistration/Login.js | 1 - webapp/src/translations/en/global.json | 3 ++- webapp/src/translations/es/global.json | 4 ++- webapp/src/translations/tk/global.json | 5 +++- 6 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 webapp/public/idioma.png diff --git a/webapp/public/idioma.png b/webapp/public/idioma.png new file mode 100644 index 0000000000000000000000000000000000000000..aa6f6962acccfd640928601db98d8a7091c780f7 GIT binary patch literal 9289 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 { + const languages = ["en", "es", "tk"]; + const currentIndex = languages.indexOf(language); + const nextIndex = (currentIndex + 1) % languages.length; + const nextLanguage = languages[nextIndex]; + i18n.changeLanguage(nextLanguage); + setLanguage(nextLanguage); + alert(`${t("home.language")}`); + }; return (
@@ -35,7 +44,12 @@ function Home() { Add user - + + ! + + Language + +

@@ -44,3 +58,4 @@ function Home() { } export default Home; + diff --git a/webapp/src/components/loginAndRegistration/Login.js b/webapp/src/components/loginAndRegistration/Login.js index b3adbf44..ae03d238 100644 --- a/webapp/src/components/loginAndRegistration/Login.js +++ b/webapp/src/components/loginAndRegistration/Login.js @@ -1,6 +1,5 @@ import React from "react"; import { Link } from "react-router-dom"; -import Button from "@mui/material/Button"; import { useTranslation } from "react-i18next"; import "../../custom.css"; diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json index 139e1d8c..0a2bd647 100644 --- a/webapp/src/translations/en/global.json +++ b/webapp/src/translations/en/global.json @@ -3,7 +3,8 @@ "welcome": "Welcome to WIQ!", "how_to_play": "How to play?", "login": "Login", - "register": "Don't have an account? Register here." + "register": "Don't have an account? Register here.", + "language": "The language has been changed to English" }, "navBar": { "title": "Know and win!", diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json index e8d7d5d4..50888b37 100644 --- a/webapp/src/translations/es/global.json +++ b/webapp/src/translations/es/global.json @@ -3,7 +3,9 @@ "welcome": "¡Bienvenido a WIQ!", "how_to_play": "¿Cómo jugar?", "login": "Iniciar sesión", - "register": "¿No tienes una cuenta? Regístrate aquí." + "register": "¿No tienes una cuenta? Regístrate aquí.", + "language": "El idioma ha sido cambiado a español" + }, "navBar": { diff --git a/webapp/src/translations/tk/global.json b/webapp/src/translations/tk/global.json index 5f46ffe6..9d1982a6 100644 --- a/webapp/src/translations/tk/global.json +++ b/webapp/src/translations/tk/global.json @@ -3,7 +3,9 @@ "welcome": "WIQ'e hoş geldiniz!", "how_to_play": "Nasıl oynanır?", "login": "Giriş yap", - "register": "Hesabınız yok mu? Buradan kaydolun." + "register": "Hesabınız yok mu? Buradan kaydolun.", + "language": "Dilin Türkçe olduğu değiştirilmiştir" + }, "navBar": { @@ -24,6 +26,7 @@ "how_to_play_p3": "Verilen seçeneklerden doğru cevabı seç.", "how_to_play_p4": "Seçtiğin cevabı göndermek için tıkla veya dokun.", + "scoring": "Puanlama:", "scoring_p1": "Her doğru cevap x puan kazandırır.", "scoring_p2": "Yanlış cevaplar puanları düşürmez.", From beb4f9664879ef4a3685240f5ccc49adc6ba4c81 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Tue, 19 Mar 2024 18:46:18 +0100 Subject: [PATCH 07/66] Instructions interface improved --- webapp/src/components/Instructions.js | 4 +-- webapp/src/custom.css | 42 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/Instructions.js b/webapp/src/components/Instructions.js index 7ffc2338..160978ab 100644 --- a/webapp/src/components/Instructions.js +++ b/webapp/src/components/Instructions.js @@ -6,10 +6,10 @@ import {useTranslation} from "react-i18next"; function Instructions() { - const[t, i18n] = useTranslation("global"); + const[t] = useTranslation("global"); return ( -
+

{t("instructions.title")}

diff --git a/webapp/src/custom.css b/webapp/src/custom.css index 6cd04138..c6d4c429 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -182,6 +182,48 @@ button[type="submit"]:hover { box-shadow: inset 0px 0px 25px #3700ff; } +/*---------------------------Instructions---------------------------*/ +.instructions_title { + font-size: 35px; + font-weight: bold; + margin-bottom: 20px; + background: linear-gradient(to right, #01f051, #00f2ff); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + text-align: center; + display: flex; + justify-content: center; + align-items: center; +} + + +.ins_ul { + list-style-type: none; + padding-left: 0; + background: linear-gradient(to bottom, #a276e4, #4aecce); + border-radius: 5px; + padding: 10px; + text-align: center; + color: black; + font-weight: bold; +} + +/* Estilos para los elementos de la lista de instrucciones */ +.ins_ul li { + margin-bottom: 5px; + color: #000; /* Color de texto negro */ + text-align: justify; + font-weight: lighter; + +} + + +.instructions_container { + padding: 20px; + background-color: #f0f0f0; + border-radius: 5px; + +} /*---------------------------Home---------------------------*/ /* Transitions aren't quite as smooth on firefox */ From ef9e644f94985dbdaa92c2b2919b43b0664715d5 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Wed, 20 Mar 2024 16:00:44 +0100 Subject: [PATCH 08/66] Added the navbar, improvements of things and also added a scroll bar when needed --- webapp/src/App.js | 30 +++---- webapp/src/components/Home/Home.js | 26 ++---- .../loginAndRegistration/AddUser.js | 2 + .../components/loginAndRegistration/Login.js | 3 + webapp/src/custom.css | 90 ++++++++++++------- 5 files changed, 82 insertions(+), 69 deletions(-) diff --git a/webapp/src/App.js b/webapp/src/App.js index b1007ca1..b0287a21 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -10,23 +10,23 @@ import Container from '@mui/material/Container'; import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; import './custom.css'; - function App() { return ( - - - {/* */} - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - + +
+ + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + +
); } diff --git a/webapp/src/components/Home/Home.js b/webapp/src/components/Home/Home.js index 4f19a2f6..c6476f27 100644 --- a/webapp/src/components/Home/Home.js +++ b/webapp/src/components/Home/Home.js @@ -1,24 +1,13 @@ import React, { useState } from "react"; import { Link } from 'react-router-dom'; import "../../custom.css"; -import { useTranslation } from "react-i18next"; -function Home() { - const { t, i18n } = useTranslation("global"); - const [language, setLanguage] = useState("en"); - const changeLanguage = () => { - const languages = ["en", "es", "tk"]; - const currentIndex = languages.indexOf(language); - const nextIndex = (currentIndex + 1) % languages.length; - const nextLanguage = languages[nextIndex]; - i18n.changeLanguage(nextLanguage); - setLanguage(nextLanguage); - alert(`${t("home.language")}`); - }; + +function Home() { return ( -
+
@@ -44,16 +33,11 @@ function Home() { Add user - - ! - - Language - -
-
+
+ ); } diff --git a/webapp/src/components/loginAndRegistration/AddUser.js b/webapp/src/components/loginAndRegistration/AddUser.js index 65e26d88..e4c8459d 100644 --- a/webapp/src/components/loginAndRegistration/AddUser.js +++ b/webapp/src/components/loginAndRegistration/AddUser.js @@ -7,6 +7,7 @@ const AddUser = () => { const { t } = useTranslation("global"); return ( +
@@ -39,6 +40,7 @@ const AddUser = () => {
+
); }; diff --git a/webapp/src/components/loginAndRegistration/Login.js b/webapp/src/components/loginAndRegistration/Login.js index ae03d238..25d25835 100644 --- a/webapp/src/components/loginAndRegistration/Login.js +++ b/webapp/src/components/loginAndRegistration/Login.js @@ -7,6 +7,8 @@ const Login = () => { const { t } = useTranslation("global"); return ( +
+
@@ -31,6 +33,7 @@ const Login = () => {
+
); }; diff --git a/webapp/src/custom.css b/webapp/src/custom.css index c6d4c429..82c35fd5 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -1,19 +1,23 @@ +/*---------------------------App---------------------------*/ +.main { + width: 100%; +} /*---------------------------Navbar---------------------------*/ .navbar-container { - display: flex; - justify-content: space-between; - align-items: center; - background-color: rgb(23, 23, 151); - width: 100%; - padding: 10px; - box-sizing: border-box; - } + display: flex; + justify-content: space-between; + align-items: center; + background-image: linear-gradient(to right, rgb(128, 227, 238), rgb(209, 66, 209)); /* Degradado de verde a morado */ + width: 100vw; + padding: 10px; + box-sizing: border-box; + position: fixed; + left: 0; + top: 0; +} - main { - width: 100%; - } .navbar-container img { display: flex; @@ -25,7 +29,8 @@ } .navbar-text { - color: white; + color: rgb(0, 0, 0); + font-weight: bold; } @@ -37,7 +42,7 @@ .language-button{ margin-right: 10px; - background: rgb(171, 171, 221); + background: rgb(0, 0, 0); border: none; outline: none; border-radius: 40px; @@ -79,12 +84,12 @@ .form { display: flex; flex-direction: column; - gap: 10px; + gap: 50px; padding-left: 2em; padding-right: 2em; padding-bottom: 0.4em; background-color: #171717; - border-radius: 25px; + border-radius: 30px; transition: 0.4s ease-in-out; align-items: center; } @@ -110,21 +115,23 @@ } - .input-box input{ + .input-box input { width: 100%; - height: 100%; + height: 100%; background: rgb(177, 233, 188); border: none; outline: none; border: 2px solid gray; border-radius: 40px; - font-size: 14.5px; + font-size: 18px; color: black; -} - -.input-box input::placeholder{ + } + + .input-box input::placeholder { background-color: rgb(255, 255, 255); -} + font-size: 18px; /* Ajustar el tamaño de la fuente del marcador de posición */ + } + .remember-forgot { @@ -145,7 +152,7 @@ button[type="submit"] { color: white; transition: 1s; border-radius: 0.3em; - font-size: 16px; + font-size: 18px; font-weight: bold; cursor: pointer; } @@ -194,9 +201,9 @@ button[type="submit"]:hover { display: flex; justify-content: center; align-items: center; + width: 100%; } - .ins_ul { list-style-type: none; padding-left: 0; @@ -206,9 +213,18 @@ button[type="submit"]:hover { text-align: center; color: black; font-weight: bold; + width: 100%; } -/* Estilos para los elementos de la lista de instrucciones */ +.instructions_container { + padding: 20px; + background-color: #f0f0f0; + border-radius: 5px; + width: 100%; + +} + + .ins_ul li { margin-bottom: 5px; color: #000; /* Color de texto negro */ @@ -218,16 +234,19 @@ button[type="submit"]:hover { } -.instructions_container { - padding: 20px; - background-color: #f0f0f0; - border-radius: 5px; -} /*---------------------------Home---------------------------*/ /* Transitions aren't quite as smooth on firefox */ + .general { + display: flex; + justify-content: center; /* Centrar horizontalmente */ + align-items: center; /* Centrar verticalmente */ + height: 100vh; /* Toma el 100% del alto de la ventana */ + } + + :root { --gradient: conic-gradient( from 240deg at 50% 50%, @@ -244,6 +263,8 @@ button[type="submit"]:hover { #9f97ff, #c285ff ); + overflow-y: auto; /* Permitir desplazamiento vertical */ + } * @@ -266,7 +287,7 @@ body { align-items: center; justify-content: center; width: 100%; - height: 100vh; + min-height: 100vh; /* Cambia height a min-height para permitir el desplazamiento si es necesario */ overflow: hidden; margin: 0; font-size: 100%; @@ -275,12 +296,14 @@ body { backface-visibility: hidden; } + .input-home { display: none; } #welcomeMessage { - font-size: 130%; + width: 100%; + max-width: 600px; } #welcomeMessage @@ -528,7 +551,8 @@ svg { #toggleOpen:checked ~ #welcomeMessage { - font-size: 100%; + font-size: 100%; + } #toggleOpen:checked From 0ed799ae5a5bf4d1119a7f185a6694b5b0762a92 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sat, 23 Mar 2024 22:13:50 +0100 Subject: [PATCH 09/66] Added MockUp because Docker is giving weird problems --- .../questionView/QuestionGenerator.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/questionView/QuestionGenerator.js b/webapp/src/components/questionView/QuestionGenerator.js index 27efaf9c..4e249cdb 100644 --- a/webapp/src/components/questionView/QuestionGenerator.js +++ b/webapp/src/components/questionView/QuestionGenerator.js @@ -9,8 +9,23 @@ class QuestionGenerator{ async generateQuestions() { try { - const response = await fetch(this.apiUrl); - const receivedQuestions = await response.json(); + //const response = await fetch(this.apiUrl); + //const receivedQuestions = await response.json(); + + //Mockup + const receivedQuestions = JSON.parse('{"0":{"question":"¿Cuál es la población de Oviedo?","answers":["225089","191325","220587","121548"]},'+ + '"1":{"question":"¿Cuál es la población de Gijón?","answers":["275274","159658","233982","305554"]},'+ + '"2":{"question":"¿Cuál es la población de Avilés?","answers":["82568","115595","41284","122200"]},'+ + '"3":{"question":"¿Cuál es la capital de Asturias?","answers":["Ciudad de Oviedo","a","b","c"]},'+ + '"4":{"question":"¿Cuál es la capital de España?","answers":["Madrid","a","b","c"]},'+ + '"5":{"question":"¿Cuál es la capital de Turquía?","answers":["Ankara","a","b","c"]},'+ + '"6":{"question":"¿Cuál es el área (km cuadrados) de España?","answers":["505990","a","b","c"]},'+ + '"7":{"question":"¿Cuál es el área (km cuadrados) de Gijón?","answers":["184.31","a","b","c"]},'+ + '"8":{"question":"¿Cuál es el área (km cuadrados) de Asturias?","answers":["10603.57","a","b","c"]},'+ + '"9":{"question":"¿Cuál es el idioma oficial de España?","answers":["español","a","b","c"]},'+ + '"10":{"question":"¿Cuál es el idioma oficial de Turquía?","answers":["turco","a","b","c"]},'+ + '"11":{"question":"¿Cuál es el idioma oficial de Asturias?","answers":["español","a","b","c"]},'+ + '"12":{"question":"Whats the population of Oviedo?","answers":["225089","216085","285863","243096"]}}') let i = 0; var questions = []; From c59c2d82fa45e5759002477fc67310d1138509d9 Mon Sep 17 00:00:00 2001 From: uo289267 Date: Sun, 24 Mar 2024 18:35:03 +0100 Subject: [PATCH 10/66] Started with viewing answers after respoding --- webapp/package-lock.json | 6 ++ webapp/package.json | 1 + .../src/components/questionView/Question.js | 3 + .../components/questionView/QuestionView.js | 76 ++++++++++++++----- webapp/src/custom.css | 27 ++++++- webapp/src/translations/en/global.json | 3 +- webapp/src/translations/es/global.json | 3 +- 7 files changed, 98 insertions(+), 21 deletions(-) diff --git a/webapp/package-lock.json b/webapp/package-lock.json index ad42295e..edd9e824 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -16,6 +16,7 @@ "@testing-library/user-event": "^14.5.2", "axios": "^1.6.5", "i18n": "^0.15.1", + "jquery": "^3.7.1", "react": "^18.2.0", "react-countdown": "^2.3.5", "react-dom": "^18.2.0", @@ -18351,6 +18352,11 @@ "@sideway/pinpoint": "^2.0.0" } }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/webapp/package.json b/webapp/package.json index f31b2a0c..25caecfe 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -11,6 +11,7 @@ "@testing-library/user-event": "^14.5.2", "axios": "^1.6.5", "i18n": "^0.15.1", + "jquery": "^3.7.1", "react": "^18.2.0", "react-countdown": "^2.3.5", "react-dom": "^18.2.0", diff --git a/webapp/src/components/questionView/Question.js b/webapp/src/components/questionView/Question.js index 0249c2f1..c6dfca13 100644 --- a/webapp/src/components/questionView/Question.js +++ b/webapp/src/components/questionView/Question.js @@ -14,6 +14,9 @@ class Question{ getAnswers() { return this.answers; } + isCorrect(answer){ + return answer===this.correctAnswer; + } } diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index b8240d5c..b6162cd1 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -4,6 +4,7 @@ import "../../custom.css"; import React from "react"; import Countdown from "react-countdown"; import {useTranslation} from "react-i18next"; +import $ from 'jquery'; function QuestionView(){ const questionGenerator = new QuestionGenerator(); @@ -25,8 +26,37 @@ function QuestionView(){ } } + function revealColorsForAnswers(){ + let colorCorrectAnswer='green'; + let colorIncorrectAnswer='red'; + $(document).ready(function() { + $('.answerButton').each(function() { + var dataValue = $(this).data('value'); + if (dataValue === false || dataValue === "false") + $(this).css('background-color', colorIncorrectAnswer); // Cambia el color de fondo del botón actual a rojo + else{ + $(this).css('background-color', colorCorrectAnswer); + } + }); + }); + + } + function setColorsBackToNormal() { + let colorOriginal = '#9f97ff'; + $(document).ready(function() { + $('.answerButton').each(function() { + $(this).css('background-color', colorOriginal); + }); + }); + } + function handleClick(){ - setnumQuestion(numQuestion + 1); + revealColorsForAnswers(); + setTimeout(function() { + setColorsBackToNormal(); + setnumQuestion(numQuestion + 1); + }, 1000); + } useEffect(() => {generateQuestions(numQuestion)}, []); @@ -35,15 +65,16 @@ function QuestionView(){
{/*Nav*/} {numQuestion >= 0 ? - : + :

Please Wait a bit...

}
); } function QuestionComponent({questions, numQuestion, handleClick, t}){ + const renderer = ({seconds, completed }) => { if (completed) { - + handleClick(); return {t("questionView.end_countdown")}; // Rendered when countdown completes } else { return {seconds} {t("questionView.seconds")}; // Render countdown @@ -52,26 +83,35 @@ function QuestionComponent({questions, numQuestion, handleClick, t}){ return ( <> -
-

{questions[numQuestion].getQuestion()}

-
- -
-
-
- {questions[numQuestion].getAnswers().map((item, index) => ( - - ))} - -
-

{t("questionView.question_counter")} {numQuestion}

+ {numQuestion < questions.length ? ( + <> +
+

{questions[numQuestion].getQuestion()}

+
+ +
+
+
+ {questions[numQuestion].getAnswers().map((item, index) => ( + + ))} +
+

{t("questionView.question_counter")} {numQuestion}

+ + ) : ( + <> +

{t("questionView.finished_game")}

+

500 Points

+ + )} ); + } -function Answer({text, onClick}){ +function Answer({text, onClick, dataValue}){ return ( - + ); } diff --git a/webapp/src/custom.css b/webapp/src/custom.css index 82c35fd5..26cf205f 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -1093,7 +1093,32 @@ svg { font-size: 65%; } } - +/*------------------------------Question--------------------------------------------*/ +.answerPanel { + display: flex; + flex-wrap: wrap; + display: grid; + grid-template-columns: repeat(2, 1fr); /* Divide en dos columnas de igual tamaño */ + gap: 5px; /* Ajusta el espacio entre los botones */ +} +.answerPanel button { + flex: 1 1 50%; /* Divide los botones en dos columnas */ + margin: 5px; /* Ajusta el margen entre los botones según sea necesario */ +} + +.answerButton{ + margin-right: 10px; + background: #9f97ff; + border: none; + outline: none; + border-radius: 40px; + box-shadow: 0 0 10px #9f97ff; + cursor:pointer; + font-size: 16px; + color: white; + font-weight: 700; + margin: 0.5em; +} diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json index 0a2bd647..9d482da3 100644 --- a/webapp/src/translations/en/global.json +++ b/webapp/src/translations/en/global.json @@ -55,7 +55,8 @@ "questionView":{ "seconds":"seconds", "question_counter":"Question counter :", - "end_countdown":"Time's up!" + "end_countdown":"Time's up!", + "finished_game":"The game has finished!" } } diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json index 50888b37..79014696 100644 --- a/webapp/src/translations/es/global.json +++ b/webapp/src/translations/es/global.json @@ -59,7 +59,8 @@ },"questionView":{ "seconds":"segundos", "question_counter":"Número de pregunta : ", - "end_countdown":"¡Se acabó el tiempo!" + "end_countdown":"¡Se acabó el tiempo!", + "finished_game":"¡El juego se ha terminado!" } From 1707058cec634f3f4fce6d26ffee818eaa2ce79b Mon Sep 17 00:00:00 2001 From: uo289267 Date: Tue, 26 Mar 2024 18:45:41 +0100 Subject: [PATCH 11/66] Added historical page and route and started with the elements inside it --- webapp/src/App.js | 2 ++ webapp/src/components/GameMenu/GameMenu.js | 10 +++--- .../HistoricalData/HistoricalView.js | 31 +++++++++++++++++++ .../components/questionView/QuestionView.js | 10 +++--- webapp/src/custom.css | 20 ++++++++++++ 5 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 webapp/src/components/HistoricalData/HistoricalView.js diff --git a/webapp/src/App.js b/webapp/src/App.js index b0287a21..17434c1a 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -9,6 +9,7 @@ import Instructions from './components/Instructions'; import Container from '@mui/material/Container'; import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; import './custom.css'; +import HistoricalView from './components/HistoricalData/HistoricalView'; function App() { return ( @@ -24,6 +25,7 @@ function App() { } /> } /> } /> + } />
diff --git a/webapp/src/components/GameMenu/GameMenu.js b/webapp/src/components/GameMenu/GameMenu.js index a84fe5ea..332a8f25 100644 --- a/webapp/src/components/GameMenu/GameMenu.js +++ b/webapp/src/components/GameMenu/GameMenu.js @@ -15,11 +15,11 @@ export default function GameMenu() { } function ButtonHistoricalData({ t }) { - function handleClick() { - //ir a la vista de historical data - alert("Historical Data"); - } - return ; + return ( + +

{t("gameMenu.history_button")}

+ + ); } function ButtonNewGame({ t }) { diff --git a/webapp/src/components/HistoricalData/HistoricalView.js b/webapp/src/components/HistoricalData/HistoricalView.js new file mode 100644 index 00000000..b520f4cb --- /dev/null +++ b/webapp/src/components/HistoricalData/HistoricalView.js @@ -0,0 +1,31 @@ +import React, { useState } from 'react' +export default function HistoricalView() { + return ( +
+ + +
+ ) +} + + +function HistoricalGameElement(){ + function handleClick (){ + setToggle(!toggle); + }; + const [toggle, setToggle] = useState(false); + return ( +
+ + +
    +
  • An item
  • +
  • A second item
  • +
  • A third item
  • +
  • A fourth item
  • +
  • And a fifth one
  • +
+ +
+ ); +} \ No newline at end of file diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index b6162cd1..440ccebb 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -2,16 +2,18 @@ import QuestionGenerator from './QuestionGenerator'; import { useEffect, useState } from 'react'; import "../../custom.css"; import React from "react"; -import Countdown from "react-countdown"; +import Countdown from 'react-countdown'; import {useTranslation} from "react-i18next"; import $ from 'jquery'; function QuestionView(){ const questionGenerator = new QuestionGenerator(); + const [numQuestion, setnumQuestion] = useState(-1); const [questions, setQuestions] = useState([]); const[t, i18n] = useTranslation("global"); + const generateQuestions = async (numQuestion) => { if (numQuestion < 0) { try { @@ -74,7 +76,6 @@ function QuestionComponent({questions, numQuestion, handleClick, t}){ const renderer = ({seconds, completed }) => { if (completed) { - handleClick(); return {t("questionView.end_countdown")}; // Rendered when countdown completes } else { return {seconds} {t("questionView.seconds")}; // Render countdown @@ -87,8 +88,8 @@ function QuestionComponent({questions, numQuestion, handleClick, t}){ <>

{questions[numQuestion].getQuestion()}

-
- +
+
@@ -102,6 +103,7 @@ function QuestionComponent({questions, numQuestion, handleClick, t}){ <>

{t("questionView.finished_game")}

500 Points

+ )} diff --git a/webapp/src/custom.css b/webapp/src/custom.css index 26cf205f..84be6bbc 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -1122,3 +1122,23 @@ svg { margin: 0.5em; } +/*------------------------------Historical--------------------------------------------*/ +.historicalButton{ + color:white; + width:50em; + height:5em; + font-size: 0.85em; + border: 3px ridge #149CEA; + background-color: transparent; + border-radius: 0.3em; + font-size: 1.5em; + font-weight: bold; + cursor: pointer; +} +.centered-div { + display: block; + position: fixed; + /* Center horizontally */ + left: 50%; + transform: translateX(-50%); +} From 5c3f676f241f09a290545df2d5e226238f8709df Mon Sep 17 00:00:00 2001 From: uo289267 Date: Wed, 27 Mar 2024 12:30:23 +0100 Subject: [PATCH 12/66] Historical individual elements created --- .../HistoricalData/HistoricalView.js | 11 ++++--- webapp/src/custom.css | 32 +++++++++++++------ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/webapp/src/components/HistoricalData/HistoricalView.js b/webapp/src/components/HistoricalData/HistoricalView.js index b520f4cb..a65b79ca 100644 --- a/webapp/src/components/HistoricalData/HistoricalView.js +++ b/webapp/src/components/HistoricalData/HistoricalView.js @@ -1,8 +1,11 @@ import React, { useState } from 'react' export default function HistoricalView() { return ( -
+
+
+ +
) @@ -19,10 +22,10 @@ function HistoricalGameElement(){
    -
  • An item
  • +
  • An item
  • A second item
  • -
  • A third item
  • -
  • A fourth item
  • +
  • A third item
  • +
  • A fourth item
  • And a fifth one
diff --git a/webapp/src/custom.css b/webapp/src/custom.css index 84be6bbc..73c7d0cc 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -1123,22 +1123,34 @@ svg { } /*------------------------------Historical--------------------------------------------*/ -.historicalButton{ - color:white; - width:50em; - height:5em; - font-size: 0.85em; +/* Estilos para los botones */ +.historicalButton { + color: white; + width: 50em; + height: 5em; + font-size: 1.5em; /* Font size ajustado a 1.5em */ border: 3px ridge #149CEA; background-color: transparent; border-radius: 0.3em; - font-size: 1.5em; font-weight: bold; cursor: pointer; + margin-bottom: 0.2em; /* Agrega espacio entre los botones */ } -.centered-div { - display: block; - position: fixed; - /* Center horizontally */ + +/* Estilos para los divs dentro de centered-div */ +.centered-div > div { + display: flex; + flex-direction: column; /* Mostrar los botones en una columna */ + align-items: center; /* Centrar horizontalmente los botones */ + position: fixed; + /* Center horizontalmente */ left: 50%; transform: translateX(-50%); } + +/* Estilos para el contenedor globalHistoricalView */ +.globalHistoricalView { + display: flex; + flex-direction: column; +} + From fd3bd705ae65aadb1201806f2dfb52c43356250c Mon Sep 17 00:00:00 2001 From: uo289267 Date: Wed, 27 Mar 2024 14:32:27 +0100 Subject: [PATCH 13/66] Record creation started --- .../HistoricalData/HistoricalView.js | 2 - .../questionView/CreationHistoricalRecord | 58 +++++++++++++++++++ .../src/components/questionView/Question.js | 3 + .../questionView/QuestionGenerator.js | 1 - .../components/questionView/QuestionView.js | 17 ++++-- webapp/src/custom.css | 2 + 6 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 webapp/src/components/questionView/CreationHistoricalRecord diff --git a/webapp/src/components/HistoricalData/HistoricalView.js b/webapp/src/components/HistoricalData/HistoricalView.js index a65b79ca..626d53e0 100644 --- a/webapp/src/components/HistoricalData/HistoricalView.js +++ b/webapp/src/components/HistoricalData/HistoricalView.js @@ -3,9 +3,7 @@ export default function HistoricalView() { return (
-
-
) diff --git a/webapp/src/components/questionView/CreationHistoricalRecord b/webapp/src/components/questionView/CreationHistoricalRecord new file mode 100644 index 00000000..a0afea5e --- /dev/null +++ b/webapp/src/components/questionView/CreationHistoricalRecord @@ -0,0 +1,58 @@ +class CreationHistoricalRecord{ + + constructor() { + this.record = { + user: "a", + game: { + questions: [] + } + }; + } + + addQuestion(statement, answers, answerGiven, correctAnswer) { + this.record.game.questions.push({ + question: statement, + answers: answers, + answerGiven: answerGiven, + correctAnswer: correctAnswer + }); + } + + setPoints(points) { + this.record.game.points = points; + } + + setDate(date) { + this.record.game.date = date; + } + + getRecord() { + return this.record; + } + +} +export default CreationHistoricalRecord; +/* +// Ejemplo de uso: +const userId = "userIdentifier"; +const record = new CreationHistoricalRecord(userId); + +record.addQuestion( + "¿Cuál es el río más largo del mundo?", + ["Nilo", "Amazonas", "Yangtsé", "Misisipi"], + "Amazonas", + "Amazonas" +); + +record.addQuestion( + "¿Cuál es el elemento más abundante en la corteza terrestre?", + ["Hierro", "Oxígeno", "Silicio", "Aluminio"], + "Oxígeno", + "Oxígeno" +); + +record.setPoints(2500); +record.setDate("02/02/24"); + +const recordRecord = record.getRecord(); +console.log(recordRecord);*/ \ No newline at end of file diff --git a/webapp/src/components/questionView/Question.js b/webapp/src/components/questionView/Question.js index c6dfca13..37a6d6f3 100644 --- a/webapp/src/components/questionView/Question.js +++ b/webapp/src/components/questionView/Question.js @@ -14,6 +14,9 @@ class Question{ getAnswers() { return this.answers; } + getCorrectAnswer(){ + return this.correctAnswer; + } isCorrect(answer){ return answer===this.correctAnswer; } diff --git a/webapp/src/components/questionView/QuestionGenerator.js b/webapp/src/components/questionView/QuestionGenerator.js index 4e249cdb..e225c73a 100644 --- a/webapp/src/components/questionView/QuestionGenerator.js +++ b/webapp/src/components/questionView/QuestionGenerator.js @@ -1,5 +1,4 @@ import Question from './Question'; -import "../../custom.css"; class QuestionGenerator{ constructor(){ diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 440ccebb..5ddac51b 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -1,4 +1,5 @@ import QuestionGenerator from './QuestionGenerator'; +import CreationHistoricalRecord from './CreationHistoricalRecord'; import { useEffect, useState } from 'react'; import "../../custom.css"; import React from "react"; @@ -8,10 +9,10 @@ import $ from 'jquery'; function QuestionView(){ const questionGenerator = new QuestionGenerator(); - + const creationHistoricalRecord = new CreationHistoricalRecord(); const [numQuestion, setnumQuestion] = useState(-1); const [questions, setQuestions] = useState([]); - const[t, i18n] = useTranslation("global"); + const[t] = useTranslation("global"); const generateQuestions = async (numQuestion) => { @@ -52,7 +53,13 @@ function QuestionView(){ }); } - function handleClick(){ + function handleClick(item){ + //addQuestion(statement, answers, answerGiven, correctAnswer) { + creationHistoricalRecord.addQuestion(questions[numQuestion].getQuestion(), + questions[numQuestion].getAnswers(), + item, + questions[numQuestion].getCorrectAnswer()); + console.log(creationHistoricalRecord.getRecord()); revealColorsForAnswers(); setTimeout(function() { setColorsBackToNormal(); @@ -89,12 +96,12 @@ function QuestionComponent({questions, numQuestion, handleClick, t}){

{questions[numQuestion].getQuestion()}

- +
{questions[numQuestion].getAnswers().map((item, index) => ( - + ))}

{t("questionView.question_counter")} {numQuestion}

diff --git a/webapp/src/custom.css b/webapp/src/custom.css index 73c7d0cc..6416c5ce 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -1152,5 +1152,7 @@ svg { .globalHistoricalView { display: flex; flex-direction: column; + align-self: center; + margin:auto; } From fc9b51a9342f6f3ff585edf9140f8fc0d424f53e Mon Sep 17 00:00:00 2001 From: uo289267 Date: Wed, 27 Mar 2024 18:03:41 +0100 Subject: [PATCH 14/66] Historical Records are now functional but not finished --- ...icalRecord => CreationHistoricalRecord.js} | 16 ++++++++------- .../components/questionView/QuestionView.js | 20 ++++++++++--------- 2 files changed, 20 insertions(+), 16 deletions(-) rename webapp/src/components/questionView/{CreationHistoricalRecord => CreationHistoricalRecord.js} (72%) diff --git a/webapp/src/components/questionView/CreationHistoricalRecord b/webapp/src/components/questionView/CreationHistoricalRecord.js similarity index 72% rename from webapp/src/components/questionView/CreationHistoricalRecord rename to webapp/src/components/questionView/CreationHistoricalRecord.js index a0afea5e..d89f1209 100644 --- a/webapp/src/components/questionView/CreationHistoricalRecord +++ b/webapp/src/components/questionView/CreationHistoricalRecord.js @@ -9,13 +9,15 @@ class CreationHistoricalRecord{ }; } - addQuestion(statement, answers, answerGiven, correctAnswer) { - this.record.game.questions.push({ - question: statement, - answers: answers, - answerGiven: answerGiven, - correctAnswer: correctAnswer - }); + addQuestion(statement, answers, answerGiven, correctAnswer, numQuestion) { + if(this.record.game.questions.length == numQuestion){ + this.record.game.questions.push({ + question: statement, + answers: answers, + answerGiven: answerGiven, + correctAnswer: correctAnswer + }); + } } setPoints(points) { diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 5ddac51b..15b4283f 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -7,9 +7,11 @@ import Countdown from 'react-countdown'; import {useTranslation} from "react-i18next"; import $ from 'jquery'; + +const creationHistoricalRecord = new CreationHistoricalRecord(); +const questionGenerator = new QuestionGenerator(); + function QuestionView(){ - const questionGenerator = new QuestionGenerator(); - const creationHistoricalRecord = new CreationHistoricalRecord(); const [numQuestion, setnumQuestion] = useState(-1); const [questions, setQuestions] = useState([]); const[t] = useTranslation("global"); @@ -52,13 +54,13 @@ function QuestionView(){ }); }); } - - function handleClick(item){ + function handleClick(text){ //addQuestion(statement, answers, answerGiven, correctAnswer) { creationHistoricalRecord.addQuestion(questions[numQuestion].getQuestion(), - questions[numQuestion].getAnswers(), - item, - questions[numQuestion].getCorrectAnswer()); + questions[numQuestion].getAnswers(), + text, + questions[numQuestion].getCorrectAnswer(), + numQuestion); console.log(creationHistoricalRecord.getRecord()); revealColorsForAnswers(); setTimeout(function() { @@ -96,12 +98,12 @@ function QuestionComponent({questions, numQuestion, handleClick, t}){

{questions[numQuestion].getQuestion()}

- +
{questions[numQuestion].getAnswers().map((item, index) => ( - + ))}

{t("questionView.question_counter")} {numQuestion}

From e094e462ae82de8e5a9cb18501c316247e47e82c Mon Sep 17 00:00:00 2001 From: uo289267 Date: Thu, 28 Mar 2024 18:46:59 +0100 Subject: [PATCH 15/66] Added simple point system and finalized record creation for games --- .../components/questionView/QuestionView.js | 29 +++++++++++++++---- webapp/src/translations/en/global.json | 3 +- webapp/src/translations/es/global.json | 3 +- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 15b4283f..4e39b5df 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -10,7 +10,7 @@ import $ from 'jquery'; const creationHistoricalRecord = new CreationHistoricalRecord(); const questionGenerator = new QuestionGenerator(); - +var points = 0; function QuestionView(){ const [numQuestion, setnumQuestion] = useState(-1); const [questions, setQuestions] = useState([]); @@ -54,17 +54,32 @@ function QuestionView(){ }); }); } + function computePointsForQuestion(correctAnswer, answerGiven){ + if(answerGiven==correctAnswer){ + points+=100; + }else if(points-50>=0){ + points-=50; + }else{ + points = 0; + } + } function handleClick(text){ - //addQuestion(statement, answers, answerGiven, correctAnswer) { + //create the record to record the response creationHistoricalRecord.addQuestion(questions[numQuestion].getQuestion(), questions[numQuestion].getAnswers(), text, questions[numQuestion].getCorrectAnswer(), numQuestion); + //compute the points for the answer given + computePointsForQuestion(questions[numQuestion].getCorrectAnswer(), text); + console.log(creationHistoricalRecord.getRecord()); + //reveal answer to user for 1 sec revealColorsForAnswers(); setTimeout(function() { + //after one second set colors back to normal setColorsBackToNormal(); + //sum one to the number of questions setnumQuestion(numQuestion + 1); }, 1000); @@ -76,12 +91,12 @@ function QuestionView(){
{/*Nav*/} {numQuestion >= 0 ? - : + :

Please Wait a bit...

}
); } -function QuestionComponent({questions, numQuestion, handleClick, t}){ +function QuestionComponent({questions, numQuestion, handleClick, t, points}){ const renderer = ({seconds, completed }) => { if (completed) { @@ -110,9 +125,11 @@ function QuestionComponent({questions, numQuestion, handleClick, t}){ ) : ( <> + {creationHistoricalRecord.setDate(Date.now())} + {creationHistoricalRecord.setPoints(points)} + {console.log(creationHistoricalRecord.getRecord())}

{t("questionView.finished_game")}

-

500 Points

- +

{points} {t("questionView.point")}

)} diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json index 9d482da3..511a89c1 100644 --- a/webapp/src/translations/en/global.json +++ b/webapp/src/translations/en/global.json @@ -56,7 +56,8 @@ "seconds":"seconds", "question_counter":"Question counter :", "end_countdown":"Time's up!", - "finished_game":"The game has finished!" + "finished_game":"The game has finished!", + "point":"Points" } } diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json index 79014696..21c8f6af 100644 --- a/webapp/src/translations/es/global.json +++ b/webapp/src/translations/es/global.json @@ -60,7 +60,8 @@ "seconds":"segundos", "question_counter":"Número de pregunta : ", "end_countdown":"¡Se acabó el tiempo!", - "finished_game":"¡El juego se ha terminado!" + "finished_game":"¡El juego se ha terminado!", + "point":"Puntos" } From f279ade3dbf2ddab7768a5189a20c88258301094 Mon Sep 17 00:00:00 2001 From: uo289267 Date: Thu, 28 Mar 2024 21:12:37 +0100 Subject: [PATCH 16/66] Historical View with data from previous games completed --- .../HistoricalData/HistoricalView.js | 63 +++++++++---- .../HistoricalData/HistoryRecordRetriever.js | 89 +++++++++++++++++++ webapp/src/translations/en/global.json | 4 + webapp/src/translations/es/global.json | 4 + 4 files changed, 142 insertions(+), 18 deletions(-) create mode 100644 webapp/src/components/HistoricalData/HistoryRecordRetriever.js diff --git a/webapp/src/components/HistoricalData/HistoricalView.js b/webapp/src/components/HistoricalData/HistoricalView.js index 626d53e0..cd57787f 100644 --- a/webapp/src/components/HistoricalData/HistoricalView.js +++ b/webapp/src/components/HistoricalData/HistoricalView.js @@ -1,32 +1,59 @@ -import React, { useState } from 'react' +import React, {useEffect, useState } from 'react'; +import {useTranslation} from "react-i18next"; +import HistoryRecordRetriever from './HistoryRecordRetriever'; +const retriever = new HistoryRecordRetriever(); + + export default function HistoricalView() { - return ( -
- - - -
- ) + const [records, setRecords]= useState([]); + const[t] = useTranslation("global"); + + const getRecords = async ()=>{ + try { + var jsonRecords = await retriever.getRecords(); // Obtener el JSON de registros + var recordsArray = jsonRecords['games']; + setRecords(recordsArray); + } catch (error) { + //Como hacer que funcione esto + console.log(error.response); + } + } + useEffect(() => {getRecords()}, []); + return ( +
+ {records.map((record, index) => ( + + ))} +
+ ) } -function HistoricalGameElement(){ +function HistoricalGameElement({record,t}){ + const [toggle, setToggle] = useState(false); + function handleClick (){ setToggle(!toggle); }; - const [toggle, setToggle] = useState(false); + return (
- - +
    -
  • An item
  • -
  • A second item
  • -
  • A third item
  • -
  • A fourth item
  • -
  • And a fifth one
  • + {record.questions.map((question, index) => (
  • +

    {question.question}

    +
      + {question.answers.map((answer, answerIndex) => ( +
    • + {answer} + {question.answerGiven === answer && " 👈 "} + {question.correctAnswer === answer && " ✅ "} +
    • + ))} +
    +
  • + ))}
-
); } \ No newline at end of file diff --git a/webapp/src/components/HistoricalData/HistoryRecordRetriever.js b/webapp/src/components/HistoricalData/HistoryRecordRetriever.js new file mode 100644 index 00000000..2ca7715b --- /dev/null +++ b/webapp/src/components/HistoricalData/HistoryRecordRetriever.js @@ -0,0 +1,89 @@ + +class HistoryRecordRetriever{ + + constructor(){ + this.apiUrl = (process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000') + "/questions"; + + } + + async getRecords() { + try { + //const response = await fetch(this.apiUrl); + //const receivedQuestions = await response.json(); + + //Mockup + const receivedRecords = { + "userIdentification": "prob email or username", + "games": [ + { + "questions": [ + { + "question": "¿Cuál es la capital de Francia?", + "answers": ["Madrid", "París", "Londres", "Roma"], + "answerGiven": "París", + "correctAnswer": "París" + }, + { + "question": "¿En qué año comenzó la Segunda Guerra Mundial?", + "answers": ["1939", "1945", "1914", "1941"], + "answerGiven": "1939", + "correctAnswer": "1939" + }, + { + "question": "¿Quién escribió 'Don Quijote de la Mancha'?", + "answers": ["Miguel de Cervantes", "Gabriel García Márquez", "Federico García Lorca", "Jorge Luis Borges"], + "answerGiven": "Miguel de Cervantes", + "correctAnswer": "Miguel de Cervantes" + } + ], + "points": 3000, + "date": new Date("01/02/24") + }, + { + "questions": [ + { + "question": "¿Cuál es el río más largo del mundo?", + "answers": ["Nilo", "Amazonas", "Yangtsé", "Misisipi"], + "answerGiven": "no-answer", + "correctAnswer": "Amazonas" + }, + { + "question": "¿Cuál es el elemento más abundante en la corteza terrestre?", + "answers": ["Hierro", "Oxígeno", "Silicio", "Aluminio"], + "answerGiven": "Oxígeno", + "correctAnswer": "Oxígeno" + } + ], + "points": 2500, + "date": new Date("02/02/24") + }, + { + "questions": [ + { + "question": "¿Quién pintó la Mona Lisa?", + "answers": ["Leonardo da Vinci", "Pablo Picasso", "Vincent van Gogh", "Rembrandt"], + "answerGiven": "Leonardo da Vinci", + "correctAnswer": "Leonardo da Vinci" + }, + { + "question": "¿Cuál es el planeta más grande del sistema solar?", + "answers": ["Júpiter", "Saturno", "Neptuno", "Urano"], + "answerGiven": "Júpiter", + "correctAnswer": "Saturno" + } + ], + "points": 3500, + "date": new Date("03/02/24") + } + ] + }; + return receivedRecords; + } catch (error) { + throw new Error(error); + } + } + +} + +export default HistoryRecordRetriever; + diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json index 511a89c1..3c2b04e4 100644 --- a/webapp/src/translations/en/global.json +++ b/webapp/src/translations/en/global.json @@ -58,6 +58,10 @@ "end_countdown":"Time's up!", "finished_game":"The game has finished!", "point":"Points" + }, + "historicalView":{ + "game":"Game", + "points":"points" } } diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json index 21c8f6af..4ba9474d 100644 --- a/webapp/src/translations/es/global.json +++ b/webapp/src/translations/es/global.json @@ -62,6 +62,10 @@ "end_countdown":"¡Se acabó el tiempo!", "finished_game":"¡El juego se ha terminado!", "point":"Puntos" + }, + "historicalView":{ + "game":"Partida", + "points":"puntos" } From 07281b29fe5acd397b57387652e5b7f0976fcd11 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Sun, 31 Mar 2024 21:40:24 +0200 Subject: [PATCH 17/66] changed signup logo --- webapp/public/signup.png | Bin 10872 -> 7099 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/webapp/public/signup.png b/webapp/public/signup.png index 60e761bda7fcb4e8f928a9229925479205f4fbc3..77b0bf9411c123d85fc19de844e2b86422dbc494 100644 GIT binary patch literal 7099 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 KniZPRBK{x7%W^mX literal 10872 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 ba(c5(W*=zId=ZDMC Date: Mon, 1 Apr 2024 11:58:04 +0200 Subject: [PATCH 18/66] Changed logo of login, deletes some text bc cant be internationalize and added some transitions --- webapp/public/click2.png | Bin 0 -> 2309 bytes webapp/public/login.png | Bin 9158 -> 1052 bytes .../components/loginAndRegistration/Login.js | 5 ---- webapp/src/custom.css | 25 +++++++++--------- 4 files changed, 12 insertions(+), 18 deletions(-) create mode 100644 webapp/public/click2.png diff --git a/webapp/public/click2.png b/webapp/public/click2.png new file mode 100644 index 0000000000000000000000000000000000000000..fa3b9d28d3cf9912a8941e9d3ec6883e3ad29eb4 GIT binary patch literal 2309 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 literal 9158 zcmd^Fi93|v`#v*9C`*=kUbz?{B(`s_ z$$o_J@FyM#FM`YDnYKB&-~#vW*@1GK<$uEmf`_rWF+$JdmT;+p@LA;KUdKR$#A~o$ zT&>^ZqX;P-+-G8Z;Ed}?PwdIZlXY)xbBBpm=l{`WDV50H#(@@e_#9hW#RqKl`DYsgN zyE}&Dud#c-|03SK#o^tUHM6$0Z7)Lf;oM5Z%ozo zt0gFX&vf#c(e4tLpDpQ(=b^lwN2bYz!W#vK zJ{BBnwEV}^lwo%GP*Kn6u;&Mhd|!Mm^wB4mi3XiVF=hb=$Vc8?jj%MFYLjd+WOu(g zcI?=*8q+HGaZAr#zI=J^g-44~z+l^x zEQ48QV)^Zc=;5zkPoFh}vPb7@E5bPz!=D~Cs#E1ym(jXIPwk$0g)+j~cS5>+idjR8soR)tmsLaF0b1ag1i0SJlvPq>{52d|7pJH z!(Uwt-gH?Y%(CIZwe5qwQDUodMH=H*;;bmyd^cJ1y9Tq9)(>{aIu{(>*O)KLygpLI z;1PF5iI$AVC|xTiYZ$L5P|nRjFNN%7_RfDwnZCSy0`vJio58>C#$zS_RP|U?EycWn z9``jgHm)RKA6 zTdU3qjD^onb+E-vDGH~ma6)E8y#VHugMQ^fjt=K@Cf0r1?)5pxv79qC#4cze4pw}5 z;X!QAvP`#k3;q3QlqynSf!d6Vx&s=&1vcw>TvnYn{ysC)7Z<#3s?8?-%&&XV7UHJy zwwk!MHQ0Q1UtO`u{m0u&WC>HsxhM8{uKmZ7T~1T^ym{KHB$7ITqHx`yX^hplv9kY- z5Yb?(22N0;WYftH8OF)4_2RwNRvVo?vmzlcL5XjwS;D-=w636vtUDPv@P0Or`Mie% zYbQ+=+1y}=f~wl>-3)!dzVuX$R9ku}&97oMp>*{1P`6g(RVfrQ`uU)r!WPd@4=1W+ zV&2=@yG(Tr3ecr%WH!GuL?PY-?{9@S!?_ZA$|o+1R3`2C_uqeq;OSfec6VTlM~#%X z4lX_`A(}fm)Zu5rsxhL9#5lmAmo>YyeTt*3tn7ACxl=&%Ul-0AX>AX|!L5OQ)X49H&`!sI4H*Acbw=-Hiu&cBgiDU99+>;fuHcBW5nH6|XkcYcKTa znvFA>J6=0CHI%o+)Jh#svOLhijo)8_(>ZM zMr=Ma{_P59@^@gC4JSV&A#YSgk~Z|L$h8a*E0d}>lwf+QHOq3$8Ga;_GTwC)QiKvt z@JqV6i9=EK(YqNH;i_M`)QPRfKO7pt(5h@Myj?BXa_C_Gp*O*+!zVu;sgd#8g&t~@ z^zo;={P??4+-(cKxSjbPnam#zt{f_Fw>uavn{-ZeUqz}eoHhYVqgm#v>iwUUJrt^! zVowf#@kloueh_E$b(7hPOxN%%>P(o?@#0V(dg9335pe%=imjn|4?DT&lV=YD6! z3D@N8tr!d*dDU@uAeH=3bvCLhWz!Lh}0G2AYNr*x41jq_{gLYr44l zw-T9g>AcCT2SosPv?$Ma<@3{Br5jw!w%y!w$wpU%e&ZqqRR8vLb(fl@ zI{%=D%yM=w$9ILh^H^`Ws@_~Qw-rEs*&YbSd1!~tZADbRH8#zkEiF!H^4G_{yIKU+ zdx(c1zZLG?)sagor59QVro-7TG)>m**>0x2zNG%~%a@Z)T7oRIj$D`YT(?TzSFNVU zYzD2eP2k*PHC+7pLEYb))D(X}i4Gg8FcY#*Rc`6%+&?MqZC_uVShd0FO~@S z84bsRwd#BLmt0PN>5qlc4@_}RVRP0YyRFl}lLXc6a*nT#k}GPp&@WerqTKajRLtu` z*I3*ric&8SD2o$_xWzSBO;__*!Tp8-&X%z!VXRiARVo{6GE& zU4DU7XuU7?=9Q{x;1Q|zG#ndtwN@V_oQa5qSA|ABucw5}Q@1$EWy;wcIB=jH=tXd~ zjLu$!m=6B_{>ZY*a=d~|jA7{3h!6qQe;?U{gkl+>WW^mZ}3+D=v1fy4n z{<_f<%$SeV>hT`=`YMdwc_gk}*^K%Cdm>?IswPTIzY@UWMD-^X*cR9R5BGKo=>T;3 zIGm4_LP+gPP=|}#>%r`&&1Q#58a@eEG++Pvgz+S)Oe-aLiCy7ylO+?WCvx?|Z7M3= z02DW2_}Q|p@9IaYh?f}xxcc=Vj#uLn+|xcE#^CgtQavAFJgsc%^TD{8-!Hm2|&j}pIy6l&HEI7 zaks`2uX`VE$J>4AAq830tyfncDu)@BR&rU592%=$)d!M6q3x>{NGQ>QoZ%NO-j>-H zxFocngw~m0Q4s;8Ry<{!|BtF&S7cv_HM+Il+Zo-_VleUEx;%91wfgLwlf$Bb_lBs- zozv*XD{yPMYv{HLm{QQHuUzS|3eG5dk;H0)KYPe?A5F(9`4OJb92P9?7>ij?*8B5T z+JiRpJ$j^Of9(4^`fN_Sv0gE48A%?KqVxiy830X8wU*{(q0i*P(URt*qht57= z*3s(X*A(>+4wPk@r$vk`AEys5MOC5wtUA6atUPy{=s68(RMo+R0Zm;>Plv1g{erf) zua0c(>|Ex%a0W6dNh0W*TSC^KNB+$8UmqXTmOpcPHMh=e;b}g+K5go$TWrhJb=rOG zpf@k1iN)A^?>A&wimu%9>(gKC6AYjr3iFcz%TgZW2kbEh%^B7~5s?mi5@(4t?jPyg zin+mb*=5UYf#2;RAd~f9xX}_sUg^tg+{C8Jxk}o#CgP_xp!{@b(AQCK9%Tojn0WK5 zlA&?+fCN_`ha~fX)hVNlsxRDgQ-t~PL$gli&Pad2%VAf{d#IbIBpSSd}!I$0bFX&8_=nuzEIM<;{|%n{`-kk1kl zBE=cZe7lgv8?>)n>Gz*Idv*A0c1CsEIXd2I;Cvd8@RvmKLh!D+B53ceCgR=;h%N&! z_fi<`y#ybjQ<+ZqD1z!X!I%;-c07!^9FGFt4oEPiaYzr|i4}|J8ZTxAX7?hBEIfTy z8Ieq(QzK~hh&6wtWxQp=D$e&{2w!H_zVL|KF0o zpS@ME_9CcL6h7xlq5MnGpNk4QBn{JfZGk8oV4NK!lpzb>-&=~Tc0#*&Ve}XW&mAWq z?~6^ubtZVEQ#BwV153=nu5fsVs1rhq?;v^}?Bu3(+1V_)#1nnBaYP;8?qcQj*&8+-NSqi^;wigE{!} z_#aP)Yf)(LIaFuq>BpmNPk7;jDG*bPG^E3uUKGJ{gQV;F<3_(SQk#fBY{N;;lV4Bd zjc5lj>xRS)CqD#dnWvrJf96TXY`#(`@Ox8C=L(6f+~WB*MzZqBTgQvXlXtJ||0`5rlOVaEIC8q@}+CK;9FnqLZqIp8q@-8<~Yr{69nV8QIV0$*W zygoIgB{-9MU1`rX*Fx_vNmM5*07z7T%Vz4T856%{ABBAs)N>9VJQW2fk2zxnh0NL(2BVL+)i<;RhXQO zh6V)mQB6}*(+?I{pSn2TT7Rr;;^4yf*4yD^6UAZl!4LOpxIJ7^nXT=t%7NTiA~~WHh*z#? z>(x}F@X(*1K7G=yx#5($`Pe^yqk2I%26(0U6wZz(m}<&(XBc021qva-y(x7=R|IE- z|M7Lu5WA@J@RdhYy_LY{@TAH|3b^(?M4Jds7h|=3WyE|CRfN>%jHl=A>EG(|15b3YZ|P$5_O{*ViGZEX7go0VeKLMC;b#k(V(6 zMFNs;xP&s63ZqWKKElIUfgOsd(;1@EI^8IIR0c?ZF#(bt74h`5Du{H&1jXk8jyOu;IzVB2Dxx}7K&g!2 zvED?uWeLa?BaB$kkvw!%u@uE0fhIzD-~@O&;M?9y!sydlAVrF3?-fM9aS4$ygry6k z01Q#UyXXcCl|rX)I=0103R0o_`QGQ=fuluQ7xBhZlumIow}wI4q*a`G9hJN(A?iXt=UE1*9BO-Pot5dYl5zk3{WIK|Kh1cG zIK~e?8Axk|O%Fei)pRa4O~E^=AUZ$(^DTOIcJ_UbyCDPPT7m_@z1*am3EXWR9(Ztb zUbwATXg9U}M~srn&pETIpXsy;pTA%F-5Aowfd=xHjlu}Xp$iGxxROu{$`#oSMk4>A zL587|#j49a@Cz>F0(qgtGJlv=@i=4rGk?2TY1&MNc4!d{`NHS>xm_`stCcoNO97Zb4#cpx??Z5SieCx<(q*XnwAo-}vJzL}7a&;n_T5&ZK`a0JFG z6%oBD;kHOIaMK770?{SZC%a#t`n~xl%y_J@#fZbz`^!C>K0iNFTWK_2CE!AvA99m8 z4x+G&8dAPJXmD~6_RaE1FPCkRJ0E?FRC^hgxH{f>Uj+MXcd@^Hl;>{qbffY>PtV_J z)WuI6FyMEMnC+imzQL*O^en4ixju*oj_9BA^69TbPnhZ7^KfcXNNp)7i6-U$iop^> zJU$u7r6Www4s&O{ddouYka;tG3hURezg+aiJ#E)WR}qa3&JLGxRGzoqdowN`k3%_@ zQ&9|0SOxp0+j=kTr!pBN4Ssa!)S#`3u8r%-H-bA$Pmj!bm}cv; z=cpySf#RP2u}}5RmeQOY@6vq2Ru!P1TTcD@a1cN0TVnHA5{Kf?FH^VMLexJ!oL6(|#r&T*ngQe)t_Mde zazVIZo7n7tv3-z!SUUB4{X4S}l;l4!#Y31`S*>*>Ay2~2)^=H>nm0)7y62cf|EEDc zZx~Du8#}wtbKs5kZuqM&uSI5Yj`in;vvHu|LA=UtbnV_Os+~K>=vlA<5arr4FcSBH zZ-F@s(QB|S|L0XZ<~{5+29?}#k^1hLOKG9?3VeuH&+8zu8m+#STaM@J{Ix(*x1K26 zBC73+onOq-z*bT+O3r?Mwm{==i$chkIpxO58jhb7Mb8;b!TEV9T60wzwcUUbbXt&x zL;g2??AbxKXSCM)Z8(ZK*fU!ol(9AC&Q9n@t%=XViXdvD+M55hSQc1I&DAiFfozGL zBnjIC2V^Se2A^^wJ$Ekyp)vwdzhuEbczCFEq>$s$_b%4{qUY`n&c!E_CCJ?IF2K%P zx{R}dEm&CwT!&X9glrY1-V3sF?C6&GVYOg8qS4PR{29I`+Rk9k?$)YwS%l9dp z`hG2#xmr!d7I(Inul(zR!K$V$i*no)!JWAWBb~#b86aL%q&4R;&pBkXD7Y4sf3^pY z8mOkZb%bEP;hBM39^y-ENXNhv(Ekm-ai_MKb}snmOS)d2VEg{{>tvQMw+H!dL=$h# zDTYb-jd!8=3aA_TZUxT#5iG;@J$%P`gL~t`bQw7D5tbLJc55vKb9f(0G|kT45M8A+ z%mxzO742zvlrwR$S_$o+Wbo%1>~^qB49s2}{`7F)PXM*~T3E|Yu)srjV9thmgV~v= zVs5uOpl*!~c)lj+;bYsUc0^zk^Ut-KQcX9OPfEb=el}*QKCfNP`4}Uq^zNePXL(pn ziBPok6>Pz0sGI25Xn{NC*g6Bg>#gk`&A0iBK|B~jEy@teYd`c8_wb`0<^1j{8hfjC zaiug;)5nv$mpU|L3)FvW#Fx zxJQ&)TMF9ih#ikRr#|h|jqS6yx3z;#HaX~yZFZ6=1Y*IlkxR-&s#Xl|wo(A2% zyjm(>4ou*Zolz3Rh`#fJODa|+75Fx8DB=#c(0G9y08C8@Q>!D*h+}n`Nb|%VNXs3yym}bwFpy8PNUtQtJG^AXvqv%M6x`Kxj2|4 z3MnaepRvV6*Klt+N2y-yQoW%_{jp2qQu(VfCkN6-9MSMt!wp^wna_Pg)yqmyz0?db zodqd!W3?1kC{WVvK3TJ@eri_Bd{@Ej7;IMy@0$=g#l^{K?wy7H$fO0P<18u;uN94H zg0e}ft>5&)vv5eCB?_G=pJ>)+g#GzR$g>Sw1)EH-iSj?*vPcm!KZnrVRVAH{&2ofZS1PxoILJz zF(?S)F!>uY(WFZ(ff|C5bP^rUt|9WqpMxw-_nuG%hN)l;HRBnmtdP0iE=b%39}Iu< z_B4NfjKKEd((YWnuab9~2- z8;ZI&&*)apHrf8CG8(-V$Wzm!WY^G-kj_sXfqJJD3hGn`kFCay`(t@9ZSvzD{V3%O zaW72L0|16Ovy{kC^K4e8Z_j~Bg{9@K&Bs~{B- zL4$2JyW>`e`(VWqDDXa4INkZZ92lASsUsUbC6VA!EYU!$a;C7lvA-W;W-*=kP+-nA zoOrLj2b_pAwhmFZrIFxqj2NkyrD!p~M-z=)g((q_v3db$#@>+6jvlcy(?ykr8#Q)% z5h%EY64kpnB6*7lR`y=BP`4f`1;`)Xkd+=W7X)r9kEF44kU$|cG&B@Gy+)VL!VHck zT}HQ(hJfQsP~GL77-9j}4q@9J^qF#Wh$>ry6emVY$0Gcogsw^k<-Vs3E4$d*+0Cg4 zAEmJBdao(y^ZMxm;%8oh2^~BFu7h7>GHIg-JqBts#r;_Io&W#< diff --git a/webapp/src/components/loginAndRegistration/Login.js b/webapp/src/components/loginAndRegistration/Login.js index 25d25835..d4503d52 100644 --- a/webapp/src/components/loginAndRegistration/Login.js +++ b/webapp/src/components/loginAndRegistration/Login.js @@ -22,11 +22,6 @@ const Login = () => { placeholder={t("login.password_placeholder")} />
-
- -
diff --git a/webapp/src/custom.css b/webapp/src/custom.css index 82c35fd5..c738e201 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -379,23 +379,22 @@ h1::before transition: all 0.7s ease-in-out; } -#welcomeMessage -figcaption -h1::before { - top: -4.3em; - right: 2em; - content: "Click to close"; - font-weight: 400; - color: #666; - opacity: 0; +@keyframes moveUpDown { + 0% { transform: translateY(0); } + 50% { transform: translateY(5px); } /* Mover hacia abajo */ + 100% { transform: translateY(0); } /* Volver a la posición inicial */ } -#welcomeMessage -figcaption -h1::after { +#welcomeMessage figcaption h1::after { bottom: -3em; - content: "Click to continue"; + content: url('../public/click2.png'); transition: all 0.3s ease-in-out; + animation: moveUpDown 2s infinite alternate; /* Alternar entre mover hacia arriba y hacia abajo cada 2 segundos */ +} + + +#welcomeMessage figcaption h1:hover::after { + transform: translate(5px, 5px); } #welcomeMessage From 48121a8e1bcbea64e993256f4f4f28289850a801 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Mon, 1 Apr 2024 12:09:27 +0200 Subject: [PATCH 19/66] improved click --- webapp/src/custom.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/src/custom.css b/webapp/src/custom.css index c738e201..370c6ccf 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -381,7 +381,7 @@ h1::before @keyframes moveUpDown { 0% { transform: translateY(0); } - 50% { transform: translateY(5px); } /* Mover hacia abajo */ + 50% { transform: translateY(10px); } /* Mover hacia abajo */ 100% { transform: translateY(0); } /* Volver a la posición inicial */ } @@ -389,7 +389,7 @@ h1::before bottom: -3em; content: url('../public/click2.png'); transition: all 0.3s ease-in-out; - animation: moveUpDown 2s infinite alternate; /* Alternar entre mover hacia arriba y hacia abajo cada 2 segundos */ + animation: moveUpDown 1s infinite alternate; /* Alternar entre mover hacia arriba y hacia abajo cada 2 segundos */ } From 408db340386dde0e3d03891f77ddfe87b3710acf Mon Sep 17 00:00:00 2001 From: lauratbg Date: Mon, 1 Apr 2024 12:48:06 +0200 Subject: [PATCH 20/66] Changed styles of linkf of login and reigister --- webapp/src/custom.css | 49 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/webapp/src/custom.css b/webapp/src/custom.css index 370c6ccf..68e2d38e 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -134,12 +134,49 @@ -.remember-forgot { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 20px; -} + .button-register, .button-login { + appearance: none; + background-color: transparent; + border: 0.125em solid #00fff2; + border-radius: 0.9375em; + box-sizing: border-box; + color: #ffffffbf; + cursor: pointer; + display: inline-block; + font-family: Roobert,-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; + font-size: 16px; + font-weight: 600; + line-height: normal; + margin: 0; + min-height: 3.75em; + min-width: 0; + outline: none; + padding: 1em 2.3em; + text-align: center; + text-decoration: none; + transition: all 300ms cubic-bezier(.23, 1, 0.32, 1); + user-select: none; + -webkit-user-select: none; + touch-action: manipulation; + will-change: transform; + } + + .button-register:disabled, .button-login:disabled { + pointer-events: none; + } + + .button-register:hover, .button-login:hover { + color: #fff; + background-color: #1A1A1A; + box-shadow: rgba(0, 0, 0, 0.25) 0 8px 15px; + transform: translateY(-2px); + } + + .button-register:active, .button-login:active { + box-shadow: none; + transform: translateY(0); + } + button[type="submit"] { From 7477913d2fd50469b13b72ec4220812fc80ad724 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Mon, 1 Apr 2024 16:58:58 +0200 Subject: [PATCH 21/66] Some modifications of login and register and also internationalize of tooltips --- webapp/src/components/Home/Home.js | 9 ++++++--- webapp/src/components/loginAndRegistration/AddUser.js | 3 +++ webapp/src/components/loginAndRegistration/Login.js | 2 ++ webapp/src/custom.css | 1 - 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/webapp/src/components/Home/Home.js b/webapp/src/components/Home/Home.js index c6476f27..42514596 100644 --- a/webapp/src/components/Home/Home.js +++ b/webapp/src/components/Home/Home.js @@ -1,11 +1,14 @@ import React, { useState } from "react"; import { Link } from 'react-router-dom'; +import { useTranslation } from "react-i18next"; + import "../../custom.css"; function Home() { + const { t } = useTranslation("global"); return (
@@ -17,19 +20,19 @@ function Home() { W - + Instructions I - + Login Q - + Add user diff --git a/webapp/src/components/loginAndRegistration/AddUser.js b/webapp/src/components/loginAndRegistration/AddUser.js index e4c8459d..c729c359 100644 --- a/webapp/src/components/loginAndRegistration/AddUser.js +++ b/webapp/src/components/loginAndRegistration/AddUser.js @@ -13,6 +13,7 @@ const AddUser = () => {

{t("addUser.title")}

+

{t("addUser.username_placeholder")}:

{ />
+

{t("addUser.password_placeholder")}:

{ />
+

{t("addUser.repeat_password_placeholder")}:

{

{t("login.title")}

+

{t("login.username_placeholder")}:

+

{t("login.password_placeholder")}:

Date: Mon, 1 Apr 2024 21:48:08 +0200 Subject: [PATCH 22/66] Improvements and added welcome text in home view --- webapp/src/components/Home/Home.js | 26 +++++--- .../loginAndRegistration/AddUser.js | 3 - .../components/loginAndRegistration/Login.js | 3 +- webapp/src/custom.css | 60 ++++++++++++++----- webapp/src/translations/en/global.json | 17 +++--- webapp/src/translations/es/global.json | 4 +- webapp/src/translations/tk/global.json | 17 +++--- 7 files changed, 85 insertions(+), 45 deletions(-) diff --git a/webapp/src/components/Home/Home.js b/webapp/src/components/Home/Home.js index 42514596..4c2c8f11 100644 --- a/webapp/src/components/Home/Home.js +++ b/webapp/src/components/Home/Home.js @@ -1,18 +1,28 @@ import React, { useState } from "react"; import { Link } from 'react-router-dom'; import { useTranslation } from "react-i18next"; - import "../../custom.css"; +function Home() { + const { t } = useTranslation("global"); + const [textContainerVisible, setTextContainerVisible] = useState(true); + const handleToggleOpen = () => { + setTextContainerVisible(false); + }; -function Home() { + const handleToggleClose = () => { + setTextContainerVisible(true); + }; - const { t } = useTranslation("global"); return ( -
- - +
+
+

{t("home.msg1")}

+

{t("home.msg2")}

+
+ +

@@ -39,10 +49,8 @@ function Home() {

-
- +
); } export default Home; - diff --git a/webapp/src/components/loginAndRegistration/AddUser.js b/webapp/src/components/loginAndRegistration/AddUser.js index c729c359..70809725 100644 --- a/webapp/src/components/loginAndRegistration/AddUser.js +++ b/webapp/src/components/loginAndRegistration/AddUser.js @@ -16,7 +16,6 @@ const AddUser = () => {

{t("addUser.username_placeholder")}:

@@ -24,7 +23,6 @@ const AddUser = () => {

{t("addUser.password_placeholder")}:

@@ -32,7 +30,6 @@ const AddUser = () => {

{t("addUser.repeat_password_placeholder")}:

diff --git a/webapp/src/components/loginAndRegistration/Login.js b/webapp/src/components/loginAndRegistration/Login.js index 9c3d1a5e..ca655582 100644 --- a/webapp/src/components/loginAndRegistration/Login.js +++ b/webapp/src/components/loginAndRegistration/Login.js @@ -15,13 +15,12 @@ const Login = () => {

{t("login.title")}

{t("login.username_placeholder")}:

- +

{t("login.password_placeholder")}:

diff --git a/webapp/src/custom.css b/webapp/src/custom.css index d2e45c6b..df546480 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -84,7 +84,7 @@ .form { display: flex; flex-direction: column; - gap: 50px; + gap: 20px; padding-left: 2em; padding-right: 2em; padding-bottom: 0.4em; @@ -115,24 +115,32 @@ } + .input-box { + display: flex; + flex-direction: row; + align-items: center; + margin-bottom: 20px; + } + + .input-box p { + font-weight: bold; + margin-right: 10%; + width: 150px; + text-align: right; + } + .input-box input { - width: 100%; - height: 100%; - background: rgb(177, 233, 188); - border: none; - outline: none; + flex: 1; + height: 40px; + background: rgb(255, 255, 255); border: 2px solid gray; - border-radius: 40px; - font-size: 18px; + border-radius: 10px; + font-size: 18px; color: black; + padding: 10px; } - .input-box input::placeholder { - background-color: rgb(255, 255, 255); - font-size: 18px; /* Ajustar el tamaño de la fuente del marcador de posición */ - } - - + .button-register, .button-login { appearance: none; background-color: transparent; @@ -282,7 +290,6 @@ button[type="submit"]:hover { height: 100vh; /* Toma el 100% del alto de la ventana */ } - :root { --gradient: conic-gradient( from 240deg at 50% 50%, @@ -303,6 +310,27 @@ button[type="submit"]:hover { } +.text-container{ + position: absolute; + top: 15%; + width: 300%; /* Ajusta el ancho al 100% de la pantalla */ + text-align: center; /* Centra el texto horizontalmente */ + z-index: 2; /* Asegura que el texto esté encima del mensaje de bienvenida */ + +} + +.text-container p { + font-size: 1.5rem; /* Ajusta el tamaño del texto según sea necesario */ +} + + +.text-container.hidden { + opacity: 0; + height: 0; +} + + + * , *::before , *::after { @@ -338,8 +366,10 @@ body { } #welcomeMessage { + position: relative; /* Cambia a posición relativa para que el z-index funcione correctamente */ width: 100%; max-width: 600px; + z-index: 1; /* Asegura que el mensaje de bienvenida esté detrás del texto */ } #welcomeMessage diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json index 0a2bd647..d95b3eed 100644 --- a/webapp/src/translations/en/global.json +++ b/webapp/src/translations/en/global.json @@ -1,11 +1,14 @@ { - "home": { - "welcome": "Welcome to WIQ!", - "how_to_play": "How to play?", - "login": "Login", - "register": "Don't have an account? Register here.", - "language": "The language has been changed to English" - }, + "home": { + "welcome": "Welcome to WIQ!", + "how_to_play": "How to Play?", + "login": "Log In", + "register": "Don't have an account? Sign up here.", + "language": "The language has been changed to English", + "msg1": "Welcome to the knowledge challenge! Get ready to test your mind and demonstrate your skills. In this exciting game, you will face a series of questions that will test your knowledge on a variety of topics.", + "msg2": "So go ahead, prove that you are the master of questions! Are you ready to accept the challenge?" +}, + "navBar": { "title": "Know and win!", "en": "English", diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json index 50888b37..ab4d8be8 100644 --- a/webapp/src/translations/es/global.json +++ b/webapp/src/translations/es/global.json @@ -4,7 +4,9 @@ "how_to_play": "¿Cómo jugar?", "login": "Iniciar sesión", "register": "¿No tienes una cuenta? Regístrate aquí.", - "language": "El idioma ha sido cambiado a español" + "language": "El idioma ha sido cambiado a español", + "msg1": "Bienvenido al desafío de conocimientos! Prepárate para poner a prueba tu mente y demostrar tus habilidades. En este emocionante juego, te enfrentarás a una serie de preguntas que pondrán a prueba tu conocimiento en una variedad de temas.", + "msg2": "¡Así que adelante, demuestra que eres el maestro de las preguntas! ¿Estás listo para aceptar el desafío?" }, diff --git a/webapp/src/translations/tk/global.json b/webapp/src/translations/tk/global.json index 9d1982a6..e55a4d45 100644 --- a/webapp/src/translations/tk/global.json +++ b/webapp/src/translations/tk/global.json @@ -1,12 +1,13 @@ { - "home": { - "welcome": "WIQ'e hoş geldiniz!", - "how_to_play": "Nasıl oynanır?", - "login": "Giriş yap", - "register": "Hesabınız yok mu? Buradan kaydolun.", - "language": "Dilin Türkçe olduğu değiştirilmiştir" - - }, + "home": { + "welcome": "WIQ'e hoş geldiniz!", + "how_to_play": "Nasıl Oynanır?", + "login": "Giriş Yap", + "register": "Hesabınız yok mu? Buradan kaydolun.", + "language": "Dil Türkçe olarak değiştirildi", + "msg1": "Bilgi meydan okumasına hoş geldiniz! Zihninizi test etmeye ve becerilerinizi göstermeye hazır olun. Bu heyecan verici oyunda, çeşitli konulardaki bilginizi test edecek bir dizi soruyla karşılaşacaksınız.", + "msg2": "Öyleyse ilerleyin, soruların ustası olduğunuzu kanıtlayın! Meydan okumayı kabul etmeye hazır mısınız?" +}, "navBar": { "title": "Bil ve Kazan!", From 0fb05aa2ee889e09df66a7830b42077644241418 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Tue, 2 Apr 2024 18:21:14 +0200 Subject: [PATCH 23/66] First version of jest test --- package-lock.json | 4279 +++++++++++++++-- package.json | 3 + webapp/src/App.test.js | 7 +- .../loginAndRegistration/AddUser.test.js | 29 + .../components/loginAndRegistration/Login.js | 2 +- .../loginAndRegistration/Login.test.js | 87 +- 6 files changed, 3995 insertions(+), 412 deletions(-) diff --git a/package-lock.json b/package-lock.json index 737d6d39..ce1e9876 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,22 @@ "i18n": "^0.15.1", "react-countdown": "^2.3.5", "react-router-dom": "^6.22.1" + }, + "devDependencies": { + "jest": "^29.7.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/@asciidoctor/core": { @@ -40,438 +56,3124 @@ "node": ">=16" } }, - "node_modules/@babel/runtime": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", - "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, "dependencies": { - "regenerator-runtime": "^0.14.0" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + "node_modules/@babel/compat-data": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.1.tgz", + "integrity": "sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@material-ui/core": { - "version": "4.12.4", - "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz", - "integrity": "sha512-tr7xekNlM9LjA6pagJmL8QCgZXaubWUwkJnoYcMKd4gw/t4XiyvnTkjdGrUVicyB2BsdaAv1tvow45bPM4sSwQ==", - "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", + "node_modules/@babel/core": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.3.tgz", + "integrity": "sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.4.4", - "@material-ui/styles": "^4.11.5", - "@material-ui/system": "^4.12.2", - "@material-ui/types": "5.1.0", - "@material-ui/utils": "^4.11.3", - "@types/react-transition-group": "^4.2.0", - "clsx": "^1.0.4", - "hoist-non-react-statics": "^3.3.2", - "popper.js": "1.16.1-lts", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0", - "react-transition-group": "^4.4.0" + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.1", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.1", + "@babel/parser": "^7.24.1", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { - "node": ">=8.0.0" + "node": ">=6.9.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/material-ui" - }, - "peerDependencies": { - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "url": "https://opencollective.com/babel" } }, - "node_modules/@material-ui/icons": { - "version": "4.11.3", - "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.3.tgz", - "integrity": "sha512-IKHlyx6LDh8n19vzwH5RtHIOHl9Tu90aAAxcbWME6kp4dmvODM3UvOHJeMIDzUbd4muuJKHmlNoBN+mDY4XkBA==", + "node_modules/@babel/generator": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.1.tgz", + "integrity": "sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.4.4" + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" }, "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "@material-ui/core": "^4.0.0", - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@material-ui/styles": { - "version": "4.11.5", - "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.5.tgz", - "integrity": "sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA==", - "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.4.4", - "@emotion/hash": "^0.8.0", - "@material-ui/types": "5.1.0", - "@material-ui/utils": "^4.11.3", - "clsx": "^1.0.4", - "csstype": "^2.5.2", - "hoist-non-react-statics": "^3.3.2", - "jss": "^10.5.1", - "jss-plugin-camel-case": "^10.5.1", - "jss-plugin-default-unit": "^10.5.1", - "jss-plugin-global": "^10.5.1", - "jss-plugin-nested": "^10.5.1", - "jss-plugin-props-sort": "^10.5.1", - "jss-plugin-rule-value-function": "^10.5.1", - "jss-plugin-vendor-prefixer": "^10.5.1", - "prop-types": "^15.7.2" + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { - "node": ">=8.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/material-ui" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, - "peerDependencies": { - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@material-ui/system": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz", - "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==", + "node_modules/@babel/helper-module-imports": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.4.4", - "@material-ui/utils": "^4.11.3", - "csstype": "^2.5.2", - "prop-types": "^15.7.2" + "@babel/types": "^7.24.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.20" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/material-ui" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@types/react": "^16.8.6 || ^17.0.0", - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@babel/core": "^7.0.0" } }, - "node_modules/@material-ui/types": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", - "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==", - "peerDependencies": { - "@types/react": "*" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "dev": true, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@material-ui/utils": { - "version": "4.11.3", - "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz", - "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==", + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.4.4", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0" + "@babel/types": "^7.22.5" }, "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0", - "react-dom": "^16.8.0 || ^17.0.0" + "node": ">=6.9.0" } }, - "node_modules/@messageformat/core": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@messageformat/core/-/core-3.3.0.tgz", - "integrity": "sha512-YcXd3remTDdeMxAlbvW6oV9d/01/DZ8DHUFwSttO3LMzIZj3iO0NRw+u1xlsNNORFI+u0EQzD52ZX3+Udi0T3g==", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dev": true, "dependencies": { - "@messageformat/date-skeleton": "^1.0.0", - "@messageformat/number-skeleton": "^1.0.0", - "@messageformat/parser": "^5.1.0", - "@messageformat/runtime": "^3.0.1", - "make-plural": "^7.0.0", - "safe-identifier": "^0.4.1" + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@messageformat/date-skeleton": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@messageformat/date-skeleton/-/date-skeleton-1.0.1.tgz", - "integrity": "sha512-jPXy8fg+WMPIgmGjxSlnGJn68h/2InfT0TNSkVx0IGXgp4ynnvYkbZ51dGWmGySEK+pBiYUttbQdu5XEqX5CRg==" + "node_modules/@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@messageformat/number-skeleton": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@messageformat/number-skeleton/-/number-skeleton-1.2.0.tgz", - "integrity": "sha512-xsgwcL7J7WhlHJ3RNbaVgssaIwcEyFkBqxHdcdaiJzwTZAWEOD8BuUFxnxV9k5S0qHN3v/KzUpq0IUpjH1seRg==" + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@messageformat/parser": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@messageformat/parser/-/parser-5.1.0.tgz", - "integrity": "sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ==", - "dependencies": { - "moo": "^0.5.1" + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@messageformat/runtime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@messageformat/runtime/-/runtime-3.0.1.tgz", - "integrity": "sha512-6RU5ol2lDtO8bD9Yxe6CZkl0DArdv0qkuoZC+ZwowU+cdRlVE1157wjCmlA5Rsf1Xc/brACnsZa5PZpEDfTFFg==", + "node_modules/@babel/helpers": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.1.tgz", + "integrity": "sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg==", + "dev": true, "dependencies": { - "make-plural": "^7.0.0" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.1", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@remix-run/router": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz", - "integrity": "sha512-zcU0gM3z+3iqj8UX45AmWY810l3oUmXM7uH4dt5xtzvMhRtYVhKGOmgOd1877dOPPepfCjUv57w+syamWIYe7w==", + "node_modules/@babel/highlight": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" } }, - "node_modules/@types/prop-types": { - "version": "15.7.11", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", - "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } }, - "node_modules/@types/react": { - "version": "17.0.76", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.76.tgz", - "integrity": "sha512-w9Aq+qeszGYoQM0hgFcdsAODGJdogadBDiitPm+zjBFJ0mLymvn2qSXsDaLJUndFRqqXk1FQfa9avHUBk1JhJQ==", + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/@types/react-transition-group": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", - "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "dependencies": { - "@types/react": "*" + "color-name": "1.1.3" } }, - "node_modules/@types/react/node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true }, - "node_modules/@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } }, - "node_modules/asciidoctor-emoji": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/asciidoctor-emoji/-/asciidoctor-emoji-0.5.0.tgz", - "integrity": "sha512-3lsYV2kdX1MseZAm1KgSPwny+P7Fr83ZPH4MxNISIZAz3cPEGaFgNxRbr/uha4Tyv+oarpoaY5cGI7Fe0HluZg==", - "peerDependencies": { + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", + "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", + "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.24.1", + "@babel/generator": "^7.24.1", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.24.1", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@material-ui/core": { + "version": "4.12.4", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz", + "integrity": "sha512-tr7xekNlM9LjA6pagJmL8QCgZXaubWUwkJnoYcMKd4gw/t4XiyvnTkjdGrUVicyB2BsdaAv1tvow45bPM4sSwQ==", + "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", + "dependencies": { + "@babel/runtime": "^7.4.4", + "@material-ui/styles": "^4.11.5", + "@material-ui/system": "^4.12.2", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.3", + "@types/react-transition-group": "^4.2.0", + "clsx": "^1.0.4", + "hoist-non-react-statics": "^3.3.2", + "popper.js": "1.16.1-lts", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0", + "react-transition-group": "^4.4.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/material-ui" + }, + "peerDependencies": { + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/icons": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.3.tgz", + "integrity": "sha512-IKHlyx6LDh8n19vzwH5RtHIOHl9Tu90aAAxcbWME6kp4dmvODM3UvOHJeMIDzUbd4muuJKHmlNoBN+mDY4XkBA==", + "dependencies": { + "@babel/runtime": "^7.4.4" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "@material-ui/core": "^4.0.0", + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/styles": { + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.5.tgz", + "integrity": "sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA==", + "deprecated": "Material UI v4 doesn't receive active development since September 2021. See the guide https://mui.com/material-ui/migration/migration-v4/ to upgrade to v5.", + "dependencies": { + "@babel/runtime": "^7.4.4", + "@emotion/hash": "^0.8.0", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.3", + "clsx": "^1.0.4", + "csstype": "^2.5.2", + "hoist-non-react-statics": "^3.3.2", + "jss": "^10.5.1", + "jss-plugin-camel-case": "^10.5.1", + "jss-plugin-default-unit": "^10.5.1", + "jss-plugin-global": "^10.5.1", + "jss-plugin-nested": "^10.5.1", + "jss-plugin-props-sort": "^10.5.1", + "jss-plugin-rule-value-function": "^10.5.1", + "jss-plugin-vendor-prefixer": "^10.5.1", + "prop-types": "^15.7.2" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/material-ui" + }, + "peerDependencies": { + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/system": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz", + "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==", + "dependencies": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.11.3", + "csstype": "^2.5.2", + "prop-types": "^15.7.2" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/material-ui" + }, + "peerDependencies": { + "@types/react": "^16.8.6 || ^17.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/types": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", + "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==", + "peerDependencies": { + "@types/react": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@material-ui/utils": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz", + "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==", + "dependencies": { + "@babel/runtime": "^7.4.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@messageformat/core": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@messageformat/core/-/core-3.3.0.tgz", + "integrity": "sha512-YcXd3remTDdeMxAlbvW6oV9d/01/DZ8DHUFwSttO3LMzIZj3iO0NRw+u1xlsNNORFI+u0EQzD52ZX3+Udi0T3g==", + "dependencies": { + "@messageformat/date-skeleton": "^1.0.0", + "@messageformat/number-skeleton": "^1.0.0", + "@messageformat/parser": "^5.1.0", + "@messageformat/runtime": "^3.0.1", + "make-plural": "^7.0.0", + "safe-identifier": "^0.4.1" + } + }, + "node_modules/@messageformat/date-skeleton": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@messageformat/date-skeleton/-/date-skeleton-1.0.1.tgz", + "integrity": "sha512-jPXy8fg+WMPIgmGjxSlnGJn68h/2InfT0TNSkVx0IGXgp4ynnvYkbZ51dGWmGySEK+pBiYUttbQdu5XEqX5CRg==" + }, + "node_modules/@messageformat/number-skeleton": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@messageformat/number-skeleton/-/number-skeleton-1.2.0.tgz", + "integrity": "sha512-xsgwcL7J7WhlHJ3RNbaVgssaIwcEyFkBqxHdcdaiJzwTZAWEOD8BuUFxnxV9k5S0qHN3v/KzUpq0IUpjH1seRg==" + }, + "node_modules/@messageformat/parser": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@messageformat/parser/-/parser-5.1.0.tgz", + "integrity": "sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ==", + "dependencies": { + "moo": "^0.5.1" + } + }, + "node_modules/@messageformat/runtime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@messageformat/runtime/-/runtime-3.0.1.tgz", + "integrity": "sha512-6RU5ol2lDtO8bD9Yxe6CZkl0DArdv0qkuoZC+ZwowU+cdRlVE1157wjCmlA5Rsf1Xc/brACnsZa5PZpEDfTFFg==", + "dependencies": { + "make-plural": "^7.0.0" + } + }, + "node_modules/@remix-run/router": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz", + "integrity": "sha512-zcU0gM3z+3iqj8UX45AmWY810l3oUmXM7uH4dt5xtzvMhRtYVhKGOmgOd1877dOPPepfCjUv57w+syamWIYe7w==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/node": { + "version": "20.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.2.tgz", + "integrity": "sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.11", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" + }, + "node_modules/@types/react": { + "version": "17.0.76", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.76.tgz", + "integrity": "sha512-w9Aq+qeszGYoQM0hgFcdsAODGJdogadBDiitPm+zjBFJ0mLymvn2qSXsDaLJUndFRqqXk1FQfa9avHUBk1JhJQ==", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.10", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", + "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react/node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/@types/scheduler": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/asciidoctor-emoji": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/asciidoctor-emoji/-/asciidoctor-emoji-0.5.0.tgz", + "integrity": "sha512-3lsYV2kdX1MseZAm1KgSPwny+P7Fr83ZPH4MxNISIZAz3cPEGaFgNxRbr/uha4Tyv+oarpoaY5cGI7Fe0HluZg==", + "peerDependencies": { "@asciidoctor/core": ">=2.2 <4.0" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "peer": true + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001605", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001605.tgz", + "integrity": "sha512-nXwGlFWo34uliI9z3n6Qc0wZaf7zaZWA1CPZ169La5mV3I/gem7bst0vr5XQH5TJXZIMfDeZyOrZnSlVzKxxHQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-vendor": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", + "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", + "dependencies": { + "@babel/runtime": "^7.8.3", + "is-in-browser": "^1.0.2" + } + }, + "node_modules/csstype": { + "version": "2.6.21", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dom-helpers/node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.723", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.723.tgz", + "integrity": "sha512-rxFVtrMGMFROr4qqU6n95rUi9IlfIm+lIAt+hOToy/9r6CDv0XiEcQdC3VP71y1pE5CFTzKV0RvxOGYCPWWHPw==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-printf": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", + "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "dependencies": { + "boolean": "^3.1.4" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hyphenate-style-name": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", + "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" + }, + "node_modules/i18n": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.15.1.tgz", + "integrity": "sha512-yue187t8MqUPMHdKjiZGrX+L+xcUsDClGO0Cz4loaKUOK9WrGw5pgan4bv130utOwX7fHE9w2iUeHFalVQWkXA==", + "dependencies": { + "@messageformat/core": "^3.0.0", + "debug": "^4.3.3", + "fast-printf": "^1.6.9", + "make-plural": "^7.0.0", + "math-interval-parser": "^2.0.1", + "mustache": "^4.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/mashpie" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-in-browser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", + "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==" + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "peer": true, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" } }, - "node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "node_modules/istanbul-lib-instrument/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/css-vendor": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", - "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.8.3", - "is-in-browser": "^1.0.2" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/csstype": { - "version": "2.6.21", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", - "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + "node_modules/istanbul-lib-instrument/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, "dependencies": { - "ms": "2.1.2" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=6.0" + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "supports-color": { + "node-notifier": { "optional": true } } }, - "node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dom-helpers/node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/fast-printf": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", - "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", + "node_modules/jest-snapshot/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, "dependencies": { - "boolean": "^3.1.4" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, "engines": { - "node": ">=10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "peer": true - }, - "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "peer": true, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, "dependencies": { - "react-is": "^16.7.0" + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/hyphenate-style-name": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", - "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/i18n": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.15.1.tgz", - "integrity": "sha512-yue187t8MqUPMHdKjiZGrX+L+xcUsDClGO0Cz4loaKUOK9WrGw5pgan4bv130utOwX7fHE9w2iUeHFalVQWkXA==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { - "@messageformat/core": "^3.0.0", - "debug": "^4.3.3", - "fast-printf": "^1.6.9", - "make-plural": "^7.0.0", - "math-interval-parser": "^2.0.1", - "mustache": "^4.2.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/mashpie" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "peer": true, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "peer": true + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } }, - "node_modules/is-in-browser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", - "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==" + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } }, "node_modules/jss": { "version": "10.10.0", @@ -560,6 +3262,42 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -571,11 +3309,77 @@ "loose-envify": "cli.js" } }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/make-plural": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-7.3.0.tgz", "integrity": "sha512-/K3BC0KIsO+WK2i94LkMPv3wslMrazrQhfi5We9fMbLlLjzoOSJWr7TAdupLlDWaJcWxwoNosBkhFDejiu5VDw==" }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, "node_modules/math-interval-parser": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-2.0.1.tgz", @@ -584,51 +3388,273 @@ "node": ">=0.10.0" } }, - "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "peer": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/moo": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", - "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "bin": { - "mustache": "bin/mustache" + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "peer": true, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, "dependencies": { - "wrappy": "1" + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/popper.js": { @@ -636,6 +3662,51 @@ "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==" }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -651,6 +3722,22 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/react": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", @@ -745,6 +3832,62 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/safe-identifier": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", @@ -760,11 +3903,302 @@ "object-assign": "^4.1.1" } }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/tiny-warning": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/unxhr": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.2.0.tgz", @@ -774,11 +4208,162 @@ "node": ">=8.11" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", + "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "peer": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 37679c9a..e3f47e10 100644 --- a/package.json +++ b/package.json @@ -6,5 +6,8 @@ "i18n": "^0.15.1", "react-countdown": "^2.3.5", "react-router-dom": "^6.22.1" + }, + "devDependencies": { + "jest": "^29.7.0" } } diff --git a/webapp/src/App.test.js b/webapp/src/App.test.js index 5e3b7314..7a9678db 100644 --- a/webapp/src/App.test.js +++ b/webapp/src/App.test.js @@ -3,6 +3,9 @@ import App from './App'; test('renders learn react link', () => { render(); - const linkElement = screen.getByText(/Welcome to the 2024 edition of the Software Architecture course/i); - expect(linkElement).toBeInTheDocument(); + + expect(screen.getByText('navBar.title')).toBeInTheDocument(); + expect(screen.getByText('navBar.language')).toBeInTheDocument(); + expect(screen.getByAltText('App logo')).toBeInTheDocument(); + expect(screen.getByAltText('Help')).toBeInTheDocument(); }); diff --git a/webapp/src/components/loginAndRegistration/AddUser.test.js b/webapp/src/components/loginAndRegistration/AddUser.test.js index 302db0aa..bc9954d8 100644 --- a/webapp/src/components/loginAndRegistration/AddUser.test.js +++ b/webapp/src/components/loginAndRegistration/AddUser.test.js @@ -1,3 +1,32 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import AddUser from './AddUser'; +import { BrowserRouter as Router } from 'react-router-dom'; + +// Mocking useTranslation hook +jest.mock('react-i18next', () => ({ + useTranslation: () => ({ t: key => key }), +})); + +describe('', () => { + test('renders the AddUser component', () => { + render( + + + + ); + + expect(screen.getByText('addUser.title')).toBeInTheDocument(); + expect(screen.getByText('addUser.username_placeholder:')).toBeInTheDocument(); + expect(screen.getByText('addUser.password_placeholder:')).toBeInTheDocument(); + expect(screen.getByText('addUser.repeat_password_placeholder:')).toBeInTheDocument(); + expect(screen.getByText('addUser.register_button')).toBeInTheDocument(); + expect(screen.getByText('addUser.login_link')).toBeInTheDocument(); + + }); +}); + + // import React from 'react'; // import { render, fireEvent, screen, waitFor } from '@testing-library/react'; // import axios from 'axios'; diff --git a/webapp/src/components/loginAndRegistration/Login.js b/webapp/src/components/loginAndRegistration/Login.js index ca655582..0c4d262d 100644 --- a/webapp/src/components/loginAndRegistration/Login.js +++ b/webapp/src/components/loginAndRegistration/Login.js @@ -12,7 +12,7 @@ const Login = () => {
-

{t("login.title")}

+

{t("login.title")}

{t("login.username_placeholder")}:

diff --git a/webapp/src/components/loginAndRegistration/Login.test.js b/webapp/src/components/loginAndRegistration/Login.test.js index d95164ca..ce0598e2 100644 --- a/webapp/src/components/loginAndRegistration/Login.test.js +++ b/webapp/src/components/loginAndRegistration/Login.test.js @@ -1,62 +1,25 @@ -// import React from 'react'; -// import { render, fireEvent, screen, waitFor, act } from '@testing-library/react'; -// import axios from 'axios'; -// import MockAdapter from 'axios-mock-adapter'; -// import Login from './Login'; - -// const mockAxios = new MockAdapter(axios); - -// describe('Login component', () => { -// beforeEach(() => { -// mockAxios.reset(); -// }); - -// it('should log in successfully', async () => { -// render(); - -// const usernameInput = screen.getByLabelText(/Username/i); -// const passwordInput = screen.getByLabelText(/Password/i); -// const loginButton = screen.getByRole('button', { name: /Login/i }); - -// // Mock the axios.post request to simulate a successful response -// mockAxios.onPost('http://localhost:8000/login').reply(200, { createdAt: '2024-01-01T12:34:56Z' }); - -// // Simulate user input -// await act(async () => { -// fireEvent.change(usernameInput, { target: { value: 'testUser' } }); -// fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); -// fireEvent.click(loginButton); -// }); - -// // Verify that the user information is displayed -// expect(screen.getByText(/Hello testUser!/i)).toBeInTheDocument(); -// expect(screen.getByText(/Your account was created on 1\/1\/2024/i)).toBeInTheDocument(); -// }); - -// it('should handle error when logging in', async () => { -// render(); - -// const usernameInput = screen.getByLabelText(/Username/i); -// const passwordInput = screen.getByLabelText(/Password/i); -// const loginButton = screen.getByRole('button', { name: /Login/i }); - -// // Mock the axios.post request to simulate an error response -// mockAxios.onPost('http://localhost:8000/login').reply(401, { error: 'Unauthorized' }); - -// // Simulate user input -// fireEvent.change(usernameInput, { target: { value: 'testUser' } }); -// fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); - -// // Trigger the login button click -// fireEvent.click(loginButton); - -// // Wait for the error Snackbar to be open -// await waitFor(() => { -// expect(screen.getByText(/Error: Unauthorized/i)).toBeInTheDocument(); -// }); - -// // Verify that the user information is not displayed -// expect(screen.queryByText(/Hello testUser!/i)).toBeNull(); -// expect(screen.queryByText(/Your account was created on/i)).toBeNull(); -// }); -// }); +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import Login from './Login'; +import { BrowserRouter as Router } from 'react-router-dom'; + +// Mocking useTranslation hook +jest.mock('react-i18next', () => ({ + useTranslation: () => ({ t: key => key }), +})); + +describe('', () => { + test('renders the Login component', () => { + render( + + + + ); + + expect(screen.getByText('login.title')).toBeInTheDocument(); + expect(screen.getByText('login.username_placeholder:')).toBeInTheDocument(); + expect(screen.getByText('login.password_placeholder:')).toBeInTheDocument(); + expect(screen.getByText('login.login_button')).toBeInTheDocument(); + expect(screen.getByText('login.register_link')).toBeInTheDocument(); + }); +}); From 9856a7a56ed9a18e6f688717fcb4d0507724fa96 Mon Sep 17 00:00:00 2001 From: uo289267 Date: Tue, 2 Apr 2024 20:54:56 +0200 Subject: [PATCH 24/66] Started jest tests --- webapp/src/App.test.js | 4 ++- .../src/components/GameMenu/GameMenu.test.js | 10 ++++++ .../components/questionView/QuestionView.js | 35 ++++++++++++------- 3 files changed, 35 insertions(+), 14 deletions(-) create mode 100644 webapp/src/components/GameMenu/GameMenu.test.js diff --git a/webapp/src/App.test.js b/webapp/src/App.test.js index 5e3b7314..086e69a3 100644 --- a/webapp/src/App.test.js +++ b/webapp/src/App.test.js @@ -1,8 +1,10 @@ import { render, screen } from '@testing-library/react'; import App from './App'; + test('renders learn react link', () => { render(); + /* const linkElement = screen.getByText(/Welcome to the 2024 edition of the Software Architecture course/i); - expect(linkElement).toBeInTheDocument(); + expect(linkElement).toBeInTheDocument();*/ }); diff --git a/webapp/src/components/GameMenu/GameMenu.test.js b/webapp/src/components/GameMenu/GameMenu.test.js new file mode 100644 index 00000000..5498ca93 --- /dev/null +++ b/webapp/src/components/GameMenu/GameMenu.test.js @@ -0,0 +1,10 @@ +import { render, screen } from '@testing-library/react'; +import GameMenu from './GameMenu'; +import { MemoryRouter } from 'react-router-dom'; + +test('renders learn react link', () => { + render(); + const linkElement = screen.getByText(/Game Menu/i); + expect(linkElement).toBeInTheDocument(); +}); + diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 4e39b5df..b4107a50 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -6,7 +6,9 @@ import React from "react"; import Countdown from 'react-countdown'; import {useTranslation} from "react-i18next"; import $ from 'jquery'; - +import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; +import HistoricalView from '../HistoricalData/HistoricalView'; +import ButtonHistoricalData from '../HistoricalData/HistoricalView'; const creationHistoricalRecord = new CreationHistoricalRecord(); const questionGenerator = new QuestionGenerator(); @@ -34,23 +36,26 @@ function QuestionView(){ function revealColorsForAnswers(){ let colorCorrectAnswer='green'; let colorIncorrectAnswer='red'; - $(document).ready(function() { - $('.answerButton').each(function() { - var dataValue = $(this).data('value'); - if (dataValue === false || dataValue === "false") - $(this).css('background-color', colorIncorrectAnswer); // Cambia el color de fondo del botón actual a rojo - else{ - $(this).css('background-color', colorCorrectAnswer); - } + $('.answerButton').each(function() { + var dataValue = $(this).data('value'); + if (dataValue === false || dataValue === "false") + $(this).css('background-color', colorIncorrectAnswer); // Cambia el color de fondo del botón actual a rojo + + else{ + $(this).css({ + 'background-color': colorCorrectAnswer, + 'text-decoration': 'underline' // Underline the text of the button for correct answers }); - }); + } + }); } function setColorsBackToNormal() { let colorOriginal = '#9f97ff'; - $(document).ready(function() { - $('.answerButton').each(function() { - $(this).css('background-color', colorOriginal); + $('.answerButton').each(function() { + $(this).css({ + 'background-color': colorOriginal, + 'text-decoration': 'none' // Remove underline }); }); } @@ -130,6 +135,10 @@ function QuestionComponent({questions, numQuestion, handleClick, t, points}){ {console.log(creationHistoricalRecord.getRecord())}

{t("questionView.finished_game")}

{points} {t("questionView.point")}

+ + } /> + + )} From e7744b7432756b7f875eeeced9918b6fa3e8eddf Mon Sep 17 00:00:00 2001 From: uo289267 Date: Tue, 2 Apr 2024 21:18:32 +0200 Subject: [PATCH 25/66] Added link to historical data at the end of the game --- webapp/src/components/GameMenu/GameMenu.js | 10 ++-------- .../components/HistoricalData/ButtonHistoricalData.js | 8 ++++++++ webapp/src/components/questionView/QuestionView.js | 6 ++---- 3 files changed, 12 insertions(+), 12 deletions(-) create mode 100644 webapp/src/components/HistoricalData/ButtonHistoricalData.js diff --git a/webapp/src/components/GameMenu/GameMenu.js b/webapp/src/components/GameMenu/GameMenu.js index 332a8f25..de71e3ba 100644 --- a/webapp/src/components/GameMenu/GameMenu.js +++ b/webapp/src/components/GameMenu/GameMenu.js @@ -1,9 +1,10 @@ import "../../custom.css"; import { Link } from "react-router-dom"; import {useTranslation} from "react-i18next"; +import ButtonHistoricalData from "../HistoricalData/ButtonHistoricalData"; export default function GameMenu() { - const[t, i18n] = useTranslation("global"); + const[t] = useTranslation("global"); return (
@@ -14,13 +15,6 @@ export default function GameMenu() { ); } - function ButtonHistoricalData({ t }) { - return ( - -

{t("gameMenu.history_button")}

- - ); - } function ButtonNewGame({ t }) { return ( diff --git a/webapp/src/components/HistoricalData/ButtonHistoricalData.js b/webapp/src/components/HistoricalData/ButtonHistoricalData.js new file mode 100644 index 00000000..442c86b8 --- /dev/null +++ b/webapp/src/components/HistoricalData/ButtonHistoricalData.js @@ -0,0 +1,8 @@ +import { Link } from "react-router-dom"; +export default function ButtonHistoricalData({ t }) { + return ( + +

{t("gameMenu.history_button")}

+ + ); +} \ No newline at end of file diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index b4107a50..48742453 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -8,7 +8,7 @@ import {useTranslation} from "react-i18next"; import $ from 'jquery'; import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; import HistoricalView from '../HistoricalData/HistoricalView'; -import ButtonHistoricalData from '../HistoricalData/HistoricalView'; +import ButtonHistoricalData from "../HistoricalData/ButtonHistoricalData"; const creationHistoricalRecord = new CreationHistoricalRecord(); const questionGenerator = new QuestionGenerator(); @@ -135,9 +135,7 @@ function QuestionComponent({questions, numQuestion, handleClick, t, points}){ {console.log(creationHistoricalRecord.getRecord())}

{t("questionView.finished_game")}

{points} {t("questionView.point")}

- - } /> - + )} From 41f595a272cdcbc9befaa507de3bd3513cfb9132 Mon Sep 17 00:00:00 2001 From: uo289267 Date: Tue, 2 Apr 2024 22:14:54 +0200 Subject: [PATCH 26/66] Better look for question view --- webapp/src/components/GameMenu/GameMenu.js | 2 +- .../HistoricalData/ButtonHistoricalData.js | 2 +- .../components/questionView/QuestionView.js | 20 ++--- webapp/src/custom.css | 73 ++++++++++++++----- webapp/src/translations/en/global.json | 2 +- webapp/src/translations/es/global.json | 2 +- 6 files changed, 68 insertions(+), 33 deletions(-) diff --git a/webapp/src/components/GameMenu/GameMenu.js b/webapp/src/components/GameMenu/GameMenu.js index de71e3ba..7f7bd957 100644 --- a/webapp/src/components/GameMenu/GameMenu.js +++ b/webapp/src/components/GameMenu/GameMenu.js @@ -18,7 +18,7 @@ export default function GameMenu() { function ButtonNewGame({ t }) { return ( - +

{t("gameMenu.new_game_button")}

); diff --git a/webapp/src/components/HistoricalData/ButtonHistoricalData.js b/webapp/src/components/HistoricalData/ButtonHistoricalData.js index 442c86b8..3567146e 100644 --- a/webapp/src/components/HistoricalData/ButtonHistoricalData.js +++ b/webapp/src/components/HistoricalData/ButtonHistoricalData.js @@ -1,7 +1,7 @@ import { Link } from "react-router-dom"; export default function ButtonHistoricalData({ t }) { return ( - +

{t("gameMenu.history_button")}

); diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 48742453..43354f9a 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -34,8 +34,8 @@ function QuestionView(){ } function revealColorsForAnswers(){ - let colorCorrectAnswer='green'; - let colorIncorrectAnswer='red'; + let colorCorrectAnswer='#6EF26E';//green + let colorIncorrectAnswer='#FF6666'; //red $('.answerButton').each(function() { var dataValue = $(this).data('value'); if (dataValue === false || dataValue === "false") @@ -114,10 +114,10 @@ function QuestionComponent({questions, numQuestion, handleClick, t, points}){ return ( <> {numQuestion < questions.length ? ( - <> +

{questions[numQuestion].getQuestion()}

-
+
@@ -126,22 +126,22 @@ function QuestionComponent({questions, numQuestion, handleClick, t, points}){ ))}
-

{t("questionView.question_counter")} {numQuestion}

- +

{t("questionView.question_counter")} {numQuestion+1}

+
) : ( <> - {creationHistoricalRecord.setDate(Date.now())} - {creationHistoricalRecord.setPoints(points)} - {console.log(creationHistoricalRecord.getRecord())} + {creationHistoricalRecord.setDate(Date.now())} + {creationHistoricalRecord.setPoints(points)} + {console.log(creationHistoricalRecord.getRecord())}

{t("questionView.finished_game")}

{points} {t("questionView.point")}

- )} ); + } function Answer({text, onClick, dataValue}){ diff --git a/webapp/src/custom.css b/webapp/src/custom.css index 6416c5ce..d7129caa 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -1094,34 +1094,47 @@ svg { } } /*------------------------------Question--------------------------------------------*/ +.questionContainer { + display: grid; + grid-template-areas: + "topPanel" + "answerPanel"; + gap: 1em; + width: fit-content; + width: 500px; /* Establecer un ancho fijo */ +} .answerPanel { - display: flex; - flex-wrap: wrap; - display: grid; - grid-template-columns: repeat(2, 1fr); /* Divide en dos columnas de igual tamaño */ - gap: 5px; /* Ajusta el espacio entre los botones */ + display: grid; /* Usamos display: grid para los elementos dentro de answerPanel */ + grid-template-columns: repeat(2, 1fr); + gap: 1em; + padding: 0.5em; + min-width: 0; } -.answerPanel button { - flex: 1 1 50%; /* Divide los botones en dos columnas */ - margin: 5px; /* Ajusta el margen entre los botones según sea necesario */ +.topPanel { + min-width: 0; } -.answerButton{ +.answerButton { margin-right: 10px; - background: #9f97ff; - border: none; - outline: none; - border-radius: 40px; - box-shadow: 0 0 10px #9f97ff; - cursor:pointer; - font-size: 16px; - color: white; - font-weight: 700; - margin: 0.5em; + background: #9f97ff; + border: none; + outline: none; + border-radius: 40px; + box-shadow: 0 0 10px #9f97ff; + cursor: pointer; + font-size: 21px; + color: black; + font-weight: 700; + margin: 0.5em; + width: 100%; + max-width: 200px; } +.questionContainer p, span{ + font-size: 20px; +} /*------------------------------Historical--------------------------------------------*/ /* Estilos para los botones */ .historicalButton { @@ -1156,3 +1169,25 @@ svg { margin:auto; } +.linkButton { + display: flex; + justify-content: center; + align-items: center; + width: 50em; + height: 45px; + background: #c285ff; + border: none; + outline: none; + border-radius: 40px; + box-shadow: 0 0 10px black; + cursor: pointer; + font-size: 1em; + color: black; + font-weight: 700; + margin: 0.5em; + text-decoration: none; +} + +h2{ + text-align: center; +} diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json index 3c2b04e4..c60f92a7 100644 --- a/webapp/src/translations/en/global.json +++ b/webapp/src/translations/en/global.json @@ -54,7 +54,7 @@ }, "questionView":{ "seconds":"seconds", - "question_counter":"Question counter :", + "question_counter":"Question number ", "end_countdown":"Time's up!", "finished_game":"The game has finished!", "point":"Points" diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json index 4ba9474d..661e4ff8 100644 --- a/webapp/src/translations/es/global.json +++ b/webapp/src/translations/es/global.json @@ -58,7 +58,7 @@ "title":"Menú del Juego" },"questionView":{ "seconds":"segundos", - "question_counter":"Número de pregunta : ", + "question_counter":"Pregunta nº ", "end_countdown":"¡Se acabó el tiempo!", "finished_game":"¡El juego se ha terminado!", "point":"Puntos" From 13b45b1b01e337dfe7adeca07fd74f0a3b8ccf8d Mon Sep 17 00:00:00 2001 From: lauratbg Date: Wed, 3 Apr 2024 18:36:46 +0200 Subject: [PATCH 27/66] Added Home test and some changes --- webapp/src/components/Home/Home.js | 4 +- webapp/src/components/Home/Home.test.js | 38 ++++++++++++ .../loginAndRegistration/AddUser.test.js | 59 ------------------- webapp/src/translations/en/global.json | 6 +- webapp/src/translations/es/global.json | 4 +- webapp/src/translations/tk/global.json | 4 +- 6 files changed, 50 insertions(+), 65 deletions(-) create mode 100644 webapp/src/components/Home/Home.test.js diff --git a/webapp/src/components/Home/Home.js b/webapp/src/components/Home/Home.js index 4c2c8f11..c67d3e54 100644 --- a/webapp/src/components/Home/Home.js +++ b/webapp/src/components/Home/Home.js @@ -26,8 +26,8 @@ function Home() {

- - + + W diff --git a/webapp/src/components/Home/Home.test.js b/webapp/src/components/Home/Home.test.js new file mode 100644 index 00000000..0d16902b --- /dev/null +++ b/webapp/src/components/Home/Home.test.js @@ -0,0 +1,38 @@ +import React from 'react'; +import { render, fireEvent, screen } from '@testing-library/react'; +import { BrowserRouter as Router } from 'react-router-dom'; +import Home from './Home'; + +// Mocking useTranslation hook +jest.mock('react-i18next', () => ({ + useTranslation: () => ({ t: key => key }), +})); + +describe('Home component', () => { + test('renders correctly and toggles text container visibility', () => { + render( + + + + ); + // The welcome messages must be shown + expect(screen.getByText('home.msg1')).toBeInTheDocument(); + expect(screen.getByText('home.msg2')).toBeInTheDocument(); + + // Click toggle open button + fireEvent.click(screen.getByTitle("home.clickOpen")); + + // Icons of instructions, login and signup must be shown + expect(screen.getByAltText('Instructions')).toBeVisible(); + expect(screen.getByAltText('Login')).toBeVisible(); + expect(screen.getByAltText('Add user')).toBeVisible(); + + + // Click toggle close button + fireEvent.click(screen.getByTitle('home.clickClose')); + + // The welcome messages must be shown + expect(screen.getByText('home.msg1')).toBeVisible(); + expect(screen.getByText('home.msg2')).toBeVisible(); + }); +}); diff --git a/webapp/src/components/loginAndRegistration/AddUser.test.js b/webapp/src/components/loginAndRegistration/AddUser.test.js index bc9954d8..8cf04089 100644 --- a/webapp/src/components/loginAndRegistration/AddUser.test.js +++ b/webapp/src/components/loginAndRegistration/AddUser.test.js @@ -27,62 +27,3 @@ describe('', () => { }); -// import React from 'react'; -// import { render, fireEvent, screen, waitFor } from '@testing-library/react'; -// import axios from 'axios'; -// import MockAdapter from 'axios-mock-adapter'; -// import AddUser from './AddUser'; - -// const mockAxios = new MockAdapter(axios); - -// describe('AddUser component', () => { -// beforeEach(() => { -// mockAxios.reset(); -// }); - -// it('should add user successfully', async () => { -// render(); - -// const usernameInput = screen.getByLabelText(/Username/i); -// const passwordInput = screen.getByLabelText(/Password/i); -// const addUserButton = screen.getByRole('button', { name: /Add User/i }); - -// // Mock the axios.post request to simulate a successful response -// mockAxios.onPost('http://localhost:8000/adduser').reply(200); - -// // Simulate user input -// fireEvent.change(usernameInput, { target: { value: 'testUser' } }); -// fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); - -// // Trigger the add user button click -// fireEvent.click(addUserButton); - -// // Wait for the Snackbar to be open -// await waitFor(() => { -// expect(screen.getByText(/User added successfully/i)).toBeInTheDocument(); -// }); -// }); - -// it('should handle error when adding user', async () => { -// render(); - -// const usernameInput = screen.getByLabelText(/Username/i); -// const passwordInput = screen.getByLabelText(/Password/i); -// const addUserButton = screen.getByRole('button', { name: /Add User/i }); - -// // Mock the axios.post request to simulate an error response -// mockAxios.onPost('http://localhost:8000/adduser').reply(500, { error: 'Internal Server Error' }); - -// // Simulate user input -// fireEvent.change(usernameInput, { target: { value: 'testUser' } }); -// fireEvent.change(passwordInput, { target: { value: 'testPassword' } }); - -// // Trigger the add user button click -// fireEvent.click(addUserButton); - -// // Wait for the error Snackbar to be open -// await waitFor(() => { -// expect(screen.getByText(/Error: Internal Server Error/i)).toBeInTheDocument(); -// }); -// }); -// }); diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json index d95b3eed..8baa3169 100644 --- a/webapp/src/translations/en/global.json +++ b/webapp/src/translations/en/global.json @@ -6,8 +6,10 @@ "register": "Don't have an account? Sign up here.", "language": "The language has been changed to English", "msg1": "Welcome to the knowledge challenge! Get ready to test your mind and demonstrate your skills. In this exciting game, you will face a series of questions that will test your knowledge on a variety of topics.", - "msg2": "So go ahead, prove that you are the master of questions! Are you ready to accept the challenge?" -}, + "msg2": "So go ahead, prove that you are the master of questions! Are you ready to accept the challenge?", + "clickOpen": "Click to continue", + "clickClose": "Click to close" + }, "navBar": { "title": "Know and win!", diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json index ab4d8be8..837364e9 100644 --- a/webapp/src/translations/es/global.json +++ b/webapp/src/translations/es/global.json @@ -6,7 +6,9 @@ "register": "¿No tienes una cuenta? Regístrate aquí.", "language": "El idioma ha sido cambiado a español", "msg1": "Bienvenido al desafío de conocimientos! Prepárate para poner a prueba tu mente y demostrar tus habilidades. En este emocionante juego, te enfrentarás a una serie de preguntas que pondrán a prueba tu conocimiento en una variedad de temas.", - "msg2": "¡Así que adelante, demuestra que eres el maestro de las preguntas! ¿Estás listo para aceptar el desafío?" + "msg2": "¡Así que adelante, demuestra que eres el maestro de las preguntas! ¿Estás listo para aceptar el desafío?", + "clickOpen": "Haz click para continuar", + "clickClose": "Haz click para cerrar" }, diff --git a/webapp/src/translations/tk/global.json b/webapp/src/translations/tk/global.json index e55a4d45..762fba93 100644 --- a/webapp/src/translations/tk/global.json +++ b/webapp/src/translations/tk/global.json @@ -6,7 +6,9 @@ "register": "Hesabınız yok mu? Buradan kaydolun.", "language": "Dil Türkçe olarak değiştirildi", "msg1": "Bilgi meydan okumasına hoş geldiniz! Zihninizi test etmeye ve becerilerinizi göstermeye hazır olun. Bu heyecan verici oyunda, çeşitli konulardaki bilginizi test edecek bir dizi soruyla karşılaşacaksınız.", - "msg2": "Öyleyse ilerleyin, soruların ustası olduğunuzu kanıtlayın! Meydan okumayı kabul etmeye hazır mısınız?" + "msg2": "Öyleyse ilerleyin, soruların ustası olduğunuzu kanıtlayın! Meydan okumayı kabul etmeye hazır mısınız?", + "clickOpen": "Devamı için tıklayınız", + "clickClose": "Kapatmak için tıklayın" }, "navBar": { From 675def7744b970a3be53695293f4b1ae7b4a3da8 Mon Sep 17 00:00:00 2001 From: uo289267 Date: Wed, 3 Apr 2024 21:39:43 +0200 Subject: [PATCH 28/66] Changed a bit the view of the navBar --- webapp/src/components/fragments/NavBar.js | 6 +++--- webapp/src/custom.css | 13 +++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/webapp/src/components/fragments/NavBar.js b/webapp/src/components/fragments/NavBar.js index f941719c..5b9b5308 100644 --- a/webapp/src/components/fragments/NavBar.js +++ b/webapp/src/components/fragments/NavBar.js @@ -26,10 +26,10 @@ function Navbar() { return (
+
- - {t("navBar.title")} - +

{t("navBar.title")}

+
Date: Wed, 3 Apr 2024 22:41:57 +0200 Subject: [PATCH 29/66] Added changes on view shown after playing the game --- .../HistoricalData/HistoricalView.js | 18 +++---------- .../components/HistoricalData/RecordList.js | 20 ++++++++++++++ webapp/src/components/fragments/NavBar.js | 1 - .../questionView/CreationHistoricalRecord.js | 24 ----------------- .../components/questionView/QuestionView.js | 20 +++++++++----- webapp/src/custom.css | 27 +++++++++++++++++-- 6 files changed, 62 insertions(+), 48 deletions(-) create mode 100644 webapp/src/components/HistoricalData/RecordList.js diff --git a/webapp/src/components/HistoricalData/HistoricalView.js b/webapp/src/components/HistoricalData/HistoricalView.js index cd57787f..19366492 100644 --- a/webapp/src/components/HistoricalData/HistoricalView.js +++ b/webapp/src/components/HistoricalData/HistoricalView.js @@ -1,6 +1,8 @@ import React, {useEffect, useState } from 'react'; import {useTranslation} from "react-i18next"; import HistoryRecordRetriever from './HistoryRecordRetriever'; +import RecordList from './RecordList'; + const retriever = new HistoryRecordRetriever(); @@ -38,21 +40,9 @@ function HistoricalGameElement({record,t}){ return (
- +
    - {record.questions.map((question, index) => (
  • -

    {question.question}

    -
      - {question.answers.map((answer, answerIndex) => ( -
    • - {answer} - {question.answerGiven === answer && " 👈 "} - {question.correctAnswer === answer && " ✅ "} -
    • - ))} -
    -
  • - ))} +
); diff --git a/webapp/src/components/HistoricalData/RecordList.js b/webapp/src/components/HistoricalData/RecordList.js new file mode 100644 index 00000000..fe100a0a --- /dev/null +++ b/webapp/src/components/HistoricalData/RecordList.js @@ -0,0 +1,20 @@ +export default function RecordList({record}){ + return ( + <> + {record.questions.map((question, index) => ( +
  • +

    {question.question}

    +
      + {question.answers.map((answer, answerIndex) => ( +
    • + {answer} + {question.answerGiven === answer && " 👈 "} + {question.correctAnswer === answer && " ✅ "} +
    • + ))} +
    +
  • + ))} + + ); +} \ No newline at end of file diff --git a/webapp/src/components/fragments/NavBar.js b/webapp/src/components/fragments/NavBar.js index 5b9b5308..4437ef9f 100644 --- a/webapp/src/components/fragments/NavBar.js +++ b/webapp/src/components/fragments/NavBar.js @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import Typography from "@mui/material/Typography"; import { Link } from 'react-router-dom'; import MenuItem from '@mui/material/MenuItem'; import Menu from '@mui/material/Menu'; diff --git a/webapp/src/components/questionView/CreationHistoricalRecord.js b/webapp/src/components/questionView/CreationHistoricalRecord.js index d89f1209..e7c6903e 100644 --- a/webapp/src/components/questionView/CreationHistoricalRecord.js +++ b/webapp/src/components/questionView/CreationHistoricalRecord.js @@ -34,27 +34,3 @@ class CreationHistoricalRecord{ } export default CreationHistoricalRecord; -/* -// Ejemplo de uso: -const userId = "userIdentifier"; -const record = new CreationHistoricalRecord(userId); - -record.addQuestion( - "¿Cuál es el río más largo del mundo?", - ["Nilo", "Amazonas", "Yangtsé", "Misisipi"], - "Amazonas", - "Amazonas" -); - -record.addQuestion( - "¿Cuál es el elemento más abundante en la corteza terrestre?", - ["Hierro", "Oxígeno", "Silicio", "Aluminio"], - "Oxígeno", - "Oxígeno" -); - -record.setPoints(2500); -record.setDate("02/02/24"); - -const recordRecord = record.getRecord(); -console.log(recordRecord);*/ \ No newline at end of file diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 43354f9a..17dce797 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -6,8 +6,7 @@ import React from "react"; import Countdown from 'react-countdown'; import {useTranslation} from "react-i18next"; import $ from 'jquery'; -import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; -import HistoricalView from '../HistoricalData/HistoricalView'; +import RecordList from '../HistoricalData/RecordList'; import ButtonHistoricalData from "../HistoricalData/ButtonHistoricalData"; const creationHistoricalRecord = new CreationHistoricalRecord(); @@ -44,9 +43,10 @@ function QuestionView(){ else{ $(this).css({ 'background-color': colorCorrectAnswer, - 'text-decoration': 'underline' // Underline the text of the button for correct answers + 'text-decoration': 'underline'// Underline the text of the button for correct answers }); } + $(this).css('pointer-events', 'none'); }); } @@ -55,7 +55,8 @@ function QuestionView(){ $('.answerButton').each(function() { $(this).css({ 'background-color': colorOriginal, - 'text-decoration': 'none' // Remove underline + 'text-decoration': 'none', // Remove underline + 'pointer-events': 'auto' }); }); } @@ -115,6 +116,7 @@ function QuestionComponent({questions, numQuestion, handleClick, t, points}){ <> {numQuestion < questions.length ? (
    +

    {questions[numQuestion].getQuestion()}

    @@ -126,15 +128,19 @@ function QuestionComponent({questions, numQuestion, handleClick, t, points}){ ))}
    -

    {t("questionView.question_counter")} {numQuestion+1}

    -
    +
    +

    {t("questionView.question_counter")} {numQuestion+1}

    +

    {points} {t("questionView.point")}

    +
    +
    + ) : ( <> {creationHistoricalRecord.setDate(Date.now())} {creationHistoricalRecord.setPoints(points)} - {console.log(creationHistoricalRecord.getRecord())}

    {t("questionView.finished_game")}

    {points} {t("questionView.point")}

    +
      < RecordList record={creationHistoricalRecord.getRecord().game}/>
    )} diff --git a/webapp/src/custom.css b/webapp/src/custom.css index 6bc0fa79..94426fb0 100644 --- a/webapp/src/custom.css +++ b/webapp/src/custom.css @@ -1103,6 +1103,12 @@ svg { gap: 1em; width: fit-content; width: 500px; /* Establecer un ancho fijo */ + align-items: center; /* Centrar horizontalmente */ + justify-content: center; /* Centrar verticalmente */ + position: fixed; /* Posición fija para centrar en la ventana */ + left: 50%; + top: 50%; + transform: translate(-50%, -50%); /* Mover el elemento hacia atrás en la mitad de su tamaño */ } .answerPanel { @@ -1115,6 +1121,7 @@ svg { .topPanel { min-width: 0; + width: 100%; } .answerButton { @@ -1129,13 +1136,19 @@ svg { color: black; font-weight: 700; margin: 0.5em; - width: 100%; max-width: 200px; } .questionContainer p, span{ font-size: 20px; } + +.bottomPanel{ + display: flex; + justify-content: space-between; + +} + /*------------------------------Historical--------------------------------------------*/ /* Estilos para los botones */ .historicalButton { @@ -1148,7 +1161,7 @@ svg { border-radius: 0.3em; font-weight: bold; cursor: pointer; - margin-bottom: 0.2em; /* Agrega espacio entre los botones */ + margin: 1em; } /* Estilos para los divs dentro de centered-div */ @@ -1169,6 +1182,16 @@ svg { align-self: center; margin:auto; } +.divMenu { + display: flex; + flex-direction: column; /* Colocar los elementos en una columna */ + align-items: center; /* Centrar horizontalmente */ + justify-content: center; /* Centrar verticalmente */ + position: fixed; /* Posición fija para centrar en la ventana */ + left: 50%; + top: 50%; + transform: translate(-50%, -50%); /* Mover el elemento hacia atrás en la mitad de su tamaño */ +} .linkButton { display: flex; From 7d283e2f677a9079124755aa4bcb7560f602ccc9 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Thu, 4 Apr 2024 17:55:31 +0200 Subject: [PATCH 30/66] Some test more, also solved issue of the warning --- package-lock.json | 106 ++++++++++++++++++++++ package.json | 3 + webapp/src/App.test.js | 28 +++++- webapp/src/components/Instructons.test.js | 31 +++++++ webapp/src/setupTests.js | 14 +++ 5 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 webapp/src/components/Instructons.test.js diff --git a/package-lock.json b/package-lock.json index ce1e9876..354f7e9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,9 +7,12 @@ "dependencies": { "@material-ui/core": "^4.12.4", "@material-ui/icons": "^4.11.3", + "@testing-library/react-hooks": "^8.0.1", "asciidoctor-emoji": "^0.5.0", "i18n": "^0.15.1", + "i18next": "^23.10.1", "react-countdown": "^2.3.5", + "react-i18next": "^14.1.0", "react-router-dom": "^6.22.1" }, "devDependencies": { @@ -1246,6 +1249,35 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@testing-library/react-hooks": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-8.0.1.tgz", + "integrity": "sha512-Aqhl2IVmLt8IovEVarNDFuJDVWVvhnr9/GCU6UUnrYXwgDFF9h2L2o2P9KBni1AST5sT6riAyoukFLyjQUgD/g==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "react-error-boundary": "^3.1.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0", + "react": "^16.9.0 || ^17.0.0", + "react-dom": "^16.9.0 || ^17.0.0", + "react-test-renderer": "^16.9.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-test-renderer": { + "optional": true + } + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2213,6 +2245,14 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "dependencies": { + "void-elements": "3.1.0" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -2246,6 +2286,28 @@ "url": "https://github.com/sponsors/mashpie" } }, + "node_modules/i18next": { + "version": "23.10.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.10.1.tgz", + "integrity": "sha512-NDiIzFbcs3O9PXpfhkjyf7WdqFn5Vq6mhzhtkXzj51aOcNuPNcTwuYNuXCpHsanZGHlHKL35G7huoFeVic1hng==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -3777,6 +3839,42 @@ "react": "17.0.2" } }, + "node_modules/react-error-boundary": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz", + "integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, + "node_modules/react-i18next": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.0.tgz", + "integrity": "sha512-3KwX6LHpbvGQ+sBEntjV4sYW3Zovjjl3fpoHbUwSgFHf0uRBcbeCBLR5al6ikncI5+W0EFb71QXZmfop+J6NrQ==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 23.2.3", + "react": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -4252,6 +4350,14 @@ "node": ">=10.12.0" } }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", diff --git a/package.json b/package.json index e3f47e10..cd13ae94 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,12 @@ "dependencies": { "@material-ui/core": "^4.12.4", "@material-ui/icons": "^4.11.3", + "@testing-library/react-hooks": "^8.0.1", "asciidoctor-emoji": "^0.5.0", "i18n": "^0.15.1", + "i18next": "^23.10.1", "react-countdown": "^2.3.5", + "react-i18next": "^14.1.0", "react-router-dom": "^6.22.1" }, "devDependencies": { diff --git a/webapp/src/App.test.js b/webapp/src/App.test.js index 7a9678db..505529b4 100644 --- a/webapp/src/App.test.js +++ b/webapp/src/App.test.js @@ -1,11 +1,33 @@ -import { render, screen } from '@testing-library/react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import App from './App'; test('renders learn react link', () => { render(); - expect(screen.getByText('navBar.title')).toBeInTheDocument(); - expect(screen.getByText('navBar.language')).toBeInTheDocument(); expect(screen.getByAltText('App logo')).toBeInTheDocument(); expect(screen.getByAltText('Help')).toBeInTheDocument(); }); + +describe('', () => { + test('Navbar renders correctly and language change works', async () => { + render( + + ); + + expect(screen.getByText('navBar.title')).toBeInTheDocument(); + expect(screen.getByText('navBar.language')).toBeInTheDocument(); + + // fireEvent.click(screen.getByText('navBar.language')); + + // // Cambiar idioma a español + // fireEvent.click(screen.getByText('navBar.es')); + + // Espera a que el cambio de idioma se refleje en el DOM + // await waitFor(() => { + // expect(screen.getByText('¡Saber y ganar!')).toBeInTheDocument(); + // }); + + + + }); +}); diff --git a/webapp/src/components/Instructons.test.js b/webapp/src/components/Instructons.test.js new file mode 100644 index 00000000..46a44b9c --- /dev/null +++ b/webapp/src/components/Instructons.test.js @@ -0,0 +1,31 @@ +import React from 'react'; +import { render, fireEvent, screen } from '@testing-library/react'; +import { BrowserRouter as Router } from 'react-router-dom'; +import Instructions from './Instructions'; + + +describe('Instructions component', () => { + test('Instructions renders correctly', () => { + render( + + + + ); + // The welcome messages must be shown + expect(screen.getByText('instructions.title')).toBeInTheDocument(); + expect(screen.getByText('instructions.objective')).toBeInTheDocument(); + expect(screen.getByText('instructions.objective_p1')).toBeInTheDocument(); + expect(screen.getByText('instructions.how_to_play_p1')).toBeInTheDocument(); + expect(screen.getByText('instructions.how_to_play_p2')).toBeInTheDocument(); + expect(screen.getByText('instructions.how_to_play_p3')).toBeInTheDocument(); + expect(screen.getByText('instructions.how_to_play_p4')).toBeInTheDocument(); + expect(screen.getByText('instructions.scoring')).toBeInTheDocument(); + expect(screen.getByText('instructions.scoring_p1')).toBeInTheDocument(); + expect(screen.getByText('instructions.scoring_p2')).toBeInTheDocument(); + expect(screen.getByText('instructions.time_limit_p1')).toBeInTheDocument(); + expect(screen.getByText('instructions.time_limit')).toBeInTheDocument(); + expect(screen.getByText('instructions.have_fun')).toBeInTheDocument(); + expect(screen.getByText('instructions.have_fun_p1')).toBeInTheDocument(); + + }); +}); diff --git a/webapp/src/setupTests.js b/webapp/src/setupTests.js index 8f2609b7..82638af3 100644 --- a/webapp/src/setupTests.js +++ b/webapp/src/setupTests.js @@ -3,3 +3,17 @@ // expect(element).toHaveTextContent(/react/i) // learn more: https://github.com/testing-library/jest-dom import '@testing-library/jest-dom'; + +import { initReactI18next } from 'react-i18next'; +import i18n from 'i18next'; + +// Configuración de i18next +i18n.use(initReactI18next).init({ + resources: {}, + lng: 'en', + interpolation: { + escapeValue: false, + }, +}); + +global.i18n = i18n; From 5bfc9c1b6a5d2f4cb5228c716dce2db427e49e60 Mon Sep 17 00:00:00 2001 From: uo289267 Date: Thu, 4 Apr 2024 22:06:01 +0200 Subject: [PATCH 31/66] Started jest tests --- .../src/components/GameMenu/GameMenu.test.js | 33 ++++++++++ .../HistoricalData/HistoricalView.test.js | 24 +++++++ .../components/questionView/QuestionView.js | 1 - .../questionView/QuestionView.test.js | 65 +++++++++++++++++++ 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 webapp/src/components/HistoricalData/HistoricalView.test.js create mode 100644 webapp/src/components/questionView/QuestionView.test.js diff --git a/webapp/src/components/GameMenu/GameMenu.test.js b/webapp/src/components/GameMenu/GameMenu.test.js index 5498ca93..265e27a4 100644 --- a/webapp/src/components/GameMenu/GameMenu.test.js +++ b/webapp/src/components/GameMenu/GameMenu.test.js @@ -2,9 +2,42 @@ import { render, screen } from '@testing-library/react'; import GameMenu from './GameMenu'; import { MemoryRouter } from 'react-router-dom'; +import { initReactI18next } from 'react-i18next'; +import i18en from 'i18next'; + +i18en.use(initReactI18next).init({ + resources: {}, + lng: 'en', + interpolation:{ + escapeValue: false, + } +}); +global.i18en = i18en; +/* test('renders learn react link', () => { render(); const linkElement = screen.getByText(/Game Menu/i); expect(linkElement).toBeInTheDocument(); +});*/ + +describe('GameMenu component', () => { + it('renders Title for Game Menu view', () => { + render(); + const text = screen.getByText(i18en.t('gameMenu.title')); + expect(text).toBeInTheDocument(); + }); + + it('renders option to create a new Game', () => { + render(); + const text = screen.getByText(i18en.t('gameMenu.new_game_button')); + expect(text).toBeInTheDocument(); + }); + + it('renders option to view historical data', () => { + render(); + const text = screen.getByText(i18en.t('gameMenu.history_button')); + expect(text).toBeInTheDocument(); + }); }); + diff --git a/webapp/src/components/HistoricalData/HistoricalView.test.js b/webapp/src/components/HistoricalData/HistoricalView.test.js new file mode 100644 index 00000000..cb176e6d --- /dev/null +++ b/webapp/src/components/HistoricalData/HistoricalView.test.js @@ -0,0 +1,24 @@ +import { initReactI18next } from 'react-i18next'; +import i18en from 'i18next'; + +i18en.use(initReactI18next).init({ + resources: {}, + lng: 'en', + interpolation:{ + escapeValue: false, + } +}); +global.i18en = i18en; + +describe('Historical View component', () => { + it('renders Game Record Buttons', () => { + /*render(); + const text = screen.getByText(i18en.t('gameMenu.title')); + expect(text).toBeInTheDocument();*/ + }); + it('clicking Game Record Buttons Record Lists are displayed', () => { + /*render(); + const text = screen.getByText(i18en.t('gameMenu.title')); + expect(text).toBeInTheDocument();*/ + }); +}); \ No newline at end of file diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 17dce797..8a29e8fd 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -95,7 +95,6 @@ function QuestionView(){ return (
    - {/*Nav*/} {numQuestion >= 0 ? :

    Please Wait a bit...

    } diff --git a/webapp/src/components/questionView/QuestionView.test.js b/webapp/src/components/questionView/QuestionView.test.js new file mode 100644 index 00000000..fffe0619 --- /dev/null +++ b/webapp/src/components/questionView/QuestionView.test.js @@ -0,0 +1,65 @@ +import { render, screen ,fireEvent } from '@testing-library/react'; +import { initReactI18next } from 'react-i18next'; +import i18en from 'i18next'; +import QuestionView from './QuestionView'; +import { MemoryRouter } from 'react-router-dom'; +import { act } from 'react-dom/test-utils'; +import {queryHelpers, buildQueries} from '@testing-library/react' + + +i18en.use(initReactI18next).init({ + resources: {}, + lng: 'en', + interpolation:{ + escapeValue: false, + } +}); +global.i18en = i18en; + +describe('Question View component', () => { + it('renders a question', () => { + act(() => { + render(); + }); + //h2 con la pregunta + const tituloH2 = screen.getByRole('heading', { level: 2 }); + // Verifica si el elemento h2 está presente en el documento + expect(tituloH2).toBeInTheDocument(); + }); + it('render a question and 4 buttons for answers', () => { + act(() => { + render(); + }); + // Busca todos los botones por su rol + const botones = screen.getAllByRole('button'); + + // Verifica si hay exactamente 4 botones + expect(botones.length).toBe(4); + }); + it('shows colors to reveal correct answer', () => { + act(() => { + render(); + fireEvent.click(queryHelpers.queryByAttribute('data-value', 'true'));//clicamos en la respuesta correcta + }); + + // Clic en un botón de respuesta con data-value=true + const correctAnswerButton = queryHelpers.queryByAttribute('data-value', 'true'); + // Verificar que el botón tenga el color esperado + expect(correctAnswerButton).toHaveStyle('background-color: #6EF26E'); + }); + it('shows colors to reveal false answer', () => { + act(() => { + render(); + const falseAnswerButtons = (dataValue)=> queryHelpers.queryAllByAttribute('data-value', dataValue)('false'); + fireEvent.click(falseAnswerButtons.get(0)); + }); + + + // Obtener el botón de respuesta falso por su atributo data-value + const falseAnswerButton = queryHelpers.queryAllByAttribute('data-value', 'false').get(0); + + // Verificar que el botón tenga el color esperado + expect(falseAnswerButton).toHaveStyle('background-color:#FF6666'); + + }); +}); \ No newline at end of file From 0d4041cb6d9840a7c63dcbc2334494b4c31dfd61 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Thu, 4 Apr 2024 23:58:08 +0200 Subject: [PATCH 32/66] Added new endpoint to get questions by language and reduced the amount of questions returned by 5 that are random --- gatewayservice/gateway-service.js | 18 ++++++++++-- questionGenerator/src/main/java/Main.java | 1 - .../questionGenerator/question/Question.java | 5 ---- questionservice/question-model.js | 3 +- questionservice/question-service.js | 28 +++++++++++++++++-- .../questionView/QuestionGenerator.js | 21 ++------------ 6 files changed, 46 insertions(+), 30 deletions(-) diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index b145db56..15da77b2 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -45,8 +45,20 @@ app.post('/adduser', async (req, res) => { app.get('/questions', async (req, res) => { try { + // Forward the question request to the quetion service - const quetionResponse = await axios.get(questionServiceUrl+'/questions', req.params); + const quetionResponse = await axios.get(questionServiceUrl+'/questions'); + res.send(quetionResponse.data); + } catch (error) { + res.status(error.response.status).json({ error: error.response.data.error }); + } +}); + +app.get('/questions/:lang', async (req, res) => { + try { + const lang = req.params.lang; + // Forward the question request to the quetion service + const quetionResponse = await axios.get(questionServiceUrl+'/questions/' + lang); res.send(quetionResponse.data); } catch (error) { res.status(error.response.status).json({ error: error.response.data.error }); @@ -63,11 +75,11 @@ app.post('/addrecord', async(req, res) => { } }); -app.get('/records/:user', async(req, res)=>{ +app.get('/record/:user', async(req, res)=>{ try { const user = req.params.user; // Forward the record request to the record service - const recordResponse = await axios.get(recordServiceUrl + '/records/' + user); + const recordResponse = await axios.get(recordServiceUrl + '/record/' + user); res.json(recordResponse.data); } catch (error) { res.send(error); diff --git a/questionGenerator/src/main/java/Main.java b/questionGenerator/src/main/java/Main.java index 41a0d999..099adce8 100644 --- a/questionGenerator/src/main/java/Main.java +++ b/questionGenerator/src/main/java/Main.java @@ -41,7 +41,6 @@ private static void run(QuestionGenerator qg, QuestionType type) { //Populate JSON list here for(int i=0; i<3; i++) { Question question = qg.generateQuestion(type); - question.setNumber(i); questionJSONList.add(question.getJSON().toString()); System.out.println(question.getJSON().toString()); } diff --git a/questionGenerator/src/main/java/questionGenerator/question/Question.java b/questionGenerator/src/main/java/questionGenerator/question/Question.java index 7068cbd6..900e3b49 100644 --- a/questionGenerator/src/main/java/questionGenerator/question/Question.java +++ b/questionGenerator/src/main/java/questionGenerator/question/Question.java @@ -9,7 +9,6 @@ public class Question { private String question; private List answers; - private int number = -1; private String language; private QuestionType type; @@ -44,16 +43,12 @@ public void addRightAnswer(String answer) { answers.add(0, answer); } - public void setNumber(int number){ - this.number = number; - } public JSONObject getJSON() { JSONObject json = new JSONObject(); json.accumulate("question", question); for(String s : answers) json.accumulate("answers", s); - if(number != -1) json.accumulate("number", number); //Para que los tests pasen json.accumulate("language", language); json.accumulate("type", type); return json; diff --git a/questionservice/question-model.js b/questionservice/question-model.js index 26c275f0..7b8cea8f 100644 --- a/questionservice/question-model.js +++ b/questionservice/question-model.js @@ -3,7 +3,8 @@ const mongoose = require('mongoose'); const questionSchema = new mongoose.Schema({ question: String, answers: [String], - number: Number + language: String, + type: String }); const Question = mongoose.model('Question', questionSchema); diff --git a/questionservice/question-service.js b/questionservice/question-service.js index a09e78eb..026feb5c 100644 --- a/questionservice/question-service.js +++ b/questionservice/question-service.js @@ -12,8 +12,9 @@ mongoose.connect(mongoUri); app.get('/questions', async (req, res) => { try { // Find the question by it's number - const questions = await Question.find({}); - //const question = await Question.find({number: { $in: ['0', '1']}}); And I can find many that way + const questions = await Question.aggregate([ + {$sample: {size:5}} //5 random from the ones that fullfil the condition + ]); let jsonResult = {}; for (let i = 0; i < questions.length; i++) { @@ -29,6 +30,29 @@ app.get('/questions', async (req, res) => { } }); +app.get('/questions/:lang', async (req, res) => { + try { + const lang = req.params.lang; + + const questions = await Question.aggregate([ + {$match: {language : lang}}, //Condition + {$sample: {size:5}} //5 random from the ones that fullfil the condition + ]); + + let jsonResult = {}; + for (let i = 0; i < questions.length; i++) { + const question = questions[i]; + jsonResult[i] = { + question : question.question, + answers : question.answers + } + } + res.json(jsonResult); + } catch (error) { + res.status(500).json({ error: 'Internal Server Error' }); + } +}); + const server = app.listen(port, () => { console.log(`Question Service listening at http://localhost:${port}`); diff --git a/webapp/src/components/questionView/QuestionGenerator.js b/webapp/src/components/questionView/QuestionGenerator.js index e225c73a..a4c41303 100644 --- a/webapp/src/components/questionView/QuestionGenerator.js +++ b/webapp/src/components/questionView/QuestionGenerator.js @@ -6,25 +6,10 @@ class QuestionGenerator{ } - async generateQuestions() { + async generateQuestions(lang) { try { - //const response = await fetch(this.apiUrl); - //const receivedQuestions = await response.json(); - - //Mockup - const receivedQuestions = JSON.parse('{"0":{"question":"¿Cuál es la población de Oviedo?","answers":["225089","191325","220587","121548"]},'+ - '"1":{"question":"¿Cuál es la población de Gijón?","answers":["275274","159658","233982","305554"]},'+ - '"2":{"question":"¿Cuál es la población de Avilés?","answers":["82568","115595","41284","122200"]},'+ - '"3":{"question":"¿Cuál es la capital de Asturias?","answers":["Ciudad de Oviedo","a","b","c"]},'+ - '"4":{"question":"¿Cuál es la capital de España?","answers":["Madrid","a","b","c"]},'+ - '"5":{"question":"¿Cuál es la capital de Turquía?","answers":["Ankara","a","b","c"]},'+ - '"6":{"question":"¿Cuál es el área (km cuadrados) de España?","answers":["505990","a","b","c"]},'+ - '"7":{"question":"¿Cuál es el área (km cuadrados) de Gijón?","answers":["184.31","a","b","c"]},'+ - '"8":{"question":"¿Cuál es el área (km cuadrados) de Asturias?","answers":["10603.57","a","b","c"]},'+ - '"9":{"question":"¿Cuál es el idioma oficial de España?","answers":["español","a","b","c"]},'+ - '"10":{"question":"¿Cuál es el idioma oficial de Turquía?","answers":["turco","a","b","c"]},'+ - '"11":{"question":"¿Cuál es el idioma oficial de Asturias?","answers":["español","a","b","c"]},'+ - '"12":{"question":"Whats the population of Oviedo?","answers":["225089","216085","285863","243096"]}}') + const response = await fetch(this.apiUrl + '/' + lang); + const receivedQuestions = await response.json(); let i = 0; var questions = []; From 28983a3be8e3ef5ef88f055a73b44e347346ab22 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Fri, 5 Apr 2024 00:39:40 +0200 Subject: [PATCH 33/66] Incorporated the new questions endpoint into the webapp and randomized the answers position --- webapp/src/components/questionView/Question.js | 14 +++++++++++++- .../components/questionView/QuestionGenerator.js | 2 -- webapp/src/components/questionView/QuestionView.js | 4 ++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/webapp/src/components/questionView/Question.js b/webapp/src/components/questionView/Question.js index 37a6d6f3..b79c53f4 100644 --- a/webapp/src/components/questionView/Question.js +++ b/webapp/src/components/questionView/Question.js @@ -3,8 +3,9 @@ import "../../custom.css"; class Question{ constructor(json){ this.question = json.question; - this.answers = json.answers; this.correctAnswer = json.answers[0]; + this.answers = this.shuffleArray(json.answers); + } getQuestion(){ @@ -20,6 +21,17 @@ class Question{ isCorrect(answer){ return answer===this.correctAnswer; } + + shuffleArray(array) { + let innerArray = [...array]; // Copies array + for (let i = innerArray.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); // Generate a random index between 0 and i + const temp = innerArray[i]; // Swap innerArray[i] and innerArray[j] + innerArray[i] = innerArray[j]; + innerArray[j] = temp; + } + return innerArray; + } } diff --git a/webapp/src/components/questionView/QuestionGenerator.js b/webapp/src/components/questionView/QuestionGenerator.js index a4c41303..b139c517 100644 --- a/webapp/src/components/questionView/QuestionGenerator.js +++ b/webapp/src/components/questionView/QuestionGenerator.js @@ -10,14 +10,12 @@ class QuestionGenerator{ try { const response = await fetch(this.apiUrl + '/' + lang); const receivedQuestions = await response.json(); - let i = 0; var questions = []; for (const key in receivedQuestions) { questions[i] = new Question(receivedQuestions[key]); i += 1; } - console.log(questions); return questions; } catch (error) { throw new Error(error); diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 43354f9a..9abca3b1 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -16,13 +16,13 @@ var points = 0; function QuestionView(){ const [numQuestion, setnumQuestion] = useState(-1); const [questions, setQuestions] = useState([]); - const[t] = useTranslation("global"); + const[t, i18n] = useTranslation("global"); const generateQuestions = async (numQuestion) => { if (numQuestion < 0) { try { - var generatedQuestions = await questionGenerator.generateQuestions(); + var generatedQuestions = await questionGenerator.generateQuestions(i18n.language); setQuestions(generatedQuestions); setnumQuestion(0); } catch (error) { From d7e429ac7212e8754d67025961fe99fc26f2145f Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Fri, 5 Apr 2024 01:28:34 +0200 Subject: [PATCH 34/66] Added logic so the webapp can receive the user information --- gatewayservice/gateway-service.js | 3 +- questionGenerator/src/main/java/Main.java | 1 - webapp/src/App.js | 33 ++++++++++--------- webapp/src/components/fragments/NavBar.js | 8 +++++ .../loginAndRegistration/AddUser.js | 6 ++-- .../components/loginAndRegistration/Login.js | 4 ++- .../loginAndRegistration/UserContext.js | 19 +++++++++++ 7 files changed, 54 insertions(+), 20 deletions(-) create mode 100644 webapp/src/components/loginAndRegistration/UserContext.js diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 15da77b2..c7696276 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -37,6 +37,7 @@ app.post('/adduser', async (req, res) => { try { // Forward the add user request to the user service const userResponse = await axios.post(userServiceUrl+'/adduser', req.body); + console.log(userResponse) res.json(userResponse.data); } catch (error) { res.status(error.response.status).json({ error: error.response.data.error }); @@ -69,7 +70,7 @@ app.post('/addrecord', async(req, res) => { try { // Forward the record request to the record service const recordResponse = await axios.post(recordServiceUrl+'/addrecord', req.body); - res.send(recordResponse.data); + res.json(recordResponse.data); } catch (error) { res.send(error); } diff --git a/questionGenerator/src/main/java/Main.java b/questionGenerator/src/main/java/Main.java index 099adce8..abf4fcf6 100644 --- a/questionGenerator/src/main/java/Main.java +++ b/questionGenerator/src/main/java/Main.java @@ -42,7 +42,6 @@ private static void run(QuestionGenerator qg, QuestionType type) { for(int i=0; i<3; i++) { Question question = qg.generateQuestion(type); questionJSONList.add(question.getJSON().toString()); - System.out.println(question.getJSON().toString()); } QuestionRepository.getInstance().insert(questionJSONList); diff --git a/webapp/src/App.js b/webapp/src/App.js index 17434c1a..5eefcf70 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -10,25 +10,28 @@ import Container from '@mui/material/Container'; import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; import './custom.css'; import HistoricalView from './components/HistoricalData/HistoricalView'; +import { UserContextProvider } from './components/loginAndRegistration/UserContext'; function App() { return ( -
    - - - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - -
    + +
    + + + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + +
    +
    ); } diff --git a/webapp/src/components/fragments/NavBar.js b/webapp/src/components/fragments/NavBar.js index f941719c..cc6d5408 100644 --- a/webapp/src/components/fragments/NavBar.js +++ b/webapp/src/components/fragments/NavBar.js @@ -5,11 +5,14 @@ import MenuItem from '@mui/material/MenuItem'; import Menu from '@mui/material/Menu'; import "../../custom.css"; import { useTranslation } from "react-i18next"; +import { useUserContext } from '../loginAndRegistration/UserContext'; + function Navbar() { const [t, i18n] = useTranslation("global"); const [anchorEl, setAnchorEl] = useState(null); + const { user } = useUserContext(); const handleLanguageMenuOpen = (event) => { setAnchorEl(event.currentTarget); @@ -42,6 +45,11 @@ function Navbar() { changeLanguage("tk")}> {t("navBar.tk")}
    + {user != null ? ( + + {user.username} + + ) : null}
    ); diff --git a/webapp/src/components/loginAndRegistration/AddUser.js b/webapp/src/components/loginAndRegistration/AddUser.js index db2c88cf..9bd8e853 100644 --- a/webapp/src/components/loginAndRegistration/AddUser.js +++ b/webapp/src/components/loginAndRegistration/AddUser.js @@ -6,6 +6,7 @@ import axios from 'axios'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; + const AddUser = () => { const navigate = useNavigate(); const apiUrl = (process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000') + "/adduser"; @@ -14,14 +15,15 @@ const AddUser = () => { const [password, setPassword] = useState(''); const [repeatPassword, setRepeatPassword] = useState(''); + const handleSubmit = async (event) => { event.preventDefault(); try { //TODO: Add more validations if(password === repeatPassword){ //User put the same password const response = await axios.post(apiUrl, { username, password }); - console.log("Registered user: " + response.body.username); - navigate('/menu'); + console.log("Registered user: " + response.data.username); + navigate('/login'); } else{ //TODO: Show some errors to the user diff --git a/webapp/src/components/loginAndRegistration/Login.js b/webapp/src/components/loginAndRegistration/Login.js index cb54c87a..f1aec5c4 100644 --- a/webapp/src/components/loginAndRegistration/Login.js +++ b/webapp/src/components/loginAndRegistration/Login.js @@ -5,6 +5,7 @@ import "../../custom.css"; import axios from 'axios'; import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; +import { useUserContext } from "./UserContext"; const Login = () => { const navigate = useNavigate(); @@ -12,12 +13,13 @@ const Login = () => { const { t } = useTranslation("global"); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); + const { setUser } = useUserContext(); const handleSubmit = async (event) => { event.preventDefault(); try { const response = await axios.post(apiUrl, { username, password }); - console.log("Hello " + response.username); + setUser({username : response.data.username, token : response.data.token}) //Used to redirect to the menu to start playing navigate('/menu'); } catch (error) { diff --git a/webapp/src/components/loginAndRegistration/UserContext.js b/webapp/src/components/loginAndRegistration/UserContext.js new file mode 100644 index 00000000..f551b9c8 --- /dev/null +++ b/webapp/src/components/loginAndRegistration/UserContext.js @@ -0,0 +1,19 @@ +import React, { createContext, useContext, useState } from 'react'; + +const UserContext = createContext(); + +export function UserContextProvider({ children }) { + const [user, setUser] = useState(null); + + return ( + + {children} + + ); +} + +export function useUserContext() { + return useContext(UserContext); +} + + From cbcdfe28b09f71f423fca3fdc28c7d81d6077b18 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Fri, 5 Apr 2024 09:44:57 +0200 Subject: [PATCH 35/66] Added functionality so the webapp uses the record service to add and retrieve records --- gatewayservice/gateway-service.js | 5 +- users/recordservice/record-service.js | 8 +- .../HistoricalData/HistoricalView.js | 14 +++- .../HistoricalData/HistoryRecordRetriever.js | 77 ++----------------- .../questionView/CreationHistoricalRecord.js | 30 +++++++- .../components/questionView/QuestionView.js | 15 ++-- 6 files changed, 63 insertions(+), 86 deletions(-) diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index c7696276..cb49f10a 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -37,7 +37,6 @@ app.post('/adduser', async (req, res) => { try { // Forward the add user request to the user service const userResponse = await axios.post(userServiceUrl+'/adduser', req.body); - console.log(userResponse) res.json(userResponse.data); } catch (error) { res.status(error.response.status).json({ error: error.response.data.error }); @@ -66,10 +65,10 @@ app.get('/questions/:lang', async (req, res) => { } }); -app.post('/addrecord', async(req, res) => { +app.post('/record', async(req, res) => { try { // Forward the record request to the record service - const recordResponse = await axios.post(recordServiceUrl+'/addrecord', req.body); + const recordResponse = await axios.post(recordServiceUrl+'/record', req.body); res.json(recordResponse.data); } catch (error) { res.send(error); diff --git a/users/recordservice/record-service.js b/users/recordservice/record-service.js index aa0ace2b..dd383984 100644 --- a/users/recordservice/record-service.js +++ b/users/recordservice/record-service.js @@ -18,6 +18,8 @@ mongoose.connect(mongoUri); app.post('/record', async (req, res) => { const user = req.body.user; const game = req.body.game; + console.log(user) + console.log(game) if(user && game){ let record = await Record.findOne({ user : user }); if(record){ //If it exits @@ -34,11 +36,13 @@ app.post('/record', async (req, res) => { const savedRecord = await record.save(); res.json({user:savedRecord.user}); } catch (err) { - console.log(err); res.status(500).send(); } } - res.status(400).send(); + else{ + res.status(400).send(); + } + }); app.get('/record/:user', async (req, res) => { diff --git a/webapp/src/components/HistoricalData/HistoricalView.js b/webapp/src/components/HistoricalData/HistoricalView.js index cd57787f..aa868374 100644 --- a/webapp/src/components/HistoricalData/HistoricalView.js +++ b/webapp/src/components/HistoricalData/HistoricalView.js @@ -1,17 +1,23 @@ import React, {useEffect, useState } from 'react'; import {useTranslation} from "react-i18next"; import HistoryRecordRetriever from './HistoryRecordRetriever'; +import { useUserContext } from '../loginAndRegistration/UserContext'; + + const retriever = new HistoryRecordRetriever(); export default function HistoricalView() { const [records, setRecords]= useState([]); const[t] = useTranslation("global"); + const {user} = useUserContext(); const getRecords = async ()=>{ + console.log("in") try { - var jsonRecords = await retriever.getRecords(); // Obtener el JSON de registros - var recordsArray = jsonRecords['games']; + var jsonRecords = await retriever.getRecords("M"); // Obtener el JSON de registros + var recordsArray = jsonRecords.games; + console.log(recordsArray) setRecords(recordsArray); } catch (error) { //Como hacer que funcione esto @@ -30,6 +36,7 @@ export default function HistoricalView() { function HistoricalGameElement({record,t}){ + console.log(record) const [toggle, setToggle] = useState(false); function handleClick (){ @@ -38,7 +45,8 @@ function HistoricalGameElement({record,t}){ return (
    - +
      {record.questions.map((question, index) => (
    • {question.question}

      diff --git a/webapp/src/components/HistoricalData/HistoryRecordRetriever.js b/webapp/src/components/HistoricalData/HistoryRecordRetriever.js index 2ca7715b..a261ad7f 100644 --- a/webapp/src/components/HistoricalData/HistoryRecordRetriever.js +++ b/webapp/src/components/HistoricalData/HistoryRecordRetriever.js @@ -2,82 +2,15 @@ class HistoryRecordRetriever{ constructor(){ - this.apiUrl = (process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000') + "/questions"; + this.apiUrl = (process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000') + "/record"; } - async getRecords() { + async getRecords(user) { try { - //const response = await fetch(this.apiUrl); - //const receivedQuestions = await response.json(); - - //Mockup - const receivedRecords = { - "userIdentification": "prob email or username", - "games": [ - { - "questions": [ - { - "question": "¿Cuál es la capital de Francia?", - "answers": ["Madrid", "París", "Londres", "Roma"], - "answerGiven": "París", - "correctAnswer": "París" - }, - { - "question": "¿En qué año comenzó la Segunda Guerra Mundial?", - "answers": ["1939", "1945", "1914", "1941"], - "answerGiven": "1939", - "correctAnswer": "1939" - }, - { - "question": "¿Quién escribió 'Don Quijote de la Mancha'?", - "answers": ["Miguel de Cervantes", "Gabriel García Márquez", "Federico García Lorca", "Jorge Luis Borges"], - "answerGiven": "Miguel de Cervantes", - "correctAnswer": "Miguel de Cervantes" - } - ], - "points": 3000, - "date": new Date("01/02/24") - }, - { - "questions": [ - { - "question": "¿Cuál es el río más largo del mundo?", - "answers": ["Nilo", "Amazonas", "Yangtsé", "Misisipi"], - "answerGiven": "no-answer", - "correctAnswer": "Amazonas" - }, - { - "question": "¿Cuál es el elemento más abundante en la corteza terrestre?", - "answers": ["Hierro", "Oxígeno", "Silicio", "Aluminio"], - "answerGiven": "Oxígeno", - "correctAnswer": "Oxígeno" - } - ], - "points": 2500, - "date": new Date("02/02/24") - }, - { - "questions": [ - { - "question": "¿Quién pintó la Mona Lisa?", - "answers": ["Leonardo da Vinci", "Pablo Picasso", "Vincent van Gogh", "Rembrandt"], - "answerGiven": "Leonardo da Vinci", - "correctAnswer": "Leonardo da Vinci" - }, - { - "question": "¿Cuál es el planeta más grande del sistema solar?", - "answers": ["Júpiter", "Saturno", "Neptuno", "Urano"], - "answerGiven": "Júpiter", - "correctAnswer": "Saturno" - } - ], - "points": 3500, - "date": new Date("03/02/24") - } - ] - }; - return receivedRecords; + const response = await fetch(this.apiUrl + '/' + user); + const receivedRecords = await response.json(); + return receivedRecords.record; } catch (error) { throw new Error(error); } diff --git a/webapp/src/components/questionView/CreationHistoricalRecord.js b/webapp/src/components/questionView/CreationHistoricalRecord.js index d89f1209..6baf4b76 100644 --- a/webapp/src/components/questionView/CreationHistoricalRecord.js +++ b/webapp/src/components/questionView/CreationHistoricalRecord.js @@ -2,7 +2,6 @@ class CreationHistoricalRecord{ constructor() { this.record = { - user: "a", game: { questions: [] } @@ -32,6 +31,35 @@ class CreationHistoricalRecord{ return this.record; } + + async sendRecord(user) { + const apiUrl = (process.env.REACT_APP_API_ENDPOINT || 'http://localhost:8000') + "/record"; + + const body = { + user:user, + game:this.record.game + } + console.log(body) + try { + const response = await fetch(apiUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + }); + + if (!response.ok) { + throw new Error('Error al enviar el registro'); + } + + const data = await response.json(); + console.log(data); + } catch (error) { + console.error('Error:', error); + } + } + } export default CreationHistoricalRecord; /* diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 9abca3b1..53c50d67 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -9,6 +9,7 @@ import $ from 'jquery'; import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; import HistoricalView from '../HistoricalData/HistoricalView'; import ButtonHistoricalData from "../HistoricalData/ButtonHistoricalData"; +import { useUserContext } from '../loginAndRegistration/UserContext'; const creationHistoricalRecord = new CreationHistoricalRecord(); const questionGenerator = new QuestionGenerator(); @@ -17,7 +18,7 @@ function QuestionView(){ const [numQuestion, setnumQuestion] = useState(-1); const [questions, setQuestions] = useState([]); const[t, i18n] = useTranslation("global"); - + const {user} = useUserContext(); const generateQuestions = async (numQuestion) => { if (numQuestion < 0) { @@ -78,7 +79,6 @@ function QuestionView(){ //compute the points for the answer given computePointsForQuestion(questions[numQuestion].getCorrectAnswer(), text); - console.log(creationHistoricalRecord.getRecord()); //reveal answer to user for 1 sec revealColorsForAnswers(); setTimeout(function() { @@ -86,6 +86,13 @@ function QuestionView(){ setColorsBackToNormal(); //sum one to the number of questions setnumQuestion(numQuestion + 1); + + if(!(numQuestion < questions.length - 1)){ + console.log("pasa") + creationHistoricalRecord.setDate(Date.now()); + creationHistoricalRecord.setPoints(points); + creationHistoricalRecord.sendRecord(user.username); + } }, 1000); } @@ -103,6 +110,7 @@ function QuestionView(){ function QuestionComponent({questions, numQuestion, handleClick, t, points}){ + const renderer = ({seconds, completed }) => { if (completed) { return {t("questionView.end_countdown")}; // Rendered when countdown completes @@ -130,9 +138,6 @@ function QuestionComponent({questions, numQuestion, handleClick, t, points}){
    ) : ( <> - {creationHistoricalRecord.setDate(Date.now())} - {creationHistoricalRecord.setPoints(points)} - {console.log(creationHistoricalRecord.getRecord())}

    {t("questionView.finished_game")}

    {points} {t("questionView.point")}

    From bf29756aad1aec06659df1fb1718aebc87817377 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Fri, 5 Apr 2024 16:15:17 +0200 Subject: [PATCH 36/66] Change navBar test, maybe all done? --- webapp/src/App.test.js | 25 +----------------- .../src/components/fragments/NavBar.test.js | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 24 deletions(-) create mode 100644 webapp/src/components/fragments/NavBar.test.js diff --git a/webapp/src/App.test.js b/webapp/src/App.test.js index 505529b4..96c26284 100644 --- a/webapp/src/App.test.js +++ b/webapp/src/App.test.js @@ -4,30 +4,7 @@ import App from './App'; test('renders learn react link', () => { render(); - expect(screen.getByAltText('App logo')).toBeInTheDocument(); - expect(screen.getByAltText('Help')).toBeInTheDocument(); + }); -describe('', () => { - test('Navbar renders correctly and language change works', async () => { - render( - - ); - expect(screen.getByText('navBar.title')).toBeInTheDocument(); - expect(screen.getByText('navBar.language')).toBeInTheDocument(); - - // fireEvent.click(screen.getByText('navBar.language')); - - // // Cambiar idioma a español - // fireEvent.click(screen.getByText('navBar.es')); - - // Espera a que el cambio de idioma se refleje en el DOM - // await waitFor(() => { - // expect(screen.getByText('¡Saber y ganar!')).toBeInTheDocument(); - // }); - - - - }); -}); diff --git a/webapp/src/components/fragments/NavBar.test.js b/webapp/src/components/fragments/NavBar.test.js new file mode 100644 index 00000000..ec3a4832 --- /dev/null +++ b/webapp/src/components/fragments/NavBar.test.js @@ -0,0 +1,26 @@ +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import App from "../../App"; + +describe('', () => { + test('Navbar renders correctly', async () => { + render( + + ); + + expect(screen.getByAltText('App logo')).toBeInTheDocument(); + expect(screen.getByAltText('Help')).toBeInTheDocument(); + expect(screen.getByText('navBar.title')).toBeInTheDocument(); + expect(screen.getByText('navBar.language')).toBeInTheDocument(); + + fireEvent.click(screen.getByText('navBar.language')); + + // Change to spanish + fireEvent.click(screen.getByText('navBar.es')); + + // Go to instructions + fireEvent.click(screen.getByAltText('Help')); + expect(screen.getByText('instructions.title')).toBeInTheDocument(); + + + }); + }); \ No newline at end of file From 84d94e2d140d5858faba5f19939823b2e9fb26d3 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sat, 6 Apr 2024 12:04:26 +0200 Subject: [PATCH 37/66] Fixed typo where repeat password had no label --- .../components/loginAndRegistration/AddUser.js | 15 ++++++++------- .../src/components/questionView/QuestionView.js | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/webapp/src/components/loginAndRegistration/AddUser.js b/webapp/src/components/loginAndRegistration/AddUser.js index 9bd8e853..b065f007 100644 --- a/webapp/src/components/loginAndRegistration/AddUser.js +++ b/webapp/src/components/loginAndRegistration/AddUser.js @@ -61,13 +61,14 @@ const AddUser = () => { />

    - setRepeatPassword(e.target.value)} - /> +

    {t("addUser.repeat_password_placeholder")}:

    + setRepeatPassword(e.target.value)} + />
    diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 53c50d67..85e588c2 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -87,8 +87,8 @@ function QuestionView(){ //sum one to the number of questions setnumQuestion(numQuestion + 1); + //Last question sends the record if(!(numQuestion < questions.length - 1)){ - console.log("pasa") creationHistoricalRecord.setDate(Date.now()); creationHistoricalRecord.setPoints(points); creationHistoricalRecord.sendRecord(user.username); From 4467576528929fbbba6f5a2cfa3414f9ab99c20b Mon Sep 17 00:00:00 2001 From: uo289267 Date: Sat, 6 Apr 2024 18:29:41 +0200 Subject: [PATCH 38/66] added new test mock tries --- .../components/questionView/QuestionView.js | 2 +- .../questionView/QuestionView.test.js | 22 ++++++++++++++++--- .../questionView/mocks/QuestionGenerator.js | 20 +++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 webapp/src/components/questionView/mocks/QuestionGenerator.js diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 8a29e8fd..26c2f590 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -36,7 +36,7 @@ function QuestionView(){ let colorCorrectAnswer='#6EF26E';//green let colorIncorrectAnswer='#FF6666'; //red $('.answerButton').each(function() { - var dataValue = $(this).data('value'); + var dataValue = $(this).attr('data-value'); if (dataValue === false || dataValue === "false") $(this).css('background-color', colorIncorrectAnswer); // Cambia el color de fondo del botón actual a rojo diff --git a/webapp/src/components/questionView/QuestionView.test.js b/webapp/src/components/questionView/QuestionView.test.js index fffe0619..4ad708ac 100644 --- a/webapp/src/components/questionView/QuestionView.test.js +++ b/webapp/src/components/questionView/QuestionView.test.js @@ -6,6 +6,7 @@ import { MemoryRouter } from 'react-router-dom'; import { act } from 'react-dom/test-utils'; import {queryHelpers, buildQueries} from '@testing-library/react' +jest.mock('./QuestionGenerator', () => require('./mocks/QuestionGenerator')); i18en.use(initReactI18next).init({ resources: {}, @@ -17,15 +18,30 @@ i18en.use(initReactI18next).init({ global.i18en = i18en; describe('Question View component', () => { - it('renders a question', () => { + it('renders a question',async () => { act(() => { render(); + + }); + const text = screen.getByText('Please Wait a bit...'); + expect(text).toBeInTheDocument(); + + // Wait for questions to load + await waitFor(() => expect(getByText('Mocked Question 1')).toBeInTheDocument()); + const tituloH2 = screen.getByRole('heading', { level: 2 }); + expect(tituloH2).toBeInTheDocument(); + }); + /* + it('renders a question',async () => { + act(() => { + const { getByText } = render(); }); //h2 con la pregunta const tituloH2 = screen.getByRole('heading', { level: 2 }); // Verifica si el elemento h2 está presente en el documento expect(tituloH2).toBeInTheDocument(); - }); + });*/ + /* it('render a question and 4 buttons for answers', () => { act(() => { render(); @@ -61,5 +77,5 @@ describe('Question View component', () => { // Verificar que el botón tenga el color esperado expect(falseAnswerButton).toHaveStyle('background-color:#FF6666'); - }); + });*/ }); \ No newline at end of file diff --git a/webapp/src/components/questionView/mocks/QuestionGenerator.js b/webapp/src/components/questionView/mocks/QuestionGenerator.js new file mode 100644 index 00000000..4dec7679 --- /dev/null +++ b/webapp/src/components/questionView/mocks/QuestionGenerator.js @@ -0,0 +1,20 @@ +export default class QuestionGenerator { + async generateQuestions() { + return [ + { + getQuestion: () => 'Mocked Question 1', + getAnswers: () => ['Mocked Answer 1', 'Mocked Answer 2','Mocked Answer 3', 'Mocked Answer 4'], + getCorrectAnswer: () => 'Mocked Answer 1' + }, + { + getQuestion: () => 'Mocked Question 2', + getAnswers: () => ['Mocked Answer 1', 'Mocked Answer 2','Mocked Answer 3', 'Mocked Answer 4'], + getCorrectAnswer: () => 'Mocked Answer 4' + },{ + getQuestion: () => 'Mocked Question 3', + getAnswers: () => ['Mocked Answer 1', 'Mocked Answer 2','Mocked Answer 3', 'Mocked Answer 4'], + getCorrectAnswer: () => 'Mocked Answer 2' + } + ]; + } + } \ No newline at end of file From 93b0ee74d33479957ad2382e27a45120bc43668f Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sat, 6 Apr 2024 19:30:23 +0200 Subject: [PATCH 39/66] Fixed a bug when showing the correct color, re translated turkish to add missing messages --- .../components/questionView/QuestionView.js | 9 +- webapp/src/translations/en/global.json | 3 +- webapp/src/translations/es/global.json | 3 +- webapp/src/translations/tk/global.json | 88 +++++++++---------- 4 files changed, 51 insertions(+), 52 deletions(-) diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 85e588c2..efacfbac 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -37,8 +37,8 @@ function QuestionView(){ function revealColorsForAnswers(){ let colorCorrectAnswer='#6EF26E';//green let colorIncorrectAnswer='#FF6666'; //red - $('.answerButton').each(function() { - var dataValue = $(this).data('value'); + $('.answerButton').each(function() { + let dataValue = $(this).attr('data-value'); if (dataValue === false || dataValue === "false") $(this).css('background-color', colorIncorrectAnswer); // Cambia el color de fondo del botón actual a rojo @@ -101,10 +101,9 @@ function QuestionView(){ return (
    - {/*Nav*/} {numQuestion >= 0 ? : -

    Please Wait a bit...

    } +

    {t("questionView.no_questions_message")}

    }
    ); } @@ -126,7 +125,7 @@ function QuestionComponent({questions, numQuestion, handleClick, t, points}){

    {questions[numQuestion].getQuestion()}

    - +
    diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json index 3d95669f..1deefdd4 100644 --- a/webapp/src/translations/en/global.json +++ b/webapp/src/translations/en/global.json @@ -60,7 +60,8 @@ "question_counter":"Question number ", "end_countdown":"Time's up!", "finished_game":"The game has finished!", - "point":"Points" + "point":"Points", + "no_questions_message":"Please wait a bit" }, "historicalView":{ "game":"Game", diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json index 98fc3ab8..6a034a05 100644 --- a/webapp/src/translations/es/global.json +++ b/webapp/src/translations/es/global.json @@ -63,7 +63,8 @@ "question_counter":"Pregunta nº ", "end_countdown":"¡Se acabó el tiempo!", "finished_game":"¡El juego se ha terminado!", - "point":"Puntos" + "point":"Puntos", + "no_questions_message":"Please wait a bit" }, "historicalView":{ "game":"Partida", diff --git a/webapp/src/translations/tk/global.json b/webapp/src/translations/tk/global.json index e55a4d45..7e7c89d6 100644 --- a/webapp/src/translations/tk/global.json +++ b/webapp/src/translations/tk/global.json @@ -1,71 +1,69 @@ { "home": { - "welcome": "WIQ'e hoş geldiniz!", - "how_to_play": "Nasıl Oynanır?", - "login": "Giriş Yap", - "register": "Hesabınız yok mu? Buradan kaydolun.", - "language": "Dil Türkçe olarak değiştirildi", - "msg1": "Bilgi meydan okumasına hoş geldiniz! Zihninizi test etmeye ve becerilerinizi göstermeye hazır olun. Bu heyecan verici oyunda, çeşitli konulardaki bilginizi test edecek bir dizi soruyla karşılaşacaksınız.", - "msg2": "Öyleyse ilerleyin, soruların ustası olduğunuzu kanıtlayın! Meydan okumayı kabul etmeye hazır mısınız?" -}, - - "navBar": { + "welcome": "WIQ'a hoş geldiniz!", + "how_to_play": "Nasıl Oynanır?", + "login": "Giriş yap", + "register": "Hesabınız yok mu? Buradan kaydolun.", + "language": "Dil İspanyolca olarak değiştirildi", + "msg1": "Bilgi meydan okumasına hoş geldiniz! Zihninizin becerilerini ve bilginizi test etmeye hazırlanın. Bu heyecan verici oyununuzda, çeşitli konulardaki bilginizi sınayacak bir dizi soruyla karşılaşacaksınız.", + "msg2": "Öyleyse, kendinizi soruların efendisi olarak kanıtlamaya hazır mısınız? Meydan okumayı kabul etmeye hazır mısınız?" + }, + "navBar": { "title": "Bil ve Kazan!", "en": "İngilizce", "es": "İspanyolca", "tk": "Türkçe", "language": "Dil" - }, - - "instructions": { + }, + "instructions": { "title": "WIQ Talimatları", "objective": "Amaç:", "objective_p1": "Oyunun amacı mümkün olduğunca çok soruyu doğru cevaplamaktır.", "how_to_play": "Nasıl Oynanır:", "how_to_play_p1": "Oyun bir dizi sorudan oluşur.", - "how_to_play_p2": "Her soruyu dikkatlice oku.", - "how_to_play_p3": "Verilen seçeneklerden doğru cevabı seç.", - "how_to_play_p4": "Seçtiğin cevabı göndermek için tıkla veya dokun.", - - + "how_to_play_p2": "Her soruyu dikkatlice okuyun.", + "how_to_play_p3": "Sağlanan seçeneklerden doğru cevabı seçin.", + "how_to_play_p4": "Seçtiğiniz cevabı göndermek için tıklayın veya dokunun.", "scoring": "Puanlama:", - "scoring_p1": "Her doğru cevap x puan kazandırır.", - "scoring_p2": "Yanlış cevaplar puanları düşürmez.", - "time_limit": "Zaman Sınırlaması:", - "time_limit_p1": "Bazı oyun modları her soruya cevap verme için bir zaman sınırlamasına sahip olabilir. Puanını maksimize etmek için hızlı ve doğru ol.", - "have_fun": "İyi Eğlenceler!", - "have_fun_p1": "Oyunun tadını çıkar ve bilgilerini test et. İyi şanslar!" - }, - - "login": { - "title": "Giriş Yap", + "scoring_p1": "Her doğru cevap size x puan kazandırır.", + "scoring_p2": "Yanlış cevaplar puan kaybettirmez.", + "time_limit": "Zaman Sınırı:", + "time_limit_p1": "Bazı oyun modları her soruya cevap vermek için bir zaman sınırına sahip olabilir. En yüksek puanı almak için hızlı ve doğru olun.", + "have_fun": "İyi eğlenceler!", + "have_fun_p1": "Oyunun tadını çıkarın ve bilginizi sınamaktan keyif alın. İyi şanslar!" + }, + "login": { + "title": "Giriş yap", "username_placeholder": "Kullanıcı adı", "password_placeholder": "Şifre", "remember_me": "Beni hatırla", "forgot_password": "Şifrenizi mi unuttunuz?", "login_button": "Giriş yap", "register_link": "Hesabınız yok mu? Buradan kaydolun." - }, - - "addUser": { - "title": "Kaydol", + }, + "addUser": { + "title": "Kayıt Ol", "username_placeholder": "Kullanıcı adı", "password_placeholder": "Şifre", - "repeat_password_placeholder": "Şifreyi tekrar girin", - "register_button": "Kaydol", + "repeat_password_placeholder": "Şifreyi tekrarlayın", + "register_button": "Kayıt ol", "login_link": "Zaten bir hesabınız mı var? Buradan giriş yapın." - }, - - "gameMenu": { + }, + "gameMenu": { "history_button": "Geçmişi Görüntüle", - "new_game_button": "Yeni oyun oluştur", + "new_game_button": "Yeni Oyun Oluştur", "title": "Oyun Menüsü" - }, - - "questionView": { + }, + "questionView": { "seconds": "saniye", - "question_counter": "Soru numarası: ", - "end_countdown": "Süre doldu!" - } + "question_counter": "Soru no. ", + "end_countdown": "Zaman doldu!", + "finished_game": "Oyun bitti!", + "point": "Puan", + "no_questions_message": "Lütfen biraz bekleyin" + }, + "historicalView": { + "game": "Oyun", + "points": "puanlar" } - \ No newline at end of file +} From 215d707f76233ef1f4d448768f083f51b8329fcb Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sat, 6 Apr 2024 20:19:11 +0200 Subject: [PATCH 40/66] Ajusted some parts of the system for the new front-end --- webapp/src/components/HistoricalData/HistoricalView.js | 6 +++--- webapp/src/components/fragments/NavBar.js | 4 +--- .../src/components/questionView/CreationHistoricalRecord.js | 1 - 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/webapp/src/components/HistoricalData/HistoricalView.js b/webapp/src/components/HistoricalData/HistoricalView.js index 32390ba0..49b9e371 100644 --- a/webapp/src/components/HistoricalData/HistoricalView.js +++ b/webapp/src/components/HistoricalData/HistoricalView.js @@ -17,7 +17,7 @@ export default function HistoricalView() { const getRecords = async ()=>{ console.log("in") try { - var jsonRecords = await retriever.getRecords("M"); // Obtener el JSON de registros + var jsonRecords = await retriever.getRecords(user.username); var recordsArray = jsonRecords.games; console.log(recordsArray) setRecords(recordsArray); @@ -29,9 +29,9 @@ export default function HistoricalView() { useEffect(() => {getRecords()}, []); return (
    - {records.map((record, index) => ( + {(records && records.length != 0) ? records.map((record, index) => ( - ))} + )):

    No games played yet

    }
    ) } diff --git a/webapp/src/components/fragments/NavBar.js b/webapp/src/components/fragments/NavBar.js index eec3bbfd..cddffd1b 100644 --- a/webapp/src/components/fragments/NavBar.js +++ b/webapp/src/components/fragments/NavBar.js @@ -45,9 +45,7 @@ function Navbar() { {user != null ? ( - - {user.username} - +

    {user.username}

    ) : null}
    diff --git a/webapp/src/components/questionView/CreationHistoricalRecord.js b/webapp/src/components/questionView/CreationHistoricalRecord.js index d1c4e36d..e3b0cb91 100644 --- a/webapp/src/components/questionView/CreationHistoricalRecord.js +++ b/webapp/src/components/questionView/CreationHistoricalRecord.js @@ -39,7 +39,6 @@ class CreationHistoricalRecord{ user:user, game:this.record.game } - console.log(body) try { const response = await fetch(apiUrl, { method: 'POST', From 49fe698dd59a62422011c7067a4ce7ea3ba06087 Mon Sep 17 00:00:00 2001 From: ErdemYabaci Date: Sat, 6 Apr 2024 21:20:43 +0200 Subject: [PATCH 41/66] adding the default openapi.yaml from wiq_0 --- gatewayservice/openapi.yaml | 144 ++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 gatewayservice/openapi.yaml diff --git a/gatewayservice/openapi.yaml b/gatewayservice/openapi.yaml new file mode 100644 index 00000000..67bffccb --- /dev/null +++ b/gatewayservice/openapi.yaml @@ -0,0 +1,144 @@ +openapi: 3.0.0 +info: + title: Gatewayservice API + description: Gateway OpenAPI specification. + version: 0.2.0 +servers: + - url: http://localhost:8000 + description: Development server + - url: http://SOMEIP:8000 + description: Production server +paths: + /adduser: + post: + summary: Add a new user to the database. + operationId: addUser + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: User ID. + example: student + password: + type: string + description: User password. + example: pass + responses: + '200': + description: User added successfully. + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: User ID + password: + type: string + description: Hashed password + example: $2b$10$ZKdNYLWFQxzt5Rei/YTc/OsZNi12YiWz30JeUFHNdAt7MyfmkTuvC + _id: + type: string + description: Identification + example: 65f756db3fa22d227a4b7c7d + createdAt: + type: string + description: Creation date. + example: '2024-03-17T20:47:23.935Z' + ___v: + type: integer + example: '0' + '400': + description: Failed to add user. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: getaddrinfo EAI_AGAIN mongodb + /health: + get: + summary: Check the health status of the service. + operationId: checkHealth + responses: + '200': + description: Service is healthy. + content: + application/json: + schema: + type: object + properties: + status: + type: string + description: Health status. + example: OK + /login: + post: + summary: Log in to the system. + operationId: loginUser + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: User ID. + example: student + password: + type: string + description: User password. + example: pass + responses: + '200': + description: Login successful. Returns user token, username, and creation date. + content: + application/json: + schema: + type: object + properties: + token: + type: string + description: User token. + example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NWY3NTZkYjNmYTIyZDIyN2E0YjdjN2QiLCJpYXQiOjE3MTA3MDg3NDUsImV4cCI6MTcxMDcxMjM0NX0.VMG_5DOyQ4GYlJQRcu1I6ICG1IGzuo2Xuei093ONHxw + username: + type: string + description: Username. + example: student + createdAt: + type: string + description: Creation date. + example: '2024-03-17T20:47:23.935Z' + '401': + description: Invalid credentials. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Shows the error info.. + example: Invalid credentials + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error From 310a9eefc11c40e013b8c5b46db3c3bca936321f Mon Sep 17 00:00:00 2001 From: uo289267 Date: Sat, 6 Apr 2024 22:44:53 +0200 Subject: [PATCH 42/66] Added RecordList jest test --- .../HistoricalData/HistoricalView.test.js | 4 +- .../HistoricalData/RecordList.test.js | 83 +++++++++++++++++++ .../questionView/QuestionView.test.js | 19 ++--- 3 files changed, 93 insertions(+), 13 deletions(-) create mode 100644 webapp/src/components/HistoricalData/RecordList.test.js diff --git a/webapp/src/components/HistoricalData/HistoricalView.test.js b/webapp/src/components/HistoricalData/HistoricalView.test.js index cb176e6d..5a0c9564 100644 --- a/webapp/src/components/HistoricalData/HistoricalView.test.js +++ b/webapp/src/components/HistoricalData/HistoricalView.test.js @@ -12,9 +12,7 @@ global.i18en = i18en; describe('Historical View component', () => { it('renders Game Record Buttons', () => { - /*render(); - const text = screen.getByText(i18en.t('gameMenu.title')); - expect(text).toBeInTheDocument();*/ + }); it('clicking Game Record Buttons Record Lists are displayed', () => { /*render(); diff --git a/webapp/src/components/HistoricalData/RecordList.test.js b/webapp/src/components/HistoricalData/RecordList.test.js new file mode 100644 index 00000000..98aff4d7 --- /dev/null +++ b/webapp/src/components/HistoricalData/RecordList.test.js @@ -0,0 +1,83 @@ +import { render, screen } from '@testing-library/react'; +import RecordList from './RecordList'; +import { initReactI18next } from 'react-i18next'; +import i18en from 'i18next'; + +i18en.use(initReactI18next).init({ + resources: {}, + lng: 'en', + interpolation:{ + escapeValue: false, + } +}); +global.i18en = i18en; +describe('Record List component', () => { + const record = { + questions: [ + { + question: 'What is 2 + 2?', + answers: ['4', '5', '6'], + answerGiven: '4', + correctAnswer: '4' + }, + { + question: 'What is the capital of France?', + answers: ['London', 'Berlin', 'Paris'], + answerGiven: 'Paris', + correctAnswer: 'Paris' + } + ] + }; + it('renders the question', () => { + render(); + const question1 = screen.getByText('What is 2 + 2?'); + const question2 = screen.getByText('What is the capital of France?'); + expect(question1).toBeInTheDocument(); + expect(question2).toBeInTheDocument(); + }); + it('renders the answers', () => { + render(); + const answer1 = screen.getByText(/4/); + const answer2 = screen.getByText(/Paris/); + expect(answer1).toBeInTheDocument(); + expect(answer2).toBeInTheDocument(); + }); + it('renders the marks for the answers', () => { + render(); + const allElementsWithText = screen.queryAllByText(/.+/); + + // Check if any of these elements contain emojis + const elementWithGivenEmoji = allElementsWithText.find(element => + /👈/.test(element.textContent) + ); + const elementWithCorrectEmoji = allElementsWithText.find(element => + /✅/.test(element.textContent) + ); + + expect(elementWithGivenEmoji).toBeInTheDocument(); + expect(elementWithCorrectEmoji).toBeInTheDocument(); + expect(elementWithGivenEmoji).toHaveTextContent('👈'); + expect(elementWithCorrectEmoji).toHaveTextContent('✅'); + }); + it('renders places correctly the marks for the answers for first question', () => { + render(); + render(); + const allElementsWithText = screen.queryAllByText(/.+/); + + // Find the elements containing emojis within the answer lists + const elementWithGivenEmoji = allElementsWithText.find(element => + element.closest('li') && /👈/.test(element.textContent) + ); + const elementWithCorrectEmoji = allElementsWithText.find(element => + element.closest('li') && /✅/.test(element.textContent) + ); + + // Assert that elements with emojis are found within the answer lists + expect(elementWithGivenEmoji).toBeInTheDocument(); + expect(elementWithCorrectEmoji).toBeInTheDocument(); + + // Assert that emojis are associated with the correct answers + expect(elementWithGivenEmoji).toHaveTextContent('4 👈 ✅'); + expect(elementWithCorrectEmoji).toHaveTextContent('4 👈 ✅'); + }); +}); \ No newline at end of file diff --git a/webapp/src/components/questionView/QuestionView.test.js b/webapp/src/components/questionView/QuestionView.test.js index 4ad708ac..18e2a8d3 100644 --- a/webapp/src/components/questionView/QuestionView.test.js +++ b/webapp/src/components/questionView/QuestionView.test.js @@ -1,10 +1,11 @@ -import { render, screen ,fireEvent } from '@testing-library/react'; +import { render, screen ,fireEvent, waitFor } from '@testing-library/react'; import { initReactI18next } from 'react-i18next'; import i18en from 'i18next'; import QuestionView from './QuestionView'; import { MemoryRouter } from 'react-router-dom'; import { act } from 'react-dom/test-utils'; import {queryHelpers, buildQueries} from '@testing-library/react' +import { UserContextProvider } from '../loginAndRegistration/UserContext'; jest.mock('./QuestionGenerator', () => require('./mocks/QuestionGenerator')); @@ -19,17 +20,15 @@ global.i18en = i18en; describe('Question View component', () => { it('renders a question',async () => { - act(() => { - render(); - - }); - const text = screen.getByText('Please Wait a bit...'); - expect(text).toBeInTheDocument(); + render(); + const text = screen.getByText(i18en.t('questionView.no_questions_message')); + expect(text).toBeInTheDocument(); // Wait for questions to load - await waitFor(() => expect(getByText('Mocked Question 1')).toBeInTheDocument()); - const tituloH2 = screen.getByRole('heading', { level: 2 }); - expect(tituloH2).toBeInTheDocument(); + act(()=>{ + const tituloH2 = screen.getByRole('heading', { level: 2 }); + expect(tituloH2).toBeInTheDocument(); + }) }); /* it('renders a question',async () => { From eb08cf0602fdab9059d6f9a4930a447404ea5034 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sat, 6 Apr 2024 23:28:20 +0200 Subject: [PATCH 43/66] Finished the auth-service tests --- users/authservice/auth-service.js | 8 +++++++- users/authservice/auth-service.test.js | 13 +++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/users/authservice/auth-service.js b/users/authservice/auth-service.js index 9764f088..81cf62e9 100644 --- a/users/authservice/auth-service.js +++ b/users/authservice/auth-service.js @@ -27,7 +27,13 @@ function validateRequiredFields(req, requiredFields) { app.post('/login', async (req, res) => { try { // Check if required fields are present in the request body - validateRequiredFields(req, ['username', 'password']); + try{ + validateRequiredFields(req, ['username', 'password']); + } + catch(error){ + res.status(401).json({ error : error.message }); + return + } const { username, password } = req.body; diff --git a/users/authservice/auth-service.test.js b/users/authservice/auth-service.test.js index 7b55ee72..032390fc 100644 --- a/users/authservice/auth-service.test.js +++ b/users/authservice/auth-service.test.js @@ -17,6 +17,7 @@ async function addUser(user){ const newUser = new User({ username: user.username, password: hashedPassword, + createdAt: new Date() }); await newUser.save(); @@ -42,4 +43,16 @@ describe('Auth Service', () => { expect(response.status).toBe(200); expect(response.body).toHaveProperty('username', 'testuser'); }); + it('Should show missing field user /login', async () => { + const response = await request(app).post('/login').send(); + expect(response.status).toBe(401); + console.log(response) + expect(response.body).toHaveProperty('error', 'Missing required field: username'); + }); + it('Should show invalid credentials /login', async () => { + const user2 = {username:"Hello", password:"world"} + const response = await request(app).post('/login').send(user2); + expect(response.status).toBe(401); + expect(response.body).toHaveProperty('error', 'Invalid credentials'); + }); }); From d010e412384e56549ce38215cc6620a31b8a7863 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sat, 6 Apr 2024 23:47:47 +0200 Subject: [PATCH 44/66] Modified error staus to 400 for better semantics and added user-service tests --- users/authservice/auth-service.js | 4 ++-- users/authservice/auth-service.test.js | 7 ++++--- users/userservice/user-service.js | 15 +++++++++++++-- users/userservice/user-service.test.js | 24 +++++++++++++++++++++++- 4 files changed, 42 insertions(+), 8 deletions(-) diff --git a/users/authservice/auth-service.js b/users/authservice/auth-service.js index 81cf62e9..d9f50047 100644 --- a/users/authservice/auth-service.js +++ b/users/authservice/auth-service.js @@ -31,7 +31,7 @@ app.post('/login', async (req, res) => { validateRequiredFields(req, ['username', 'password']); } catch(error){ - res.status(401).json({ error : error.message }); + res.status(400).json({ error : error.message }); return } @@ -47,7 +47,7 @@ app.post('/login', async (req, res) => { // Respond with the token and user information res.json({ token: token, username: username, createdAt: user.createdAt }); } else { - res.status(401).json({ error: 'Invalid credentials' }); + res.status(400).json({ error: 'Invalid credentials' }); } } catch (error) { res.status(500).json({ error: 'Internal Server Error' }); diff --git a/users/authservice/auth-service.test.js b/users/authservice/auth-service.test.js index 032390fc..f4a5a82e 100644 --- a/users/authservice/auth-service.test.js +++ b/users/authservice/auth-service.test.js @@ -43,16 +43,17 @@ describe('Auth Service', () => { expect(response.status).toBe(200); expect(response.body).toHaveProperty('username', 'testuser'); }); + it('Should show missing field user /login', async () => { const response = await request(app).post('/login').send(); - expect(response.status).toBe(401); - console.log(response) + expect(response.status).toBe(400); expect(response.body).toHaveProperty('error', 'Missing required field: username'); }); + it('Should show invalid credentials /login', async () => { const user2 = {username:"Hello", password:"world"} const response = await request(app).post('/login').send(user2); - expect(response.status).toBe(401); + expect(response.status).toBe(400); expect(response.body).toHaveProperty('error', 'Invalid credentials'); }); }); diff --git a/users/userservice/user-service.js b/users/userservice/user-service.js index 7a49e593..69899c29 100644 --- a/users/userservice/user-service.js +++ b/users/userservice/user-service.js @@ -19,7 +19,6 @@ mongoose.connect(mongoUri); // Function to validate required fields in the request body function validateRequiredFields(req, requiredFields) { - //TODO: Add more validations for (const field of requiredFields) { if (!(field in req.body)) { throw new Error(`Missing required field: ${field}`); @@ -30,7 +29,19 @@ function validateRequiredFields(req, requiredFields) { app.post('/adduser', async (req, res) => { try { // Check if required fields are present in the request body - validateRequiredFields(req, ['username', 'password']); + try{ + validateRequiredFields(req, ['username', 'password']); + } + catch(error){ + res.status(400).json({ error : error.message }); + return + } + + //Check there is not a user with the same name + const user = await User.findOne({username: req.body.username}); + + if(user) + return res.status(400).json({error : "Username already in use"}) // Encrypt the password before saving it const hashedPassword = await bcrypt.hash(req.body.password, 10); diff --git a/users/userservice/user-service.test.js b/users/userservice/user-service.test.js index 8dd8ea16..7b9e1b4f 100644 --- a/users/userservice/user-service.test.js +++ b/users/userservice/user-service.test.js @@ -4,6 +4,8 @@ const { MongoMemoryServer } = require('mongodb-memory-server'); let mongoServer; let app; + + beforeAll(async () => { mongoServer = await MongoMemoryServer.create(); const mongoUri = mongoServer.getUri(); @@ -20,11 +22,31 @@ describe('User Service', () => { it('should add a new user on POST /adduser', async () => { const newUser = { username: 'testuser', - password: 'testpassword', + password: 'testpassword' }; const response = await request(app).post('/adduser').send(newUser); expect(response.status).toBe(200); expect(response.body).toHaveProperty('username', 'testuser'); }); + + it('Should show missing field user /adduser', async () => { + const response = await request(app).post('/adduser').send(); + expect(response.status).toBe(400); + expect(response.body).toHaveProperty('error', 'Missing required field: username'); + }); + + it('Should not register user /adduser', async () => { + const newUser = { + username: 'testuser', + password: 'testpassword' + }; + + const response = await request(app).post('/adduser').send(newUser); + expect(response.status).toBe(400); + expect(response.body).toHaveProperty('error', 'Username already in use'); + }); + + + }); From 9c4c82fdf1b1b3e7d9f715c46fc348f76b165e02 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sun, 7 Apr 2024 00:09:17 +0200 Subject: [PATCH 45/66] question-service fully tested --- questionservice/question-service.test.js | 63 ++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 questionservice/question-service.test.js diff --git a/questionservice/question-service.test.js b/questionservice/question-service.test.js new file mode 100644 index 00000000..67b5ca66 --- /dev/null +++ b/questionservice/question-service.test.js @@ -0,0 +1,63 @@ +const request = require('supertest'); +const { MongoMemoryServer } = require('mongodb-memory-server'); +const Question = require('./question-model'); + +let mongoServer; +let app; + +beforeAll(async () => { + mongoServer = await MongoMemoryServer.create(); + const mongoUri = mongoServer.getUri(); + process.env.MONGODB_URI_QUESTIONS = mongoUri; + app = require('./question-service'); + + //Populate db + for(let i = 0; i < 6 ; i++){ + const question = new Question( { + question: "¿Cuál es la población de Oviedo?", + answers: [ + "225089", + "272357", + "267855", + "231841" + ], + language: "es", + type: "POPULATION" + }) + + await question.save(); + } + + + +}); + +afterAll(async () => { + app.close(); + await mongoServer.stop(); +}); + +describe('Question Service', () => { + it('Should give 5 questions /questions/es', async () => { + + let response = await request(app).get('/questions/es'); + expect(response.status).toBe(200); + expect(response.body[0]).toHaveProperty('question', "¿Cuál es la población de Oviedo?"); + expect(Object.keys(response.body).length).toBe(5); + }); + + it('Should give no question /questions/en', async () => { + + let response = await request(app).get('/questions/en'); + expect(response.status).toBe(200); + expect(response).toHaveProperty('body', ); //There are no questions + }); + + it('Should give 5 question /questions', async () => { + + let response = await request(app).get('/questions'); + expect(response.status).toBe(200); + expect(response.body[0]).toHaveProperty('question', "¿Cuál es la población de Oviedo?"); + expect(Object.keys(response.body).length).toBe(5); + }); +}); \ No newline at end of file From 3ca88d6e9739d73eb7c758fa35bfe340c24e4a4e Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sun, 7 Apr 2024 10:33:35 +0200 Subject: [PATCH 46/66] Added tests for gateway-service --- gatewayservice/gateway-service.js | 10 +++-- gatewayservice/gateway-service.test.js | 58 ++++++++++++++++++++++++-- users/authservice/auth-service.js | 2 +- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index cb49f10a..160fd354 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -47,8 +47,8 @@ app.get('/questions', async (req, res) => { try { // Forward the question request to the quetion service - const quetionResponse = await axios.get(questionServiceUrl+'/questions'); - res.send(quetionResponse.data); + const questionResponse = await axios.get(questionServiceUrl+'/questions'); + res.json(questionResponse.data); } catch (error) { res.status(error.response.status).json({ error: error.response.data.error }); } @@ -58,9 +58,11 @@ app.get('/questions/:lang', async (req, res) => { try { const lang = req.params.lang; // Forward the question request to the quetion service - const quetionResponse = await axios.get(questionServiceUrl+'/questions/' + lang); - res.send(quetionResponse.data); + const questionResponse = await axios.get(questionServiceUrl+'/questions/' + lang); + + res.json(questionResponse.data); } catch (error) { + res.status(error.response.status).json({ error: error.response.data.error }); } }); diff --git a/gatewayservice/gateway-service.test.js b/gatewayservice/gateway-service.test.js index 56eeb124..bfed664f 100644 --- a/gatewayservice/gateway-service.test.js +++ b/gatewayservice/gateway-service.test.js @@ -12,9 +12,24 @@ describe('Gateway Service', () => { // Mock responses from external services axios.post.mockImplementation((url, data) => { if (url.endsWith('/login')) { - return Promise.resolve({ data: { token: 'mockedToken' } }); + return Promise.resolve({ data: { token: 'mockedToken', username : 'testuser'} }); } else if (url.endsWith('/adduser')) { - return Promise.resolve({ data: { userId: 'mockedUserId' } }); + return Promise.resolve({ data: { username: 'newuser' } }); + } else if(url.endsWith('/record')){ + return Promise.resolve({data : {user:'testuser'}}) + } + }); + + axios.get.mockImplementation((url, data) => { + if (url.endsWith('/questions')){ + return Promise.resolve({ data: [{question: "¿Cuál es la población de Oviedo?", + answers: ["225089","272357","267855","231841"]}] }); + } else if (url.endsWith('/questions/es')){ + return Promise.resolve({ data: [{question: "¿Cuál es la población de Oviedo?", + answers: ["225089","272357","267855","231841"]}] }); + } else if(url.endsWith('/record/testuser')){ + //Dont need to check a good record just that it redirects the call + return Promise.resolve({data : {record:'undefined'}}) } }); @@ -26,6 +41,7 @@ describe('Gateway Service', () => { expect(response.statusCode).toBe(200); expect(response.body.token).toBe('mockedToken'); + expect(response.body.username).toBe('testuser'); }); // Test /adduser endpoint @@ -35,6 +51,42 @@ describe('Gateway Service', () => { .send({ username: 'newuser', password: 'newpassword' }); expect(response.statusCode).toBe(200); - expect(response.body.userId).toBe('mockedUserId'); + expect(response.body.username).toBe('newuser'); + }); + + // Test /questions endpoint + it('should forward questions request to question service', async () => { + const response = await request(app) + .get('/questions'); + + expect(response.statusCode).toBe(200); + expect(response.body[0]).toHaveProperty('question', "¿Cuál es la población de Oviedo?"); + }); + + // Test /questions/:lang endpoint + it('should forward questions request to question service', async () => { + const response = await request(app) + .get('/questions/es'); + + expect(response.statusCode).toBe(200); + expect(response.body[0]).toHaveProperty('question', "¿Cuál es la población de Oviedo?"); + }); + + // Test /record endpoint + it('should forward record request to record service', async () => { + const response = await request(app) + .post('/record'); + + expect(response.statusCode).toBe(200); + expect(response.body.user).toBe('testuser'); + }); + + // Test /record/:user endpoint + it('should forward record request to record service', async () => { + const response = await request(app) + .get('/record/testuser'); + + expect(response.statusCode).toBe(200); + expect(response.body).toHaveProperty('record', "undefined"); }); }); \ No newline at end of file diff --git a/users/authservice/auth-service.js b/users/authservice/auth-service.js index d9f50047..98779572 100644 --- a/users/authservice/auth-service.js +++ b/users/authservice/auth-service.js @@ -45,7 +45,7 @@ app.post('/login', async (req, res) => { // Generate a JWT token const token = jwt.sign({ userId: user._id }, 'your-secret-key', { expiresIn: '1h' }); // Respond with the token and user information - res.json({ token: token, username: username, createdAt: user.createdAt }); + res.json({ token: token, username: username}); } else { res.status(400).json({ error: 'Invalid credentials' }); } From 95027ee04b4501da523cf3237bbdbf4cb138c0f3 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sun, 7 Apr 2024 12:36:36 +0200 Subject: [PATCH 47/66] Modified api calls to work with axios for making the tests, added a test case for questionView to show how to mock the endpoint --- .../HistoricalData/HistoryRecordRetriever.js | 5 +- .../questionView/QuestionGenerator.js | 6 ++- .../components/questionView/QuestionView.js | 2 +- .../questionView/QuestionView.test.js | 52 ++++++++++++++----- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/webapp/src/components/HistoricalData/HistoryRecordRetriever.js b/webapp/src/components/HistoricalData/HistoryRecordRetriever.js index a261ad7f..cc60fe04 100644 --- a/webapp/src/components/HistoricalData/HistoryRecordRetriever.js +++ b/webapp/src/components/HistoricalData/HistoryRecordRetriever.js @@ -1,3 +1,4 @@ +import axios from 'axios'; class HistoryRecordRetriever{ @@ -8,8 +9,8 @@ class HistoryRecordRetriever{ async getRecords(user) { try { - const response = await fetch(this.apiUrl + '/' + user); - const receivedRecords = await response.json(); + const response = await axios.get(this.apiUrl + '/' + user); + const receivedRecords = await response.data; return receivedRecords.record; } catch (error) { throw new Error(error); diff --git a/webapp/src/components/questionView/QuestionGenerator.js b/webapp/src/components/questionView/QuestionGenerator.js index b139c517..28038332 100644 --- a/webapp/src/components/questionView/QuestionGenerator.js +++ b/webapp/src/components/questionView/QuestionGenerator.js @@ -1,4 +1,6 @@ import Question from './Question'; +import axios from 'axios' + class QuestionGenerator{ constructor(){ @@ -8,8 +10,8 @@ class QuestionGenerator{ async generateQuestions(lang) { try { - const response = await fetch(this.apiUrl + '/' + lang); - const receivedQuestions = await response.json(); + const response = await axios.get(this.apiUrl + '/' + lang); + const receivedQuestions = await response.data; let i = 0; var questions = []; for (const key in receivedQuestions) { diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 66c7c3a0..2220e57d 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -27,7 +27,7 @@ function QuestionView(){ setnumQuestion(0); } catch (error) { //Como hacer que funcione esto - console.log(error.response); + console.log(error); } } diff --git a/webapp/src/components/questionView/QuestionView.test.js b/webapp/src/components/questionView/QuestionView.test.js index 4ad708ac..d631c659 100644 --- a/webapp/src/components/questionView/QuestionView.test.js +++ b/webapp/src/components/questionView/QuestionView.test.js @@ -1,12 +1,17 @@ -import { render, screen ,fireEvent } from '@testing-library/react'; +import { render , screen, waitFor } from '@testing-library/react'; import { initReactI18next } from 'react-i18next'; import i18en from 'i18next'; import QuestionView from './QuestionView'; import { MemoryRouter } from 'react-router-dom'; import { act } from 'react-dom/test-utils'; -import {queryHelpers, buildQueries} from '@testing-library/react' +import {queryHelpers, buildQueries} from '@testing-library/react'; +import { UserContextProvider } from '../loginAndRegistration/UserContext'; -jest.mock('./QuestionGenerator', () => require('./mocks/QuestionGenerator')); +import axios from 'axios'; +import MockAdapter from 'axios-mock-adapter'; + + +const mockAxios = new MockAdapter(axios); i18en.use(initReactI18next).init({ resources: {}, @@ -18,18 +23,37 @@ i18en.use(initReactI18next).init({ global.i18en = i18en; describe('Question View component', () => { - it('renders a question',async () => { - act(() => { - render(); - - }); - const text = screen.getByText('Please Wait a bit...'); - expect(text).toBeInTheDocument(); - + + beforeEach(() => { + mockAxios.reset(); + }); + + it('shows the no_questions_message as the endpoint does not exist',async () => { + render(); + const text = screen.getByText(i18en.t('questionView.no_questions_message')); + expect(text).toBeInTheDocument(); // Wait for questions to load - await waitFor(() => expect(getByText('Mocked Question 1')).toBeInTheDocument()); - const tituloH2 = screen.getByRole('heading', { level: 2 }); - expect(tituloH2).toBeInTheDocument(); + + }); + it('shows a question',async () => { + + mockAxios.onGet('http://localhost:8000/questions/en').reply(200, + [{question: "What is the population of Oviedo?", + answers: ["225089","272357","267855","231841"]}]); + + //It gives an error as we are not wrapping it by act, however by doing this we simulate a no questions situation + await act(async () =>{ + await render(); + }) + + await waitFor(() => expect(screen.getByText('What is the population of Oviedo?')).toBeInTheDocument()); + + //Now that we know the question is showing + expect(screen.getByText('225089')).toBeInTheDocument() + expect(screen.getByText('272357')).toBeInTheDocument() + expect(screen.getByText('267855')).toBeInTheDocument() + expect(screen.getByText('231841')).toBeInTheDocument() + }); /* it('renders a question',async () => { From 639d3b4e80a16d36976780fd3dcefe456182eeeb Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sun, 7 Apr 2024 14:19:57 +0200 Subject: [PATCH 48/66] Added new Navbar tests --- .../src/components/fragments/NavBar.test.js | 29 +++++++++++++++++++ .../loginAndRegistration/UserContext.js | 4 +-- .../questionView/QuestionView.test.js | 5 ++-- 3 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 webapp/src/components/fragments/NavBar.test.js diff --git a/webapp/src/components/fragments/NavBar.test.js b/webapp/src/components/fragments/NavBar.test.js new file mode 100644 index 00000000..74faeb9f --- /dev/null +++ b/webapp/src/components/fragments/NavBar.test.js @@ -0,0 +1,29 @@ +import { render , screen, waitFor } from '@testing-library/react'; +import { initReactI18next } from 'react-i18next'; +import i18en from 'i18next'; +import { MemoryRouter } from 'react-router-dom'; + +import { UserContextProvider} from '../loginAndRegistration/UserContext'; +import Navbar from '../fragments/NavBar'; + + +i18en.use(initReactI18next).init({ + resources: {}, + lng: 'en', + interpolation:{ + escapeValue: false, + } +}); +global.i18en = i18en; + +describe('NavBar fragment', () => { + + it('shows the user name',async () => { + const user = { username: 'dummy' }; + render(); + const text2 = await screen.findByText('dummy') + expect(text2).toBeInTheDocument(); + // Wait for questions to load + + }); +}); \ No newline at end of file diff --git a/webapp/src/components/loginAndRegistration/UserContext.js b/webapp/src/components/loginAndRegistration/UserContext.js index f551b9c8..95764078 100644 --- a/webapp/src/components/loginAndRegistration/UserContext.js +++ b/webapp/src/components/loginAndRegistration/UserContext.js @@ -2,8 +2,8 @@ import React, { createContext, useContext, useState } from 'react'; const UserContext = createContext(); -export function UserContextProvider({ children }) { - const [user, setUser] = useState(null); +export function UserContextProvider({ children, baseUser = null }) { + const [user, setUser] = useState(baseUser); return ( diff --git a/webapp/src/components/questionView/QuestionView.test.js b/webapp/src/components/questionView/QuestionView.test.js index d631c659..d7219b5d 100644 --- a/webapp/src/components/questionView/QuestionView.test.js +++ b/webapp/src/components/questionView/QuestionView.test.js @@ -5,14 +5,15 @@ import QuestionView from './QuestionView'; import { MemoryRouter } from 'react-router-dom'; import { act } from 'react-dom/test-utils'; import {queryHelpers, buildQueries} from '@testing-library/react'; -import { UserContextProvider } from '../loginAndRegistration/UserContext'; - +import { UserContextProvider} from '../loginAndRegistration/UserContext'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; const mockAxios = new MockAdapter(axios); + + i18en.use(initReactI18next).init({ resources: {}, lng: 'en', From fdc3035a3e6b361e6ec8cfae8ff8238480d12e12 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sun, 7 Apr 2024 14:28:42 +0200 Subject: [PATCH 49/66] Setted up OpenApi documentation --- gatewayservice/gateway-service.js | 15 ++ gatewayservice/openapi.yaml | 144 +++++++++++++++++ gatewayservice/package-lock.json | 261 +++++++++++++++++++++++++++--- gatewayservice/package.json | 5 +- 4 files changed, 404 insertions(+), 21 deletions(-) create mode 100644 gatewayservice/openapi.yaml diff --git a/gatewayservice/gateway-service.js b/gatewayservice/gateway-service.js index 160fd354..009db707 100644 --- a/gatewayservice/gateway-service.js +++ b/gatewayservice/gateway-service.js @@ -2,6 +2,10 @@ const express = require('express'); const axios = require('axios'); const cors = require('cors'); const promBundle = require('express-prom-bundle'); +//libraries required for OpenAPI-Swagger +const swaggerUi = require('swagger-ui-express'); +const fs = require("fs") +const YAML = require('yaml') const app = express(); const port = 8000; @@ -88,6 +92,17 @@ app.get('/record/:user', async(req, res)=>{ } }); +// Read the OpenAPI YAML file synchronously +const file = fs.readFileSync('./openapi.yaml', 'utf8'); + +// Parse the YAML content into a JavaScript object representing the Swagger document +const swaggerDocument = YAML.parse(file); + +// Serve the Swagger UI documentation at the '/api-doc' endpoint +// This middleware serves the Swagger UI files and sets up the Swagger UI page +// It takes the parsed Swagger document as input +app.use('/api-doc', swaggerUi.serve, swaggerUi.setup(swaggerDocument)); + // Start the gateway service const server = app.listen(port, () => { console.log(`Gateway Service listening at http://localhost:${port}`); diff --git a/gatewayservice/openapi.yaml b/gatewayservice/openapi.yaml new file mode 100644 index 00000000..285e7c56 --- /dev/null +++ b/gatewayservice/openapi.yaml @@ -0,0 +1,144 @@ +openapi: 3.0.0 +info: + title: Gatewayservice API + description: Gateway OpenAPI specification. + version: 0.2.0 +servers: + - url: http://localhost:8000 + description: Development server + - url: http://SOMEIP:8000 + description: Production server +paths: + /adduser: + post: + summary: Add a new user to the database. + operationId: addUser + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: User ID. + example: student + password: + type: string + description: User password. + example: pass + responses: + '200': + description: User added successfully. + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: User ID + password: + type: string + description: Hashed password + example: $2b$10$ZKdNYLWFQxzt5Rei/YTc/OsZNi12YiWz30JeUFHNdAt7MyfmkTuvC + _id: + type: string + description: Identification + example: 65f756db3fa22d227a4b7c7d + createdAt: + type: string + description: Creation date. + example: '2024-03-17T20:47:23.935Z' + ___v: + type: integer + example: '0' + '400': + description: Failed to add user. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: getaddrinfo EAI_AGAIN mongodb + /health: + get: + summary: Check the health status of the service. + operationId: checkHealth + responses: + '200': + description: Service is healthy. + content: + application/json: + schema: + type: object + properties: + status: + type: string + description: Health status. + example: OK + /login: + post: + summary: Log in to the system. + operationId: loginUser + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: User ID. + example: student + password: + type: string + description: User password. + example: pass + responses: + '200': + description: Login successful. Returns user token, username, and creation date. + content: + application/json: + schema: + type: object + properties: + token: + type: string + description: User token. + example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NWY3NTZkYjNmYTIyZDIyN2E0YjdjN2QiLCJpYXQiOjE3MTA3MDg3NDUsImV4cCI6MTcxMDcxMjM0NX0.VMG_5DOyQ4GYlJQRcu1I6ICG1IGzuo2Xuei093ONHxw + username: + type: string + description: Username. + example: student + createdAt: + type: string + description: Creation date. + example: '2024-03-17T20:47:23.935Z' + '401': + description: Invalid credentials. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Shows the error info.. + example: Invalid credentials + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error \ No newline at end of file diff --git a/gatewayservice/package-lock.json b/gatewayservice/package-lock.json index fc5f2d60..ca71293c 100644 --- a/gatewayservice/package-lock.json +++ b/gatewayservice/package-lock.json @@ -12,7 +12,10 @@ "axios": "^1.6.5", "cors": "^2.8.5", "express": "^4.18.2", - "express-prom-bundle": "^7.0.0" + "express-openapi": "^12.1.3", + "express-prom-bundle": "^7.0.0", + "swagger-ui-express": "^5.0.0", + "yaml": "^2.4.1" }, "devDependencies": { "jest": "^29.7.0", @@ -1277,6 +1280,37 @@ "node": ">= 0.6" } }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -1333,7 +1367,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } @@ -1474,8 +1507,7 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "node_modules/bintrees": { "version": "1.0.2", @@ -1510,7 +1542,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1751,8 +1782,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/content-disposition": { "version": "0.5.4", @@ -1942,6 +1972,14 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/difunc": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/difunc/-/difunc-0.0.4.tgz", + "integrity": "sha512-zBiL4ALDmviHdoLC0g0G6wVme5bwAow9WfhcZLLopXCAWgg3AEf7RYTs2xugszIGulRHzEVDF/SHl9oyQU07Pw==", + "dependencies": { + "esprima": "^4.0.0" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -2015,7 +2053,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -2121,6 +2158,21 @@ "node": ">= 0.10.0" } }, + "node_modules/express-normalize-query-params-middleware": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/express-normalize-query-params-middleware/-/express-normalize-query-params-middleware-0.5.1.tgz", + "integrity": "sha512-KUBjEukYL9KJkrphVX3ZgMHgMTdgaSJe+FIOeWwJIJpCw8UZQPIylt0MYddSyUwbms4LQ8RC4wmavcLUP9uduA==" + }, + "node_modules/express-openapi": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/express-openapi/-/express-openapi-12.1.3.tgz", + "integrity": "sha512-F570dVC5ENSkLu1SpDFPRQ13Y3a/7Udh0rfHyn3O1QrE81fPmlhnAo1JRgoNtbMRJ6goHNymxU1TVSllgFZBlQ==", + "dependencies": { + "express-normalize-query-params-middleware": "^0.5.0", + "openapi-framework": "^12.1.3", + "openapi-types": "^12.1.3" + } + }, "node_modules/express-prom-bundle": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/express-prom-bundle/-/express-prom-bundle-7.0.0.tgz", @@ -2138,6 +2190,11 @@ "prom-client": ">=15.0.0" } }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2264,11 +2321,18 @@ "node": ">= 0.6" } }, + "node_modules/fs-routes": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/fs-routes/-/fs-routes-12.1.3.tgz", + "integrity": "sha512-Vwxi5StpKj/pgH7yRpNpVFdaZr16z71KNTiYuZEYVET+MfZ31Zkf7oxUmNgyZxptG8BolRtdMP90agIhdyiozg==", + "peerDependencies": { + "glob": ">=7.1.6" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { "version": "2.3.3", @@ -2349,7 +2413,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2526,7 +2589,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -2563,6 +2625,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-dir/-/is-dir-1.0.0.tgz", + "integrity": "sha512-vLwCNpTNkFC5k7SBRxPubhOCryeulkOsSkjbGyZ8eOzZmzMS+hSEO/Kn9ZOVhFNAlRZTFc4ZKql48hESuYUPIQ==" + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -3328,7 +3395,6 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -3355,6 +3421,11 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -3403,6 +3474,11 @@ "node": ">=8" } }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -3552,7 +3628,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -3643,7 +3718,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -3663,6 +3737,97 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openapi-default-setter": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-default-setter/-/openapi-default-setter-12.1.3.tgz", + "integrity": "sha512-wHKwvEuOWwke5WcQn8pyCTXT5WQ+rm9FpJmDeEVECEBWjEyB/MVLYfXi+UQeSHTTu2Tg4VDHHmzbjOqN6hYeLQ==", + "dependencies": { + "openapi-types": "^12.1.3" + } + }, + "node_modules/openapi-framework": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-framework/-/openapi-framework-12.1.3.tgz", + "integrity": "sha512-p30PHWVXda9gGxm+t/1X2XvEcufW1YhzeDQwc5SsgDnBXt8gkuu1SwrioGJ66wxVYEzfSRTTf/FMLhI49ut8fQ==", + "dependencies": { + "difunc": "0.0.4", + "fs-routes": "^12.1.3", + "glob": "*", + "is-dir": "^1.0.0", + "js-yaml": "^3.10.0", + "openapi-default-setter": "^12.1.3", + "openapi-request-coercer": "^12.1.3", + "openapi-request-validator": "^12.1.3", + "openapi-response-validator": "^12.1.3", + "openapi-schema-validator": "^12.1.3", + "openapi-security-handler": "^12.1.3", + "openapi-types": "^12.1.3", + "ts-log": "^2.1.4" + } + }, + "node_modules/openapi-jsonschema-parameters": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-jsonschema-parameters/-/openapi-jsonschema-parameters-12.1.3.tgz", + "integrity": "sha512-aHypKxWHwu2lVqfCIOCZeJA/2NTDiP63aPwuoIC+5ksLK5/IQZ3oKTz7GiaIegz5zFvpMDxDvLR2DMQQSkOAug==", + "dependencies": { + "openapi-types": "^12.1.3" + } + }, + "node_modules/openapi-request-coercer": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-request-coercer/-/openapi-request-coercer-12.1.3.tgz", + "integrity": "sha512-CT2ZDhBmAZpHhAzHhEN+/J5oMK3Ds99ayLLdXh2Aw1DCcn72EM8VuIGVwG5fSjvkMsgtn7FgltFosHqeM6PRFQ==", + "dependencies": { + "openapi-types": "^12.1.3", + "ts-log": "^2.1.4" + } + }, + "node_modules/openapi-request-validator": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-request-validator/-/openapi-request-validator-12.1.3.tgz", + "integrity": "sha512-HW1sG00A9Hp2oS5g8CBvtaKvRAc4h5E4ksmuC5EJgmQ+eAUacL7g+WaYCrC7IfoQaZrjxDfeivNZUye/4D8pwA==", + "dependencies": { + "ajv": "^8.3.0", + "ajv-formats": "^2.1.0", + "content-type": "^1.0.4", + "openapi-jsonschema-parameters": "^12.1.3", + "openapi-types": "^12.1.3", + "ts-log": "^2.1.4" + } + }, + "node_modules/openapi-response-validator": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-response-validator/-/openapi-response-validator-12.1.3.tgz", + "integrity": "sha512-beZNb6r1SXAg1835S30h9XwjE596BYzXQFAEZlYAoO2imfxAu5S7TvNFws5k/MMKMCOFTzBXSjapqEvAzlblrQ==", + "dependencies": { + "ajv": "^8.4.0", + "openapi-types": "^12.1.3" + } + }, + "node_modules/openapi-schema-validator": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-schema-validator/-/openapi-schema-validator-12.1.3.tgz", + "integrity": "sha512-xTHOmxU/VQGUgo7Cm0jhwbklOKobXby+/237EG967+3TQEYJztMgX9Q5UE2taZKwyKPUq0j11dngpGjUuxz1hQ==", + "dependencies": { + "ajv": "^8.1.0", + "ajv-formats": "^2.0.2", + "lodash.merge": "^4.6.1", + "openapi-types": "^12.1.3" + } + }, + "node_modules/openapi-security-handler": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-security-handler/-/openapi-security-handler-12.1.3.tgz", + "integrity": "sha512-25UTAflxqqpjCLrN6rRhINeM1L+MCDixMltiAqtBa9Zz/i7UkWwYwdzqgZY3Cx3vRZElFD09brYxo5VleeP3HQ==", + "dependencies": { + "openapi-types": "^12.1.3" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==" + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -3753,7 +3918,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3886,6 +4050,14 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, "node_modules/pure-rand": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", @@ -3953,6 +4125,14 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -4171,8 +4351,7 @@ "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, "node_modules/stack-utils": { "version": "2.0.6", @@ -4389,6 +4568,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/swagger-ui-dist": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.13.0.tgz", + "integrity": "sha512-uaWhh6j18IIs5tOX0arvIBnVINAzpTXaQXkr7qAk8zoupegJVg0UU/5+S/FgsgVCnzVsJ9d7QLjIxkswEeTg0Q==" + }, + "node_modules/swagger-ui-express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", + "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, "node_modules/tdigest": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.2.tgz", @@ -4447,6 +4645,11 @@ "node": ">=0.6" } }, + "node_modules/ts-log": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/ts-log/-/ts-log-2.2.5.tgz", + "integrity": "sha512-PGcnJoTBnVGy6yYNFxWVNkdcAuAMstvutN9MgDJIV6L0oG8fB+ZNNy1T+wJzah8RPGor1mZuPQkVfXNDpy9eHA==" + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -4523,6 +4726,14 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/url-value-parser": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/url-value-parser/-/url-value-parser-2.2.0.tgz", @@ -4605,8 +4816,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/write-file-atomic": { "version": "4.0.2", @@ -4636,6 +4846,17 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "node_modules/yaml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", + "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/gatewayservice/package.json b/gatewayservice/package.json index d1362752..93a9914e 100644 --- a/gatewayservice/package.json +++ b/gatewayservice/package.json @@ -21,7 +21,10 @@ "axios": "^1.6.5", "cors": "^2.8.5", "express": "^4.18.2", - "express-prom-bundle": "^7.0.0" + "express-openapi": "^12.1.3", + "express-prom-bundle": "^7.0.0", + "swagger-ui-express": "^5.0.0", + "yaml": "^2.4.1" }, "devDependencies": { "jest": "^29.7.0", From a26f6799b7c53994f7fa92690c79fb739d206af7 Mon Sep 17 00:00:00 2001 From: uo289267 Date: Sun, 7 Apr 2024 14:40:23 +0200 Subject: [PATCH 50/66] Added jest tests for QuestionView --- .../HistoricalData/HistoricalView.test.js | 12 ++ .../questionView/CreationHistoricalRecord.js | 6 +- .../components/questionView/QuestionView.js | 2 +- .../questionView/QuestionView.test.js | 113 ++++++++++-------- 4 files changed, 81 insertions(+), 52 deletions(-) diff --git a/webapp/src/components/HistoricalData/HistoricalView.test.js b/webapp/src/components/HistoricalData/HistoricalView.test.js index 5a0c9564..cf7db6c1 100644 --- a/webapp/src/components/HistoricalData/HistoricalView.test.js +++ b/webapp/src/components/HistoricalData/HistoricalView.test.js @@ -1,6 +1,10 @@ import { initReactI18next } from 'react-i18next'; import i18en from 'i18next'; +import axios from 'axios'; +import MockAdapter from 'axios-mock-adapter'; + +const mockAxios = new MockAdapter(axios); i18en.use(initReactI18next).init({ resources: {}, lng: 'en', @@ -11,7 +15,15 @@ i18en.use(initReactI18next).init({ global.i18en = i18en; describe('Historical View component', () => { + beforeEach(() => { + mockAxios.reset(); + }); + it('renders Game Record Buttons', () => { + mockAxios.onGet('http://localhost:8000/record/dummy').reply(200, + [{question: "What is the population of Oviedo?", + answers: ["225089","272357","267855","231841"]}]); + }); it('clicking Game Record Buttons Record Lists are displayed', () => { diff --git a/webapp/src/components/questionView/CreationHistoricalRecord.js b/webapp/src/components/questionView/CreationHistoricalRecord.js index e3b0cb91..ea8d33fb 100644 --- a/webapp/src/components/questionView/CreationHistoricalRecord.js +++ b/webapp/src/components/questionView/CreationHistoricalRecord.js @@ -40,12 +40,10 @@ class CreationHistoricalRecord{ game:this.record.game } try { - const response = await fetch(apiUrl, { - method: 'POST', + const response = await axios.post(apiUrl, body, { headers: { 'Content-Type': 'application/json' - }, - body: JSON.stringify(body) + } }); if (!response.ok) { diff --git a/webapp/src/components/questionView/QuestionView.js b/webapp/src/components/questionView/QuestionView.js index 2220e57d..834f2ba1 100644 --- a/webapp/src/components/questionView/QuestionView.js +++ b/webapp/src/components/questionView/QuestionView.js @@ -127,7 +127,7 @@ function QuestionComponent({questions, numQuestion, handleClick, t, points}){

    {questions[numQuestion].getQuestion()}

    - +
    diff --git a/webapp/src/components/questionView/QuestionView.test.js b/webapp/src/components/questionView/QuestionView.test.js index d631c659..aebbc0b7 100644 --- a/webapp/src/components/questionView/QuestionView.test.js +++ b/webapp/src/components/questionView/QuestionView.test.js @@ -1,4 +1,4 @@ -import { render , screen, waitFor } from '@testing-library/react'; +import { render , screen, waitFor, fireEvent } from '@testing-library/react'; import { initReactI18next } from 'react-i18next'; import i18en from 'i18next'; import QuestionView from './QuestionView'; @@ -9,8 +9,13 @@ import { UserContextProvider } from '../loginAndRegistration/UserContext'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; +import {configure} from '@testing-library/dom'; +configure({ + testIdAttribute: 'data-value', +}); + const mockAxios = new MockAdapter(axios); i18en.use(initReactI18next).init({ @@ -35,7 +40,7 @@ describe('Question View component', () => { // Wait for questions to load }); - it('shows a question',async () => { + it('shows a question and answers',async () => { mockAxios.onGet('http://localhost:8000/questions/en').reply(200, [{question: "What is the population of Oviedo?", @@ -55,51 +60,65 @@ describe('Question View component', () => { expect(screen.getByText('231841')).toBeInTheDocument() }); - /* - it('renders a question',async () => { - act(() => { - const { getByText } = render(); - }); - //h2 con la pregunta - const tituloH2 = screen.getByRole('heading', { level: 2 }); - // Verifica si el elemento h2 está presente en el documento - expect(tituloH2).toBeInTheDocument(); - });*/ - /* - it('render a question and 4 buttons for answers', () => { - act(() => { - render(); - }); - // Busca todos los botones por su rol - const botones = screen.getAllByRole('button'); - - // Verifica si hay exactamente 4 botones - expect(botones.length).toBe(4); + it('shows colors to reveal correct answer', async () => { + mockAxios.onGet('http://localhost:8000/questions/en').reply(200, + [{question: "What is the population of Oviedo?", + answers: ["225089","272357","267855","231841"]}]); + await act(async () =>{ + await render(); + + }) + await waitFor(() => expect(screen.getByText('What is the population of Oviedo?')).toBeInTheDocument()); + fireEvent.click(screen.getByTestId('true'));//clicamos en la respuesta correcta + // Esperar un segundo antes de continuar + await waitFor(() => { + // Clic en un botón de respuesta con data-value=true + const correctAnswerButton = screen.getByTestId('true'); + // Verificar que el botón tenga el color esperado + expect(correctAnswerButton).toHaveStyle('background-color: #6EF26E'); + }, { timeout: 1000 }); // Esperar 1 segundo }); - it('shows colors to reveal correct answer', () => { - act(() => { - render(); - fireEvent.click(queryHelpers.queryByAttribute('data-value', 'true'));//clicamos en la respuesta correcta - }); - - // Clic en un botón de respuesta con data-value=true - const correctAnswerButton = queryHelpers.queryByAttribute('data-value', 'true'); - // Verificar que el botón tenga el color esperado - expect(correctAnswerButton).toHaveStyle('background-color: #6EF26E'); + it('shows colors to reveal false answer', async () => { + mockAxios.onGet('http://localhost:8000/questions/en').reply(200, + [{question: "What is the population of Oviedo?", + answers: ["225089","272357","267855","231841"]}]); + await act(async () =>{ + await render(); + + }) + await waitFor(() => expect(screen.getByText('What is the population of Oviedo?')).toBeInTheDocument()); + fireEvent.click(screen.getAllByTestId('false')[0]); + // Esperar un segundo antes de continuar + await waitFor(() => { + // Clic en un botón de respuesta con data-value=true + const incorrectAnswerButton = screen.getAllByTestId('false')[0]; + // Verificar que el botón tenga el color esperado + expect(incorrectAnswerButton).toHaveStyle('background-color: #FF6666'); + }, { timeout: 1000 }); // Esperar 1 segundo + }); + it('shows timer', async () => { + mockAxios.onGet('http://localhost:8000/questions/en').reply(200, + [{question: "What is the population of Oviedo?", + answers: ["225089","272357","267855","231841"]}]); + await act(async () =>{ + await render(); + + }) + await waitFor(() => expect(screen.getByText('What is the population of Oviedo?')).toBeInTheDocument()); + const timerElement = screen.getByText(new RegExp(`(\\d+) ${i18en.t('questionView.seconds')}`)); + expect(timerElement).toBeInTheDocument(); // Verificar que el temporizador esté presente en el DOM + }); + it('shows timer has finished', async () => { + jest.useFakeTimers(); + mockAxios.onGet('http://localhost:8000/questions/en').reply(200, + [{question: "What is the population of Oviedo?", + answers: ["225089","272357","267855","231841"]}]); + await act(async () =>{ + await render(); + + }) + jest.advanceTimersByTime(11000); + const timerElement = screen.getByText(i18en.t('questionView.end_countdown')); + expect(timerElement).toBeInTheDocument(); // Verificar que el temporizador esté presente en el DOM }); - it('shows colors to reveal false answer', () => { - act(() => { - render(); - const falseAnswerButtons = (dataValue)=> queryHelpers.queryAllByAttribute('data-value', dataValue)('false'); - fireEvent.click(falseAnswerButtons.get(0)); - }); - - - // Obtener el botón de respuesta falso por su atributo data-value - const falseAnswerButton = queryHelpers.queryAllByAttribute('data-value', 'false').get(0); - - // Verificar que el botón tenga el color esperado - expect(falseAnswerButton).toHaveStyle('background-color:#FF6666'); - - });*/ }); \ No newline at end of file From 7de042592b7472fa4ec61ae39f2374d0938618e7 Mon Sep 17 00:00:00 2001 From: uo289267 Date: Sun, 7 Apr 2024 14:52:30 +0200 Subject: [PATCH 51/66] Added more jest tests for QuestionView and pseudo tests --- .../questionView/QuestionView.test.js | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/webapp/src/components/questionView/QuestionView.test.js b/webapp/src/components/questionView/QuestionView.test.js index 9144c955..65167319 100644 --- a/webapp/src/components/questionView/QuestionView.test.js +++ b/webapp/src/components/questionView/QuestionView.test.js @@ -4,7 +4,6 @@ import i18en from 'i18next'; import QuestionView from './QuestionView'; import { MemoryRouter } from 'react-router-dom'; import { act } from 'react-dom/test-utils'; -import {queryHelpers, buildQueries} from '@testing-library/react'; import { UserContextProvider} from '../loginAndRegistration/UserContext'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; @@ -109,17 +108,35 @@ describe('Question View component', () => { const timerElement = screen.getByText(new RegExp(`(\\d+) ${i18en.t('questionView.seconds')}`)); expect(timerElement).toBeInTheDocument(); // Verificar que el temporizador esté presente en el DOM }); + /* it('shows timer has finished', async () => { jest.useFakeTimers(); mockAxios.onGet('http://localhost:8000/questions/en').reply(200, [{question: "What is the population of Oviedo?", + answers: ["225089","272357","267855","231841"]}], + [{question: "What is the population of Avilés?", answers: ["225089","272357","267855","231841"]}]); await act(async () =>{ await render(); - + jest.advanceTimersByTime(11000); }) - jest.advanceTimersByTime(11000); - const timerElement = screen.getByText(i18en.t('questionView.end_countdown')); + + const timerElement = await screen.findByText(i18en.t('questionView.end_countdown')); expect(timerElement).toBeInTheDocument(); // Verificar que el temporizador esté presente en el DOM - }); + });*/ + /* + it('shows second question', async () => { + jest.useFakeTimers(); + mockAxios.onGet('http://localhost:8000/questions/en').reply(200, + [{question: "What is the population of Oviedo?", + answers: ["225089","272357","267855","231841"]}], + [{question: "What is the population of Avilés?", + answers: ["225089","272357","267855","231841"]}]); + await act(async () =>{ + await render(); + jest.advanceTimersByTime(11000); + }) + + await waitFor(() => expect(screen.getByText('What is the population of Avilés?')).toBeInTheDocument()); + });*/ }); \ No newline at end of file From 00d1d04a03316dfaf7409481d12918f66c6dc1b6 Mon Sep 17 00:00:00 2001 From: lauratbg Date: Sun, 7 Apr 2024 15:48:06 +0200 Subject: [PATCH 52/66] Trying --- package-lock.json | 1478 +++++++++++++++++++++++++++++- package.json | 4 + webapp/e2e/features/home.feature | 16 + webapp/e2e/jest.config.js | 1 + webapp/e2e/steps/home.steps.js | 44 + webapp/package-lock.json | 562 +++++++++++- webapp/package.json | 10 + 7 files changed, 2057 insertions(+), 58 deletions(-) create mode 100644 webapp/e2e/features/home.feature create mode 100644 webapp/e2e/steps/home.steps.js diff --git a/package-lock.json b/package-lock.json index 354f7e9a..6eb812e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,12 @@ "@material-ui/icons": "^4.11.3", "@testing-library/react-hooks": "^8.0.1", "asciidoctor-emoji": "^0.5.0", + "bcrypt": "^5.1.1", + "express": "^4.19.2", "i18n": "^0.15.1", "i18next": "^23.10.1", + "jsonwebtoken": "^9.0.2", + "mongoose": "^8.3.0", "react-countdown": "^2.3.5", "react-i18next": "^14.1.0", "react-router-dom": "^6.22.1" @@ -1020,6 +1024,77 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/@material-ui/core": { "version": "4.12.4", "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz", @@ -1217,6 +1292,14 @@ "make-plural": "^7.0.0" } }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.5.tgz", + "integrity": "sha512-XLNOMH66KhJzUJNwT/qlMnS4WsNDWD5ASdyaSH3EtK+F4r/CFGa3jT4GNi4mfOitGvWXtdLgQJkQjxSVrio+jA==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@remix-run/router": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz", @@ -1400,6 +1483,19 @@ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", @@ -1415,6 +1511,34 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -1434,7 +1558,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -1467,6 +1590,23 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -1476,6 +1616,11 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, "node_modules/asciidoctor-emoji": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/asciidoctor-emoji/-/asciidoctor-emoji-0.5.0.tgz", @@ -1596,6 +1741,55 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/boolean": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", @@ -1663,12 +1857,51 @@ "node-int64": "^0.4.0" } }, + "node_modules/bson": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.6.0.tgz", + "integrity": "sha512-BVINv2SgcMjL4oYbBuCQTpE3/VKOSxrOA8Cj/wQP7izSzlBGVomdm+TcUd0Pzy0ytLSSDweCKQ6X3f5veM5LQA==", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1732,6 +1965,14 @@ "node": ">=10" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -1809,11 +2050,42 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } }, "node_modules/convert-source-map": { "version": "2.0.0", @@ -1821,6 +2093,19 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -1909,6 +2194,52 @@ "node": ">=0.10.0" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -1941,6 +2272,19 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, "node_modules/electron-to-chromium": { "version": "1.4.723", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.723.tgz", @@ -1962,8 +2306,15 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } }, "node_modules/error-ex": { "version": "1.3.2", @@ -1974,6 +2325,25 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", @@ -1983,6 +2353,11 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, "node_modules/escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", @@ -2005,6 +2380,14 @@ "node": ">=4" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -2053,6 +2436,60 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2091,6 +2528,36 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -2104,6 +2571,49 @@ "node": ">=8" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2127,11 +2637,29 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -2150,6 +2678,24 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -2199,12 +2745,23 @@ "node": ">=4" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2214,11 +2771,48 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -2253,6 +2847,33 @@ "void-elements": "3.1.0" } }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -2308,6 +2929,17 @@ "@babel/runtime": "^7.23.2" } }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/import-local": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", @@ -2350,6 +2982,14 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -2372,7 +3012,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -3237,6 +3876,57 @@ "node": ">=6" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsonwebtoken/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/jss": { "version": "10.10.0", "resolved": "https://registry.npmjs.org/jss/-/jss-10.10.0.tgz", @@ -3324,6 +4014,33 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/kareem": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.0.tgz", + "integrity": "sha512-B9wwgyKKKZkxYZXQzefvb/Ykh9eHixxR+ttTP2c/Pq8NvHi1iYIAImf3nj/DXkPcnenjGEffhPWXnCFRIbNAhw==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -3360,6 +4077,41 @@ "node": ">=8" } }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -3450,12 +4202,38 @@ "node": ">=0.10.0" } }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -3469,6 +4247,36 @@ "node": ">=8.6" } }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -3490,11 +4298,157 @@ "node": ">=10" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mongodb": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.5.0.tgz", + "integrity": "sha512-Fozq68InT+JKABGLqctgtb8P56pRrJFkbhW0ux+x1mdHeyinor8oNzJqwLjV/t5X5nJGfTlluxfyMnOXNggIUA==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.4.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", + "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.3.0.tgz", + "integrity": "sha512-Y5QNnuA38CEin8hnA+q//nUVztIi4Xklu9xlmbkd1KdWHnIlemSwf5IL/evcI+e2zplL4g5Y6PMkO+nPSAnIdA==", + "dependencies": { + "bson": "^6.5.0", + "kareem": "2.6.0", + "mongodb": "6.5.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/moo": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -3514,6 +4468,57 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -3526,6 +4531,20 @@ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -3547,6 +4566,17 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3555,6 +4585,25 @@ "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3647,6 +4696,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3660,7 +4717,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3680,6 +4736,11 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -3784,6 +4845,26 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -3800,6 +4881,42 @@ } ] }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/react": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", @@ -3925,6 +5042,19 @@ "react-dom": ">=16.6.0" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", @@ -3986,11 +5116,88 @@ "node": ">=10" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/safe-identifier": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==" }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "node_modules/scheduler": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", @@ -4010,6 +5217,87 @@ "semver": "bin/semver.js" } }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4031,11 +5319,32 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/sisteransi": { "version": "1.0.5", @@ -4071,6 +5380,14 @@ "source-map": "^0.6.0" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -4089,6 +5406,22 @@ "node": ">=10" } }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -4106,7 +5439,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -4120,7 +5452,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -4182,6 +5513,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -4270,6 +5622,25 @@ "node": ">=8.0" } }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -4291,12 +5662,32 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/unxhr": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.2.0.tgz", @@ -4336,6 +5727,19 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/v8-to-istanbul": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", @@ -4350,6 +5754,14 @@ "node": ">=10.12.0" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/void-elements": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", @@ -4367,6 +5779,26 @@ "makeerror": "1.0.12" } }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4382,6 +5814,14 @@ "node": ">= 8" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index cd13ae94..e7b64080 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,12 @@ "@material-ui/icons": "^4.11.3", "@testing-library/react-hooks": "^8.0.1", "asciidoctor-emoji": "^0.5.0", + "bcrypt": "^5.1.1", + "express": "^4.19.2", "i18n": "^0.15.1", "i18next": "^23.10.1", + "jsonwebtoken": "^9.0.2", + "mongoose": "^8.3.0", "react-countdown": "^2.3.5", "react-i18next": "^14.1.0", "react-router-dom": "^6.22.1" diff --git a/webapp/e2e/features/home.feature b/webapp/e2e/features/home.feature new file mode 100644 index 00000000..47583e2f --- /dev/null +++ b/webapp/e2e/features/home.feature @@ -0,0 +1,16 @@ +Feature: Home page functionality + + Scenario: The text container is initially visible + Given I am on the home page + Then The text container should be visible + + Scenario: Opening the text container + Given I am on the home page + When I click on the toggle button to open + Then The text container should be hidden + + Scenario: Closing the text container + Given I am on the home page + When I click on the toggle button to close + Then The text container should be visible + diff --git a/webapp/e2e/jest.config.js b/webapp/e2e/jest.config.js index db3be3d9..34fd2f81 100644 --- a/webapp/e2e/jest.config.js +++ b/webapp/e2e/jest.config.js @@ -2,4 +2,5 @@ module.exports = { testMatch: ["**/steps/*.js"], testTimeout: 30000, setupFilesAfterEnv: ["expect-puppeteer"] + } \ No newline at end of file diff --git a/webapp/e2e/steps/home.steps.js b/webapp/e2e/steps/home.steps.js new file mode 100644 index 00000000..21609f0f --- /dev/null +++ b/webapp/e2e/steps/home.steps.js @@ -0,0 +1,44 @@ +const puppeteer = require('puppeteer'); +const { defineFeature, loadFeature } = require('jest-cucumber'); +const setDefaultOptions = require('expect-puppeteer').setDefaultOptions; + +const feature = loadFeature('./features/home.feature'); + +let page; +let browser; + +defineFeature(feature, test => { + + beforeAll(async () => { + browser = await puppeteer.launch({ headless: false }); + page = await browser.newPage(); + setDefaultOptions({ timeout: 10000 }); + }); + + test('Home page functionality', ({ given, when, then }) => { + given('I am on the home page', async () => { + await page.goto('http://localhost:3000/home'); + await page.waitForSelector('.general'); + }); + + when('I click on the toggle button to open', async () => { + await page.click('#toggleOpen'); + }); + + then('The text container should be hidden', async () => { + await expect(page).toMatchElement('.text-container.hidden'); + }); + + when('I click on the toggle button to close', async () => { + await page.click('#toggleClose'); + }); + + then('The text container should be visible', async () => { + await expect(page).toMatchElement('.text-container.visible'); + }); + }); + + afterAll(async () => { + await browser.close(); + }); +}); diff --git a/webapp/package-lock.json b/webapp/package-lock.json index ad42295e..ca22e138 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -15,7 +15,11 @@ "@testing-library/react": "^14.1.2", "@testing-library/user-event": "^14.5.2", "axios": "^1.6.5", + "bcrypt": "^5.1.1", + "express": "^4.19.2", "i18n": "^0.15.1", + "jsonwebtoken": "^9.0.2", + "mongoose": "^8.3.0", "react": "^18.2.0", "react-countdown": "^2.3.5", "react-dom": "^18.2.0", @@ -4517,6 +4521,25 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, "node_modules/@messageformat/core": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/@messageformat/core/-/core-3.3.0.tgz", @@ -4557,11 +4580,9 @@ } }, "node_modules/@mongodb-js/saslprep": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.3.tgz", - "integrity": "sha512-SyCxhJfmK6MoLNV5SbDpNdUy9SDv5H7y9/9rl3KpnwgTHWuNNMc87zWqbcIZXNWY+aUjxLGLEcvHoLagG4tWCg==", - "dev": true, - "optional": true, + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.5.tgz", + "integrity": "sha512-XLNOMH66KhJzUJNwT/qlMnS4WsNDWD5ASdyaSH3EtK+F4r/CFGa3jT4GNi4mfOitGvWXtdLgQJkQjxSVrio+jA==", "dependencies": { "sparse-bitfield": "^3.0.3" } @@ -6035,8 +6056,7 @@ "node_modules/@types/webidl-conversions": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", - "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", - "dev": true + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" }, "node_modules/@types/whatwg-url": { "version": "8.2.2", @@ -6455,6 +6475,11 @@ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", "deprecated": "Use your platform's native atob() and btoa() methods instead" }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -6682,6 +6707,11 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, "node_modules/arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", @@ -6702,6 +6732,18 @@ } ] }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -7423,6 +7465,19 @@ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, + "node_modules/bcrypt": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz", + "integrity": "sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.11", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/bfj": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.1.0.tgz", @@ -7460,12 +7515,12 @@ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -7473,7 +7528,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -7770,6 +7825,11 @@ "node": "*" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -8070,6 +8130,14 @@ "node": ">= 6" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, "node_modules/chrome-trace-event": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", @@ -8317,6 +8385,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", @@ -8437,6 +8513,11 @@ "node": ">=0.8" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -8462,9 +8543,9 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "engines": { "node": ">= 0.6" } @@ -9332,6 +9413,11 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -9357,6 +9443,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -9581,6 +9675,14 @@ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -10819,16 +10921,16 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -11531,6 +11633,33 @@ "node": ">=12" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/fs-monkey": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", @@ -11587,6 +11716,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -11961,6 +12109,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -12531,7 +12684,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true + "devOptional": true }, "node_modules/ipaddr.js": { "version": "2.1.0", @@ -18534,6 +18687,27 @@ "node": ">=0.10.0" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -18548,6 +18722,33 @@ "node": ">=4.0" } }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/kareem": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.0.tgz", + "integrity": "sha512-B9wwgyKKKZkxYZXQzefvb/Ykh9eHixxR+ttTP2c/Pq8NvHi1iYIAImf3nj/DXkPcnenjGEffhPWXnCFRIbNAhw==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -18692,6 +18893,36 @@ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -18702,6 +18933,11 @@ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -18858,9 +19094,7 @@ "node_modules/memory-pager": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "dev": true, - "optional": true + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" }, "node_modules/merge-descriptors": { "version": "1.0.1", @@ -19045,6 +19279,34 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", @@ -19228,11 +19490,157 @@ "node": ">= 14" } }, + "node_modules/mongoose": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.3.0.tgz", + "integrity": "sha512-Y5QNnuA38CEin8hnA+q//nUVztIi4Xklu9xlmbkd1KdWHnIlemSwf5IL/evcI+e2zplL4g5Y6PMkO+nPSAnIdA==", + "dependencies": { + "bson": "^6.5.0", + "kareem": "2.6.0", + "mongodb": "6.5.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/@types/whatwg-url": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.4.tgz", + "integrity": "sha512-lXCmTWSHJvf0TRSO58nm978b8HJ/EdsSsEKLd3ODHFjo+3VGAyyTp4v50nWvwtzBxSMQrVOK7tcuN0zGPLICMw==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/mongoose/node_modules/bson": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.6.0.tgz", + "integrity": "sha512-BVINv2SgcMjL4oYbBuCQTpE3/VKOSxrOA8Cj/wQP7izSzlBGVomdm+TcUd0Pzy0ytLSSDweCKQ6X3f5veM5LQA==", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/mongoose/node_modules/mongodb": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.5.0.tgz", + "integrity": "sha512-Fozq68InT+JKABGLqctgtb8P56pRrJFkbhW0ux+x1mdHeyinor8oNzJqwLjV/t5X5nJGfTlluxfyMnOXNggIUA==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.4.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongoose/node_modules/mongodb-connection-string-url": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz", + "integrity": "sha512-t1Vf+m1I5hC2M5RJx/7AtxgABy1cZmIPQRMXw+gEIPn/cZNF3Oiy+l0UIypUwVB5trcWHq3crg2g3uAR9aAwsQ==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/mongoose/node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/mongoose/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/mongoose/node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/moo": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -19366,11 +19774,15 @@ "tslib": "^2.0.3" } }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -19389,20 +19801,17 @@ "node_modules/node-fetch/node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/node-fetch/node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/node-fetch/node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -19440,6 +19849,20 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -19499,6 +19922,17 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -21918,9 +22352,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -24729,8 +25163,7 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "node_modules/set-function-length": { "version": "1.1.1", @@ -24846,6 +25279,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -24868,7 +25306,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, + "devOptional": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -25033,7 +25471,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, + "devOptional": true, "dependencies": { "ip": "^2.0.0", "smart-buffer": "^4.2.0" @@ -25158,8 +25596,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "dev": true, - "optional": true, "dependencies": { "memory-pager": "^1.0.2" } @@ -25984,6 +26420,22 @@ "node": ">=6" } }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tar-fs": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", @@ -26006,6 +26458,30 @@ "streamx": "^2.15.0" } }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", @@ -27332,6 +27808,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/widest-line": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", diff --git a/webapp/package.json b/webapp/package.json index f31b2a0c..dee1cba8 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -10,7 +10,11 @@ "@testing-library/react": "^14.1.2", "@testing-library/user-event": "^14.5.2", "axios": "^1.6.5", + "bcrypt": "^5.1.1", + "express": "^4.19.2", "i18n": "^0.15.1", + "jsonwebtoken": "^9.0.2", + "mongoose": "^8.3.0", "react": "^18.2.0", "react-countdown": "^2.3.5", "react-dom": "^18.2.0", @@ -56,5 +60,11 @@ "puppeteer": "^21.7.0", "serve": "^14.2.1", "start-server-and-test": "^2.0.3" + }, + "jest": { + "testMatch": [ + "**/*.feature", + "**/*.steps.js" + ] } } From 91773a7f9877526d9809604913903a4efec6392f Mon Sep 17 00:00:00 2001 From: ErdemYabaci Date: Sun, 7 Apr 2024 17:33:39 +0200 Subject: [PATCH 53/66] =?UTF-8?q?Added=20documentation=20for=20questions?= =?UTF-8?q?=C2=A0endpoint=20and=20minor=20improvements.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gatewayservice/openapi.yaml | 125 ++++++++++++++++++++++++++++-------- 1 file changed, 99 insertions(+), 26 deletions(-) diff --git a/gatewayservice/openapi.yaml b/gatewayservice/openapi.yaml index 67bffccb..1c19d98e 100644 --- a/gatewayservice/openapi.yaml +++ b/gatewayservice/openapi.yaml @@ -1,8 +1,11 @@ openapi: 3.0.0 info: - title: Gatewayservice API - description: Gateway OpenAPI specification. - version: 0.2.0 + title: wiq_en1b API + description: Our project's OpenAPI specification. + version: 0.1.1 + contact: + name: Project github + url: https://github.com/Arquisoft/wiq_en1b servers: - url: http://localhost:8000 description: Development server @@ -38,24 +41,20 @@ paths: properties: username: type: string - description: User ID - password: - type: string - description: Hashed password - example: $2b$10$ZKdNYLWFQxzt5Rei/YTc/OsZNi12YiWz30JeUFHNdAt7MyfmkTuvC - _id: - type: string - description: Identification - example: 65f756db3fa22d227a4b7c7d - createdAt: - type: string - description: Creation date. - example: '2024-03-17T20:47:23.935Z' - ___v: - type: integer - example: '0' + description: User ID '400': - description: Failed to add user. + description: Failed to add user + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Username already in use + '500': + description: Internal server error. content: application/json: schema: @@ -64,7 +63,7 @@ paths: error: type: string description: Error information. - example: getaddrinfo EAI_AGAIN mongodb + example: Internal Server Error /health: get: summary: Check the health status of the service. @@ -116,11 +115,7 @@ paths: type: string description: Username. example: student - createdAt: - type: string - description: Creation date. - example: '2024-03-17T20:47:23.935Z' - '401': + '400': description: Invalid credentials. content: application/json: @@ -142,3 +137,81 @@ paths: type: string description: Error information. example: Internal Server Error + /questions: + get: + summary: Get 5 random questions from the system in any language + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/QuestionResponse' + + /questions/{lang}: + get: + summary: Get 5 random questions from the system in the lang specified + parameters: + - name: lang + in: path + required: true + schema: + type: string + description: Language code for filtering questions must be es or en + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/QuestionResponse' +components: + schemas: + LoginRequest: + type: object + properties: + username: + type: string + password: + type: string + required: + - username + - password + LoginResponse: + type: object + properties: + token: + type: string + User: + type: object + properties: + username: + type: string + email: + type: string + required: + - username + - email + UserResponse: + type: object + properties: + message: + type: string + QuestionResponse: + type: array + items: + type: object + properties: + question: + type: string + answers: + type: array + items: + type: string + correct_answer: + type: string + Error: + type: object + properties: + error: + type: string \ No newline at end of file From 673f292c580cd7fa2635e98744e08975824df977 Mon Sep 17 00:00:00 2001 From: uo289267 Date: Sun, 7 Apr 2024 18:07:30 +0200 Subject: [PATCH 54/66] Added more jest tests for Historical View --- .../src/components/GameMenu/GameMenu.test.js | 7 +- .../HistoricalData/HistoricalView.js | 8 +- .../HistoricalData/HistoricalView.test.js | 53 +++++++++--- .../HistoricalData/HistoryRecordRetriever.js | 4 +- .../questionView/QuestionView.test.js | 32 +------ webapp/src/translations/en/global.json | 3 +- webapp/src/translations/es/global.json | 3 +- webapp/src/translations/tk/global.json | 84 ++++++++++--------- 8 files changed, 96 insertions(+), 98 deletions(-) diff --git a/webapp/src/components/GameMenu/GameMenu.test.js b/webapp/src/components/GameMenu/GameMenu.test.js index 265e27a4..7d9b7e4d 100644 --- a/webapp/src/components/GameMenu/GameMenu.test.js +++ b/webapp/src/components/GameMenu/GameMenu.test.js @@ -13,12 +13,7 @@ i18en.use(initReactI18next).init({ } }); global.i18en = i18en; -/* -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/Game Menu/i); - expect(linkElement).toBeInTheDocument(); -});*/ + describe('GameMenu component', () => { it('renders Title for Game Menu view', () => { diff --git a/webapp/src/components/HistoricalData/HistoricalView.js b/webapp/src/components/HistoricalData/HistoricalView.js index 49b9e371..871d6125 100644 --- a/webapp/src/components/HistoricalData/HistoricalView.js +++ b/webapp/src/components/HistoricalData/HistoricalView.js @@ -15,15 +15,12 @@ export default function HistoricalView() { const {user} = useUserContext(); const getRecords = async ()=>{ - console.log("in") try { var jsonRecords = await retriever.getRecords(user.username); var recordsArray = jsonRecords.games; - console.log(recordsArray) setRecords(recordsArray); } catch (error) { - //Como hacer que funcione esto - console.log(error.response); + console.log(error); } } useEffect(() => {getRecords()}, []); @@ -31,14 +28,13 @@ export default function HistoricalView() {
    {(records && records.length != 0) ? records.map((record, index) => ( - )):

    No games played yet

    } + )):

    {t("historicalView.no_games_played")}

    }
    ) } function HistoricalGameElement({record,t}){ - console.log(record) const [toggle, setToggle] = useState(false); function handleClick (){ diff --git a/webapp/src/components/HistoricalData/HistoricalView.test.js b/webapp/src/components/HistoricalData/HistoricalView.test.js index cf7db6c1..43cf59bb 100644 --- a/webapp/src/components/HistoricalData/HistoricalView.test.js +++ b/webapp/src/components/HistoricalData/HistoricalView.test.js @@ -1,9 +1,12 @@ +import { render , screen, waitFor, fireEvent } from '@testing-library/react'; import { initReactI18next } from 'react-i18next'; import i18en from 'i18next'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; - - +import { MemoryRouter } from 'react-router-dom'; +import { UserContextProvider} from '../loginAndRegistration/UserContext'; +import HistoricalView from './HistoricalView'; +import { act } from 'react-dom/test-utils'; const mockAxios = new MockAdapter(axios); i18en.use(initReactI18next).init({ resources: {}, @@ -18,17 +21,45 @@ describe('Historical View component', () => { beforeEach(() => { mockAxios.reset(); }); + it('renders no games if the api is down', () => { + const user = { username: 'dummy' }; + render(); + const text = screen.getByText(i18en.t('historicalView.no_games_played')); + expect(text).toBeInTheDocument(); + }); + it('renders no games if the user has no games', async () => { + const user = { username: 'dummy' }; + mockAxios.onGet('http://localhost:8000/record/dummy').reply(200, "undefined"); - it('renders Game Record Buttons', () => { + await act(async()=> + await render() + ) + const text = screen.getByText(i18en.t('historicalView.no_games_played')); + expect(text).toBeInTheDocument(); + }); + it('renders Game Record Buttons', async () => { + const user = { username: 'dummy' }; mockAxios.onGet('http://localhost:8000/record/dummy').reply(200, - [{question: "What is the population of Oviedo?", - answers: ["225089","272357","267855","231841"]}]); + [{user: "dummy", + games: [{ + questions: [{ + question: "What is the capital of Spain?", + answers: ["Madrid", "Dubai", "London", "Barcelona"], + answerGiven: "Madrid", + correctAnswer: "Madrid" + }], + points: "200", + date: "1712344268728" + }]}]); - - }); - it('clicking Game Record Buttons Record Lists are displayed', () => { - /*render(); - const text = screen.getByText(i18en.t('gameMenu.title')); - expect(text).toBeInTheDocument();*/ + await act(async()=> + await render() + ) + const regex = /\d{1,2}\/\d{1,2}\/\d{4}/; // Expresión regular para el formato de fecha "MM/DD/YYYY" o "M/D/YYYY" + const textRegex = new RegExp(regex); + + const textElement = await screen.findByText(textRegex); + expect(textElement).toBeInTheDocument(); }); + }); \ No newline at end of file diff --git a/webapp/src/components/HistoricalData/HistoryRecordRetriever.js b/webapp/src/components/HistoricalData/HistoryRecordRetriever.js index cc60fe04..5b574310 100644 --- a/webapp/src/components/HistoricalData/HistoryRecordRetriever.js +++ b/webapp/src/components/HistoricalData/HistoryRecordRetriever.js @@ -11,9 +11,11 @@ class HistoryRecordRetriever{ try { const response = await axios.get(this.apiUrl + '/' + user); const receivedRecords = await response.data; - return receivedRecords.record; + return receivedRecords[0]; } catch (error) { + console.log(error) throw new Error(error); + } } diff --git a/webapp/src/components/questionView/QuestionView.test.js b/webapp/src/components/questionView/QuestionView.test.js index 65167319..25392c62 100644 --- a/webapp/src/components/questionView/QuestionView.test.js +++ b/webapp/src/components/questionView/QuestionView.test.js @@ -108,35 +108,5 @@ describe('Question View component', () => { const timerElement = screen.getByText(new RegExp(`(\\d+) ${i18en.t('questionView.seconds')}`)); expect(timerElement).toBeInTheDocument(); // Verificar que el temporizador esté presente en el DOM }); - /* - it('shows timer has finished', async () => { - jest.useFakeTimers(); - mockAxios.onGet('http://localhost:8000/questions/en').reply(200, - [{question: "What is the population of Oviedo?", - answers: ["225089","272357","267855","231841"]}], - [{question: "What is the population of Avilés?", - answers: ["225089","272357","267855","231841"]}]); - await act(async () =>{ - await render(); - jest.advanceTimersByTime(11000); - }) - - const timerElement = await screen.findByText(i18en.t('questionView.end_countdown')); - expect(timerElement).toBeInTheDocument(); // Verificar que el temporizador esté presente en el DOM - });*/ - /* - it('shows second question', async () => { - jest.useFakeTimers(); - mockAxios.onGet('http://localhost:8000/questions/en').reply(200, - [{question: "What is the population of Oviedo?", - answers: ["225089","272357","267855","231841"]}], - [{question: "What is the population of Avilés?", - answers: ["225089","272357","267855","231841"]}]); - await act(async () =>{ - await render(); - jest.advanceTimersByTime(11000); - }) - - await waitFor(() => expect(screen.getByText('What is the population of Avilés?')).toBeInTheDocument()); - });*/ + }); \ No newline at end of file diff --git a/webapp/src/translations/en/global.json b/webapp/src/translations/en/global.json index 1deefdd4..8764c1d8 100644 --- a/webapp/src/translations/en/global.json +++ b/webapp/src/translations/en/global.json @@ -65,7 +65,8 @@ }, "historicalView":{ "game":"Game", - "points":"points" + "points":"points", + "no_games_played":"No games played yet" } } diff --git a/webapp/src/translations/es/global.json b/webapp/src/translations/es/global.json index 6a034a05..a61e665b 100644 --- a/webapp/src/translations/es/global.json +++ b/webapp/src/translations/es/global.json @@ -68,7 +68,8 @@ }, "historicalView":{ "game":"Partida", - "points":"puntos" + "points":"puntos", + "no_games_played":"No has jugado todavía" } diff --git a/webapp/src/translations/tk/global.json b/webapp/src/translations/tk/global.json index 7e7c89d6..dad822ba 100644 --- a/webapp/src/translations/tk/global.json +++ b/webapp/src/translations/tk/global.json @@ -1,69 +1,71 @@ { - "home": { - "welcome": "WIQ'a hoş geldiniz!", + "home": { + "welcome": "WIQ'e hoş geldiniz!", "how_to_play": "Nasıl Oynanır?", - "login": "Giriş yap", + "login": "Giriş Yap", "register": "Hesabınız yok mu? Buradan kaydolun.", - "language": "Dil İspanyolca olarak değiştirildi", - "msg1": "Bilgi meydan okumasına hoş geldiniz! Zihninizin becerilerini ve bilginizi test etmeye hazırlanın. Bu heyecan verici oyununuzda, çeşitli konulardaki bilginizi sınayacak bir dizi soruyla karşılaşacaksınız.", - "msg2": "Öyleyse, kendinizi soruların efendisi olarak kanıtlamaya hazır mısınız? Meydan okumayı kabul etmeye hazır mısınız?" - }, - "navBar": { - "title": "Bil ve Kazan!", + "language": "Dil İngilizce olarak değiştirildi", + "msg1": "Bilgi yarışmasına hoş geldiniz! Zihninizin sınırlarını test etmeye ve becerilerinizi göstermeye hazır olun. Bu heyecan verici oyunda, çeşitli konularda bilginizi sınamanıza neden olacak bir dizi soruyla karşılaşacaksınız.", + "msg2": "Haydi, soruların ustası olduğunuzu kanıtlayın! Zorluğa hazır mısınız?" + }, + "navBar": { + "title": "Bilgi ve Kazan!", "en": "İngilizce", "es": "İspanyolca", "tk": "Türkçe", "language": "Dil" - }, - "instructions": { + }, + "instructions": { "title": "WIQ Talimatları", "objective": "Amaç:", - "objective_p1": "Oyunun amacı mümkün olduğunca çok soruyu doğru cevaplamaktır.", + "objective_p1": "Oyunun amacı, mümkün olduğunca çok soruyu doğru cevaplamaktır.", "how_to_play": "Nasıl Oynanır:", - "how_to_play_p1": "Oyun bir dizi sorudan oluşur.", + "how_to_play_p1": "Oyun, bir dizi sorudan oluşur.", "how_to_play_p2": "Her soruyu dikkatlice okuyun.", - "how_to_play_p3": "Sağlanan seçeneklerden doğru cevabı seçin.", - "how_to_play_p4": "Seçtiğiniz cevabı göndermek için tıklayın veya dokunun.", + "how_to_play_p3": "Sağlanan seçenekler arasından doğru cevabı seçin.", + "how_to_play_p4": "Seçtiğiniz cevabı göndermek için üzerine tıklayın veya dokunun.", "scoring": "Puanlama:", "scoring_p1": "Her doğru cevap size x puan kazandırır.", - "scoring_p2": "Yanlış cevaplar puan kaybettirmez.", + "scoring_p2": "Yanlış cevaplar puan kesintisi yapmaz.", "time_limit": "Zaman Sınırı:", - "time_limit_p1": "Bazı oyun modları her soruya cevap vermek için bir zaman sınırına sahip olabilir. En yüksek puanı almak için hızlı ve doğru olun.", - "have_fun": "İyi eğlenceler!", - "have_fun_p1": "Oyunun tadını çıkarın ve bilginizi sınamaktan keyif alın. İyi şanslar!" - }, - "login": { - "title": "Giriş yap", - "username_placeholder": "Kullanıcı adı", + "time_limit_p1": "Bazı oyun modları, her soruyu cevaplama için bir zaman sınırına sahip olabilir. Skorunuzu maksimize etmek için hızlı ve doğru olun.", + "have_fun": "İyi Eğlenceler!:", + "have_fun_p1": "Oyunun tadını çıkarın ve bilginizi test edin. İyi şanslar!" + }, + "login": { + "title": "Giriş", + "username_placeholder": "Kullanıcı Adı", "password_placeholder": "Şifre", "remember_me": "Beni hatırla", "forgot_password": "Şifrenizi mi unuttunuz?", - "login_button": "Giriş yap", + "login_button": "Giriş", "register_link": "Hesabınız yok mu? Buradan kaydolun." - }, - "addUser": { + }, + "addUser": { "title": "Kayıt Ol", - "username_placeholder": "Kullanıcı adı", + "username_placeholder": "Kullanıcı Adı", "password_placeholder": "Şifre", - "repeat_password_placeholder": "Şifreyi tekrarlayın", - "register_button": "Kayıt ol", - "login_link": "Zaten bir hesabınız mı var? Buradan giriş yapın." - }, - "gameMenu": { - "history_button": "Geçmişi Görüntüle", + "repeat_password_placeholder": "Şifreyi Tekrar Girin", + "register_button": "Kayıt Ol", + "login_link": "Hesabınız var mı? Buradan giriş yapın." + }, + "gameMenu": { + "history_button": "Tarihsel Verileri Görüntüle", "new_game_button": "Yeni Oyun Oluştur", "title": "Oyun Menüsü" - }, - "questionView": { + }, + "questionView": { "seconds": "saniye", - "question_counter": "Soru no. ", - "end_countdown": "Zaman doldu!", + "question_counter": "Soru numarası ", + "end_countdown": "Süre doldu!", "finished_game": "Oyun bitti!", "point": "Puan", "no_questions_message": "Lütfen biraz bekleyin" - }, - "historicalView": { + }, + "historicalView": { "game": "Oyun", - "points": "puanlar" + "points": "puanlar", + "no_games_played": "Henüz oyun oynanmadı" + } } -} + \ No newline at end of file From ee7b37912f8d34d2592697313dc5a53f6d937696 Mon Sep 17 00:00:00 2001 From: ErdemYabaci Date: Sun, 7 Apr 2024 18:18:48 +0200 Subject: [PATCH 55/66] =?UTF-8?q?Added=20documentation=20for=20record?= =?UTF-8?q?=C2=A0endpoints.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gatewayservice/openapi.yaml | 75 +++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/gatewayservice/openapi.yaml b/gatewayservice/openapi.yaml index 1c19d98e..a8df8890 100644 --- a/gatewayservice/openapi.yaml +++ b/gatewayservice/openapi.yaml @@ -2,7 +2,7 @@ openapi: 3.0.0 info: title: wiq_en1b API description: Our project's OpenAPI specification. - version: 0.1.1 + version: 0.1.2 contact: name: Project github url: https://github.com/Arquisoft/wiq_en1b @@ -101,7 +101,7 @@ paths: example: pass responses: '200': - description: Login successful. Returns user token, username, and creation date. + description: Login successful. Returns user token, and username. content: application/json: schema: @@ -146,8 +146,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/QuestionResponse' - + $ref: '#/components/schemas/QuestionResponse' /questions/{lang}: get: summary: Get 5 random questions from the system in the lang specified @@ -165,6 +164,42 @@ paths: application/json: schema: $ref: '#/components/schemas/QuestionResponse' + /record: + post: + summary: Add a new record to the database + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Record' + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + user: + type: string + /record/{user}: + get: + summary: Gets the records from a given user + parameters: + - name: user + in: path + required: true + schema: + type: string + description: Username for filtering records + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Record' components: schemas: LoginRequest: @@ -210,6 +245,38 @@ components: type: string correct_answer: type: string + Record: + type: object + properties: + user: + type: string + games: + type: array + items: + type: object + properties: + questions: + type: array + items: + type: object + properties: + question: + type: string + answers: + type: array + items: + type: string + answerGiven: + type: string + correctAnswer: + type: string + points: + type: number + date: + type: string + required: + - user + - games Error: type: object properties: From 83c08cd33806be25fca0514f726435f4505313ed Mon Sep 17 00:00:00 2001 From: ErdemYabaci Date: Sun, 7 Apr 2024 18:56:50 +0200 Subject: [PATCH 56/66] minor fixes for record --- gatewayservice/openapi.yaml | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/gatewayservice/openapi.yaml b/gatewayservice/openapi.yaml index a8df8890..98968bbf 100644 --- a/gatewayservice/openapi.yaml +++ b/gatewayservice/openapi.yaml @@ -199,7 +199,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Record' + $ref: '#/components/schemas/RecordResponse' components: schemas: LoginRequest: @@ -246,6 +246,37 @@ components: correct_answer: type: string Record: + type: object + properties: + user: + type: string + game: + type: object + properties: + questions: + type: array + items: + type: object + properties: + question: + type: string + example: What is the capital of Oviedo? + answers: + type: array + items: + type: string + answerGiven: + type: string + correctAnswer: + type: string + points: + type: number + date: + type: string + required: + - user + - game + RecordResponse: type: object properties: user: @@ -262,6 +293,7 @@ components: properties: question: type: string + example: What is the capital of Oviedo? answers: type: array items: @@ -274,9 +306,6 @@ components: type: number date: type: string - required: - - user - - games Error: type: object properties: From a30e33466af0473e98d7432023f6d0c9392a2621 Mon Sep 17 00:00:00 2001 From: jorge Date: Sun, 7 Apr 2024 21:48:07 +0200 Subject: [PATCH 57/66] Fixed the flaky tests --- questionGenerator/src/main/java/MainMock.java | 52 ------- .../questionGenerator/QuestionGenerator.java | 22 +-- .../QuestionGeneratorMock.java | 127 ------------------ .../generator/AbstractGenerator.java | 14 +- .../generator/AnswersAreEntities.java | 20 +-- 5 files changed, 30 insertions(+), 205 deletions(-) delete mode 100644 questionGenerator/src/main/java/MainMock.java delete mode 100644 questionGenerator/src/main/java/questionGenerator/QuestionGeneratorMock.java diff --git a/questionGenerator/src/main/java/MainMock.java b/questionGenerator/src/main/java/MainMock.java deleted file mode 100644 index 208458da..00000000 --- a/questionGenerator/src/main/java/MainMock.java +++ /dev/null @@ -1,52 +0,0 @@ -package main.java; - -import java.util.ArrayList; -import java.util.List; - -import main.java.questionGenerator.QuestionGeneratorMock; -import main.java.questionGenerator.question.Question; -import main.java.questionGenerator.question.QuestionType; -import main.java.questionGenerator.repository.QuestionRepository; - -public class MainMock { - - private static QuestionType[] types = {QuestionType.POPULATION, QuestionType.CAPITAL, QuestionType.SIZE, - QuestionType.LANGUAGE}; - - public static void main(String[] args) { - System.out.println("Ahora en Espa�ol"); - QuestionGeneratorMock qg = new QuestionGeneratorMock("es"); - for(QuestionType t : types) { - run(qg, t); - System.out.println(); - } - System.out.println("Now English"); - qg = new QuestionGeneratorMock("en"); - for(QuestionType t : types) { - run(qg, t); - System.out.println(); - } - System.out.println("Now in english but with bad language code"); - qg = new QuestionGeneratorMock("ep"); - for(QuestionType t : types) { - run(qg, t); - System.out.println(); - } - - } - - private static void run(QuestionGeneratorMock qg, QuestionType type) { - List questionJSONList = new ArrayList<>(); - - //Populate JSON list here - for(int i=0; i<3; i++) { - Question question = qg.generateQuestion(type); - question.setNumber(i); - questionJSONList.add(question.getJSON().toString()); - System.out.println(question.getJSON().toString()); - } - - QuestionRepository.getInstance().insert(questionJSONList); - } - -} diff --git a/questionGenerator/src/main/java/questionGenerator/QuestionGenerator.java b/questionGenerator/src/main/java/questionGenerator/QuestionGenerator.java index 92879cbe..2c5f81b2 100644 --- a/questionGenerator/src/main/java/questionGenerator/QuestionGenerator.java +++ b/questionGenerator/src/main/java/questionGenerator/QuestionGenerator.java @@ -15,8 +15,8 @@ import main.java.questionGenerator.question.QuestionType; public class QuestionGenerator { - - private AbstractGenerator generator; + + private AbstractGenerator generator; private String languageCode; public QuestionGenerator(String languageCode){ @@ -33,19 +33,21 @@ public List generateQuestions(QuestionType type, int amount){ } catch (IOException e) { e.printStackTrace(); } - Random rnd = new Random(); - List chosen = new ArrayList<>(); + Random rnd = new Random(); int size = entites.size(); - int number = 0; - while(number0) { int index = rnd.nextInt(size); String entity = entites.get(index); - if(!chosen.contains(entity)) { - chosen.add(entity); - Question q = generator.generate(entity); + entites.remove(index); + Question q = null; + try { + q = generator.generate(entity); questions.add(q); - number++; + } catch (Exception e) { + //If there's any problem generating the question we jump to the next one + System.err.println(e.getMessage()); } + size = entites.size(); } return questions; } diff --git a/questionGenerator/src/main/java/questionGenerator/QuestionGeneratorMock.java b/questionGenerator/src/main/java/questionGenerator/QuestionGeneratorMock.java deleted file mode 100644 index d40b6fc6..00000000 --- a/questionGenerator/src/main/java/questionGenerator/QuestionGeneratorMock.java +++ /dev/null @@ -1,127 +0,0 @@ -package main.java.questionGenerator; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -import main.java.questionGenerator.entityGenerator.EntityGenerator; -import main.java.questionGenerator.generator.AbstractGenerator; -import main.java.questionGenerator.generator.specificGenerators.CapitalGenerator; -import main.java.questionGenerator.generator.specificGenerators.LanguageGenerator; -import main.java.questionGenerator.generator.specificGenerators.PopulationGenerator; -import main.java.questionGenerator.generator.specificGenerators.SizeGenerator; -import main.java.questionGenerator.question.Question; -import main.java.questionGenerator.question.QuestionType; - -public class QuestionGeneratorMock { - - private AbstractGenerator generator; - private String id; - private String languageCode; - - private static String[] POP_ENTITIES = {"Q14317", "Q12273", "Q14649"}; - private static String[] CAP_ENTITIES = {"Q3934", "Q29", "Q43"}; - private static String[] SIZE_ENTITIES = {"Q29", "Q12273", "Q3934"}; - private static String[] LANG_ENTITIES = {"Q29", "Q43", "Q3934"}; - - public QuestionGeneratorMock(String languageCode){ - this.languageCode = languageCode; - } - - public Question generateQuestion(QuestionType type) { - generatorFactory(type); - generator.setLocalization(languageCode); - return generator.generate(id); - } - - public List generateQuestions(QuestionType type, int amount){ - setGenerator(type); - generator.setLocalization(languageCode); - List questions = new ArrayList<>(); - List entites = new ArrayList<>(); - try { - entites = EntityGenerator.getEntities(type, 100); - } catch (IOException e) { - e.printStackTrace(); - } - Random rnd = new Random(); - List chosen = new ArrayList<>(); - int size = entites.size(); - int number = 0; - while(number names) { return mtv.getText(); } +// protected abstract String getQuestion(String name); + protected abstract String getRightAnswer(Map> claims) throws Exception; + protected abstract List getWrongAnswers(String rightAnswer) throws Exception; protected String getQuestion(String name) { String q = getMessages().getString(message); return String.format(q, name); } - protected abstract String getRightAnswer(Map> claims); - protected abstract List getWrongAnswers(String rightAnswer); - - public String getPropertyId() { return propertyId; } - + public static ItemDocumentImpl getAlreadyProcessedEntity(String id) { return alreadyProcessedEntities.get(id); } diff --git a/questionGenerator/src/main/java/questionGenerator/generator/AnswersAreEntities.java b/questionGenerator/src/main/java/questionGenerator/generator/AnswersAreEntities.java index 171b22cc..f7bd6713 100644 --- a/questionGenerator/src/main/java/questionGenerator/generator/AnswersAreEntities.java +++ b/questionGenerator/src/main/java/questionGenerator/generator/AnswersAreEntities.java @@ -16,9 +16,9 @@ import main.java.questionGenerator.question.QuestionType; public abstract class AnswersAreEntities extends AbstractGenerator { - + private final String PROPERTY_TO_CHECK; - private final QuestionType type; + private QuestionType type; public AnswersAreEntities(String propertyId, QuestionType type, String propertyToCheck, String message) { super(propertyId, type, message); @@ -27,7 +27,11 @@ public AnswersAreEntities(String propertyId, QuestionType type, String propertyT } @Override - protected String getRightAnswer(Map> claims) { + protected String getRightAnswer(Map> claims) throws Exception { + if(claims.get(super.getPropertyId())==null) { + throw new Exception("Claims does not have the property " + super.getPropertyId()); + } + for(Statement st : claims.get(super.getPropertyId())) { boolean valid = true; for(SnakGroup sg : st.getQualifiers()) { @@ -48,7 +52,7 @@ protected String getRightAnswer(Map> claims) { return null; } - protected String processRightAnswer(Statement st) { + private String processRightAnswer(Statement st) { String entity = getIdFromLink(st.getValue().toString()); String answer = ""; try { @@ -66,7 +70,7 @@ protected String processRightAnswer(Statement st) { return answer; } - protected String getAnswer(String id){ + private String getAnswer(String id) throws Exception{ ItemDocumentImpl idi = getAlreadyProcessedEntity(id); if(idi==null) { @@ -93,7 +97,7 @@ protected String getIdFromLink(String url) { } @Override - protected List getWrongAnswers(String rightAnswer) { + protected List getWrongAnswers(String rightAnswer) throws Exception { List entites = new ArrayList<>(); try { entites = EntityGenerator.getEntities(type, 100); @@ -102,15 +106,13 @@ protected List getWrongAnswers(String rightAnswer) { } Random rnd = new Random(); List result = new ArrayList<>(); - List used = new ArrayList<>(); for(int i = 0; i < 3; i++){ int rndnum = rnd.nextInt(entites.size()); String wrong = getAnswer(entites.get(rndnum)); - if(wrong == null || wrong.equals(rightAnswer) || used.contains(rndnum)) + if(wrong == null || wrong.equals(rightAnswer) || result.contains(wrong)) i--; else{ result.add(wrong); - used.add(rndnum); } } return result; From bb34eff8d1670d459e051d437481bc215e4a9714 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sun, 7 Apr 2024 23:05:26 +0200 Subject: [PATCH 58/66] Solving merge problems --- questionGenerator/src/main/java/Main.java | 27 ++++++++++++------- .../HistoricalData/HistoricalView.test.js | 4 +-- .../HistoricalData/HistoryRecordRetriever.js | 4 ++- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/questionGenerator/src/main/java/Main.java b/questionGenerator/src/main/java/Main.java index f90f830e..cb196b9e 100644 --- a/questionGenerator/src/main/java/Main.java +++ b/questionGenerator/src/main/java/Main.java @@ -10,26 +10,35 @@ public class Main { public static void main(String[] args) { - QuestionGenerator qg = new QuestionGenerator("en"); + QuestionGenerator qgEn = new QuestionGenerator("en"); - run(qg, QuestionType.CAPITAL, 3); + run(qgEn, QuestionType.CAPITAL, 3); System.out.println(); - run(qg, QuestionType.LANGUAGE, 3); + run(qgEn, QuestionType.LANGUAGE, 3); System.out.println(); - run(qg, QuestionType.POPULATION, 3); + run(qgEn, QuestionType.POPULATION, 3); System.out.println(); - run(qg, QuestionType.SIZE, 3); + run(qgEn, QuestionType.SIZE, 3); + + QuestionGenerator qgEs = new QuestionGenerator("es"); + + run(qgEs, QuestionType.CAPITAL, 3); + System.out.println(); + + run(qgEs, QuestionType.LANGUAGE, 3); + System.out.println(); + + run(qgEs, QuestionType.POPULATION, 3); + System.out.println(); + + run(qgEs, QuestionType.SIZE, 3); } private static void run(QuestionGenerator qg, QuestionType type, int numberOfQuestions){ List questions = qg.generateQuestions(type, numberOfQuestions); - for(int i=0; i q.getJSON().toString()).toList()); } } diff --git a/webapp/src/components/HistoricalData/HistoricalView.test.js b/webapp/src/components/HistoricalData/HistoricalView.test.js index 43cf59bb..e224a4ce 100644 --- a/webapp/src/components/HistoricalData/HistoricalView.test.js +++ b/webapp/src/components/HistoricalData/HistoricalView.test.js @@ -40,7 +40,7 @@ describe('Historical View component', () => { it('renders Game Record Buttons', async () => { const user = { username: 'dummy' }; mockAxios.onGet('http://localhost:8000/record/dummy').reply(200, - [{user: "dummy", + {record : {user: "dummy", games: [{ questions: [{ question: "What is the capital of Spain?", @@ -50,7 +50,7 @@ describe('Historical View component', () => { }], points: "200", date: "1712344268728" - }]}]); + }]}}); await act(async()=> await render() diff --git a/webapp/src/components/HistoricalData/HistoryRecordRetriever.js b/webapp/src/components/HistoricalData/HistoryRecordRetriever.js index 5b574310..d586a867 100644 --- a/webapp/src/components/HistoricalData/HistoryRecordRetriever.js +++ b/webapp/src/components/HistoricalData/HistoryRecordRetriever.js @@ -11,7 +11,9 @@ class HistoryRecordRetriever{ try { const response = await axios.get(this.apiUrl + '/' + user); const receivedRecords = await response.data; - return receivedRecords[0]; + console.log(receivedRecords) + console.log(receivedRecords[0]) + return receivedRecords.record; } catch (error) { console.log(error) throw new Error(error); From e7c3e8f88681967d175e05894b8c77bf909a3ced Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Sun, 7 Apr 2024 23:55:18 +0200 Subject: [PATCH 59/66] Setted up e2e tests but they dont pass --- package-lock.json | 641 +----------------- webapp/e2e/steps/home.steps.js | 6 +- webapp/e2e/steps/register-form.steps.js | 5 +- webapp/e2e/test-environment-setup.js | 285 +++++++- webapp/openapi.yaml | 313 +++++++++ webapp/package-lock.json | 27 +- webapp/package.json | 3 +- .../loginAndRegistration/AddUser.js | 3 + 8 files changed, 632 insertions(+), 651 deletions(-) create mode 100644 webapp/openapi.yaml diff --git a/package-lock.json b/package-lock.json index b72a95ac..8e7dbe69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "wiq_en1b", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -560,6 +560,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", + "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helper-plugin-utils": "^7.24.0", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/runtime": { "version": "7.23.9", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", @@ -2619,20 +2636,6 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -5911,613 +5914,5 @@ "url": "https://github.com/sponsors/sindresorhus" } } - }, - "dependencies": { - "@asciidoctor/core": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-3.0.4.tgz", - "integrity": "sha512-41SDMi7iRRBViPe0L6VWFTe55bv6HEOJeRqMj5+E5wB1YPdUPuTucL4UAESPZM6OWmn4t/5qM5LusXomFUVwVQ==", - "peer": true, - "requires": { - "@asciidoctor/opal-runtime": "3.0.1", - "unxhr": "1.2.0" - } - }, - "@asciidoctor/opal-runtime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@asciidoctor/opal-runtime/-/opal-runtime-3.0.1.tgz", - "integrity": "sha512-iW7ACahOG0zZft4A/4CqDcc7JX+fWRNjV5tFAVkNCzwZD+EnFolPaUOPYt8jzadc0+Bgd80cQTtRMQnaaV1kkg==", - "peer": true, - "requires": { - "glob": "8.1.0", - "unxhr": "1.2.0" - } - }, - "@babel/runtime": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", - "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", - "requires": { - "regenerator-runtime": "^0.14.0" - } - }, - "@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" - }, - "@material-ui/core": { - "version": "4.12.4", - "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz", - "integrity": "sha512-tr7xekNlM9LjA6pagJmL8QCgZXaubWUwkJnoYcMKd4gw/t4XiyvnTkjdGrUVicyB2BsdaAv1tvow45bPM4sSwQ==", - "requires": { - "@babel/runtime": "^7.4.4", - "@material-ui/styles": "^4.11.5", - "@material-ui/system": "^4.12.2", - "@material-ui/types": "5.1.0", - "@material-ui/utils": "^4.11.3", - "@types/react-transition-group": "^4.2.0", - "clsx": "^1.0.4", - "hoist-non-react-statics": "^3.3.2", - "popper.js": "1.16.1-lts", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0", - "react-transition-group": "^4.4.0" - } - }, - "@material-ui/icons": { - "version": "4.11.3", - "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.3.tgz", - "integrity": "sha512-IKHlyx6LDh8n19vzwH5RtHIOHl9Tu90aAAxcbWME6kp4dmvODM3UvOHJeMIDzUbd4muuJKHmlNoBN+mDY4XkBA==", - "requires": { - "@babel/runtime": "^7.4.4" - } - }, - "@material-ui/styles": { - "version": "4.11.5", - "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.5.tgz", - "integrity": "sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA==", - "requires": { - "@babel/runtime": "^7.4.4", - "@emotion/hash": "^0.8.0", - "@material-ui/types": "5.1.0", - "@material-ui/utils": "^4.11.3", - "clsx": "^1.0.4", - "csstype": "^2.5.2", - "hoist-non-react-statics": "^3.3.2", - "jss": "^10.5.1", - "jss-plugin-camel-case": "^10.5.1", - "jss-plugin-default-unit": "^10.5.1", - "jss-plugin-global": "^10.5.1", - "jss-plugin-nested": "^10.5.1", - "jss-plugin-props-sort": "^10.5.1", - "jss-plugin-rule-value-function": "^10.5.1", - "jss-plugin-vendor-prefixer": "^10.5.1", - "prop-types": "^15.7.2" - } - }, - "@material-ui/system": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz", - "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==", - "requires": { - "@babel/runtime": "^7.4.4", - "@material-ui/utils": "^4.11.3", - "csstype": "^2.5.2", - "prop-types": "^15.7.2" - } - }, - "@material-ui/types": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", - "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==", - "requires": {} - }, - "@material-ui/utils": { - "version": "4.11.3", - "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz", - "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==", - "requires": { - "@babel/runtime": "^7.4.4", - "prop-types": "^15.7.2", - "react-is": "^16.8.0 || ^17.0.0" - } - }, - "@messageformat/core": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@messageformat/core/-/core-3.3.0.tgz", - "integrity": "sha512-YcXd3remTDdeMxAlbvW6oV9d/01/DZ8DHUFwSttO3LMzIZj3iO0NRw+u1xlsNNORFI+u0EQzD52ZX3+Udi0T3g==", - "requires": { - "@messageformat/date-skeleton": "^1.0.0", - "@messageformat/number-skeleton": "^1.0.0", - "@messageformat/parser": "^5.1.0", - "@messageformat/runtime": "^3.0.1", - "make-plural": "^7.0.0", - "safe-identifier": "^0.4.1" - } - }, - "@messageformat/date-skeleton": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@messageformat/date-skeleton/-/date-skeleton-1.0.1.tgz", - "integrity": "sha512-jPXy8fg+WMPIgmGjxSlnGJn68h/2InfT0TNSkVx0IGXgp4ynnvYkbZ51dGWmGySEK+pBiYUttbQdu5XEqX5CRg==" - }, - "@messageformat/number-skeleton": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@messageformat/number-skeleton/-/number-skeleton-1.2.0.tgz", - "integrity": "sha512-xsgwcL7J7WhlHJ3RNbaVgssaIwcEyFkBqxHdcdaiJzwTZAWEOD8BuUFxnxV9k5S0qHN3v/KzUpq0IUpjH1seRg==" - }, - "@messageformat/parser": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@messageformat/parser/-/parser-5.1.0.tgz", - "integrity": "sha512-jKlkls3Gewgw6qMjKZ9SFfHUpdzEVdovKFtW1qRhJ3WI4FW5R/NnGDqr8SDGz+krWDO3ki94boMmQvGke1HwUQ==", - "requires": { - "moo": "^0.5.1" - } - }, - "@messageformat/runtime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@messageformat/runtime/-/runtime-3.0.1.tgz", - "integrity": "sha512-6RU5ol2lDtO8bD9Yxe6CZkl0DArdv0qkuoZC+ZwowU+cdRlVE1157wjCmlA5Rsf1Xc/brACnsZa5PZpEDfTFFg==", - "requires": { - "make-plural": "^7.0.0" - } - }, - "@remix-run/router": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz", - "integrity": "sha512-zcU0gM3z+3iqj8UX45AmWY810l3oUmXM7uH4dt5xtzvMhRtYVhKGOmgOd1877dOPPepfCjUv57w+syamWIYe7w==" - }, - "@types/prop-types": { - "version": "15.7.11", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", - "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" - }, - "@types/react": { - "version": "17.0.76", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.76.tgz", - "integrity": "sha512-w9Aq+qeszGYoQM0hgFcdsAODGJdogadBDiitPm+zjBFJ0mLymvn2qSXsDaLJUndFRqqXk1FQfa9avHUBk1JhJQ==", - "requires": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" - }, - "dependencies": { - "csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - } - } - }, - "@types/react-transition-group": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz", - "integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==", - "requires": { - "@types/react": "*" - } - }, - "@types/scheduler": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" - }, - "asciidoctor-emoji": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/asciidoctor-emoji/-/asciidoctor-emoji-0.5.0.tgz", - "integrity": "sha512-3lsYV2kdX1MseZAm1KgSPwny+P7Fr83ZPH4MxNISIZAz3cPEGaFgNxRbr/uha4Tyv+oarpoaY5cGI7Fe0HluZg==", - "requires": {} - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "peer": true - }, - "boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==" - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "peer": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" - }, - "css-vendor": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", - "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", - "requires": { - "@babel/runtime": "^7.8.3", - "is-in-browser": "^1.0.2" - } - }, - "csstype": { - "version": "2.6.21", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", - "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "requires": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - }, - "dependencies": { - "csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - } - } - }, - "fast-printf": { - "version": "1.6.9", - "resolved": "https://registry.npmjs.org/fast-printf/-/fast-printf-1.6.9.tgz", - "integrity": "sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==", - "requires": { - "boolean": "^3.1.4" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "peer": true - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "peer": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "requires": { - "react-is": "^16.7.0" - }, - "dependencies": { - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - } - } - }, - "hyphenate-style-name": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", - "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" - }, - "i18n": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.15.1.tgz", - "integrity": "sha512-yue187t8MqUPMHdKjiZGrX+L+xcUsDClGO0Cz4loaKUOK9WrGw5pgan4bv130utOwX7fHE9w2iUeHFalVQWkXA==", - "requires": { - "@messageformat/core": "^3.0.0", - "debug": "^4.3.3", - "fast-printf": "^1.6.9", - "make-plural": "^7.0.0", - "math-interval-parser": "^2.0.1", - "mustache": "^4.2.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "peer": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "peer": true - }, - "is-in-browser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", - "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "jss": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss/-/jss-10.10.0.tgz", - "integrity": "sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw==", - "requires": { - "@babel/runtime": "^7.3.1", - "csstype": "^3.0.2", - "is-in-browser": "^1.1.3", - "tiny-warning": "^1.0.2" - }, - "dependencies": { - "csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" - } - } - }, - "jss-plugin-camel-case": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz", - "integrity": "sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw==", - "requires": { - "@babel/runtime": "^7.3.1", - "hyphenate-style-name": "^1.0.3", - "jss": "10.10.0" - } - }, - "jss-plugin-default-unit": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz", - "integrity": "sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ==", - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.10.0" - } - }, - "jss-plugin-global": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz", - "integrity": "sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A==", - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.10.0" - } - }, - "jss-plugin-nested": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz", - "integrity": "sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA==", - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.10.0", - "tiny-warning": "^1.0.2" - } - }, - "jss-plugin-props-sort": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz", - "integrity": "sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg==", - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.10.0" - } - }, - "jss-plugin-rule-value-function": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz", - "integrity": "sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g==", - "requires": { - "@babel/runtime": "^7.3.1", - "jss": "10.10.0", - "tiny-warning": "^1.0.2" - } - }, - "jss-plugin-vendor-prefixer": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz", - "integrity": "sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg==", - "requires": { - "@babel/runtime": "^7.3.1", - "css-vendor": "^2.0.8", - "jss": "10.10.0" - } - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "make-plural": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-7.3.0.tgz", - "integrity": "sha512-/K3BC0KIsO+WK2i94LkMPv3wslMrazrQhfi5We9fMbLlLjzoOSJWr7TAdupLlDWaJcWxwoNosBkhFDejiu5VDw==" - }, - "math-interval-parser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-2.0.1.tgz", - "integrity": "sha512-VmlAmb0UJwlvMyx8iPhXUDnVW1F9IrGEd9CIOmv+XL8AErCUUuozoDMrgImvnYt2A+53qVX/tPW6YJurMKYsvA==" - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "peer": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "moo": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", - "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "peer": true, - "requires": { - "wrappy": "1" - } - }, - "popper.js": { - "version": "1.16.1-lts", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", - "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==" - }, - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - }, - "dependencies": { - "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - } - } - }, - "react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "react-countdown": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/react-countdown/-/react-countdown-2.3.5.tgz", - "integrity": "sha512-K26ENYEesMfPxhRRtm1r+Pf70SErrvW3g4CArLi/x6MPFjgfDFYePT4UghEj8p2nI0cqVV7/JjDgjyr//U60Og==", - "requires": { - "prop-types": "^15.7.2" - } - }, - "react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" - } - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "react-router": { - "version": "6.22.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.22.1.tgz", - "integrity": "sha512-0pdoRGwLtemnJqn1K0XHUbnKiX0S4X8CgvVVmHGOWmofESj31msHo/1YiqcJWK7Wxfq2a4uvvtS01KAQyWK/CQ==", - "requires": { - "@remix-run/router": "1.15.1" - } - }, - "react-router-dom": { - "version": "6.22.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.1.tgz", - "integrity": "sha512-iwMyyyrbL7zkKY7MRjOVRy+TMnS/OPusaFVxM2P11x9dzSzGmLsebkCvYirGq0DWB9K9hOspHYYtDz33gE5Duw==", - "requires": { - "@remix-run/router": "1.15.1", - "react-router": "6.22.1" - } - }, - "react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "requires": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - } - }, - "regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "safe-identifier": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", - "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==" - }, - "scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", - "peer": true, - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, - "tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" - }, - "unxhr": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.2.0.tgz", - "integrity": "sha512-6cGpm8NFXPD9QbSNx0cD2giy7teZ6xOkCUH3U89WKVkL9N9rBrWjlCwhR94Re18ZlAop4MOc3WU1M3Hv/bgpIw==", - "peer": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "peer": true - } } } diff --git a/webapp/e2e/steps/home.steps.js b/webapp/e2e/steps/home.steps.js index 21609f0f..c333de64 100644 --- a/webapp/e2e/steps/home.steps.js +++ b/webapp/e2e/steps/home.steps.js @@ -15,7 +15,7 @@ defineFeature(feature, test => { setDefaultOptions({ timeout: 10000 }); }); - test('Home page functionality', ({ given, when, then }) => { + test('Opening the text container', ({ given, when, then }) => { given('I am on the home page', async () => { await page.goto('http://localhost:3000/home'); await page.waitForSelector('.general'); @@ -28,14 +28,14 @@ defineFeature(feature, test => { then('The text container should be hidden', async () => { await expect(page).toMatchElement('.text-container.hidden'); }); - +/* when('I click on the toggle button to close', async () => { await page.click('#toggleClose'); }); then('The text container should be visible', async () => { await expect(page).toMatchElement('.text-container.visible'); - }); + });*/ }); afterAll(async () => { diff --git a/webapp/e2e/steps/register-form.steps.js b/webapp/e2e/steps/register-form.steps.js index 172e1969..c3bda5f1 100644 --- a/webapp/e2e/steps/register-form.steps.js +++ b/webapp/e2e/steps/register-form.steps.js @@ -17,7 +17,7 @@ defineFeature(feature, test => { setDefaultOptions({ timeout: 10000 }) await page - .goto("http://localhost:3000", { + .goto("http://localhost:3000/login", { waitUntil: "networkidle0", }) .catch(() => {}); @@ -31,12 +31,13 @@ defineFeature(feature, test => { given('An unregistered user', async () => { username = "pablo" password = "pabloasw" - await expect(page).toClick("button", { text: "Don't have an account? Register here." }); + await expect(page).toClick("a", { text: "Don't have an account? Register here." }); }); when('I fill the data in the form and press submit', async () => { await expect(page).toFill('input[name="username"]', username); await expect(page).toFill('input[name="password"]', password); + await expect(page).toFill('input[name="repeat_password"]', password); await expect(page).toClick('button', { text: 'Add User' }) }); diff --git a/webapp/e2e/test-environment-setup.js b/webapp/e2e/test-environment-setup.js index 7b7ed511..efd12b6e 100644 --- a/webapp/e2e/test-environment-setup.js +++ b/webapp/e2e/test-environment-setup.js @@ -1,7 +1,8 @@ const { MongoMemoryServer } = require('mongodb-memory-server'); - let mongoserver; +let recordservice; +let questionservice; let userservice; let authservice; let gatewayservice; @@ -9,11 +10,291 @@ let gatewayservice; async function startServer() { console.log('Starting MongoDB memory server...'); mongoserver = await MongoMemoryServer.create(); + + //Populate db + await loadQuestions(); + const mongoUri = mongoserver.getUri(); process.env.MONGODB_URI = mongoUri; + process.env.MONGODB_URI_QUESTIONS = mongoUri; + questionservice = await require("../../questionservice/question-service") + recordservice = await require("../../users/recordservice/record-service"); userservice = await require("../../users/userservice/user-service"); authservice = await require("../../users/authservice/auth-service"); gatewayservice = await require("../../gatewayservice/gateway-service"); } - startServer(); + +async function loadQuestions() { + const Question = require('../../questionservice/question-model'); + + const questions =[{ + "question": "What's the capital of Mexico?", + "answers": [ + "Mexico City", + "Singapore", + "Tokyo", + "Sofia" + ], + "language": "en", + "type": "CAPITAL" + }, + { + "question": "What's the capital of São Paulo?", + "answers": [ + "São Paulo", + "Nuuk", + "Astana", + "Chișinău" + ], + "language": "en", + "type": "CAPITAL" + }, + { + "question": "What's the capital of Quebec?", + "answers": [ + "Quebec City", + "Budapest", + "Vaduz", + "Tallinn" + ], + "language": "en", + "type": "CAPITAL" + }, + { + "question": "What's the official language of Paris?", + "answers": [ + "French", + "English", + "Spanish", + "Kazakh" + ], + "language": "en", + "type": "LANGUAGE" + }, + { + "question": "What's the official language of Japan?", + "answers": [ + "Japanese", + "Brazilian Sign Language", + "English", + "French" + ], + "language": "en", + "type": "LANGUAGE" + }, + { + "question": "What's the official language of Cairo?", + "answers": [ + "Arabic", + "Serbian", + "Slovak", + "French" + ], + "language": "en", + "type": "LANGUAGE" + }, + { + "question": "What's the population of Greenland?", + "answers": [ + "56421", + "33288", + "75604", + "28774" + ], + "language": "en", + "type": "POPULATION" + }, + { + "question": "What's the population of São Paulo?", + "answers": [ + "11451245", + "10077095", + "15688205", + "8588433" + ], + "language": "en", + "type": "POPULATION" + }, + { + "question": "What's the population of Zürich?", + "answers": [ + "427721", + "598809", + "329345", + "543205" + ], + "language": "en", + "type": "POPULATION" + }, + { + "question": "What's the size of Washington, D.C.?", + "answers": [ + "177", + "178", + "127", + "92" + ], + "language": "en", + "type": "SIZE" + }, + { + "question": "What's the size of Republic of Ireland?", + "answers": [ + "69797", + "58629", + "84454", + "46066" + ], + "language": "en", + "type": "SIZE" + }, + { + "question": "What's the size of Toronto?", + "answers": [ + "630.21", + "749.94995", + "743.6478", + "642.8142" + ], + "language": "en", + "type": "SIZE" + }, + { + "question": "¿Cuál es la capital de Islandia?", + "answers": [ + "Reikiavik", + "Sarajevo", + "Yakarta", + "Bucarest" + ], + "language": "es", + "type": "CAPITAL" + }, + { + "question": "¿Cuál es la capital de Región de Bruselas-Capital?", + "answers": [ + "Ciudad de Bruselas", + "Montevideo", + "Nairobi", + "Canegrate" + ], + "language": "es", + "type": "CAPITAL" + }, + { + "question": "¿Cuál es la capital de Suecia?", + "answers": [ + "Estocolmo", + "Bakú", + "Vilna", + "Tirana" + ], + "language": "es", + "type": "CAPITAL" + }, + { + "question": "¿Cuál es el idioma oficial de Irlanda del Norte?", + "answers": [ + "inglés", + "alemán", + "japonés", + "maltés" + ], + "language": "es", + "type": "LANGUAGE" + }, + { + "question": "¿Cuál es el idioma oficial de Australia?", + "answers": [ + "inglés australiano", + "portugués", + "sueco", + "árabe" + ], + "language": "es", + "type": "LANGUAGE" + }, + { + "question": "¿Cuál es el idioma oficial de Bulgaria?", + "answers": [ + "búlgaro", + "francés", + "moldavo", + "inglés" + ], + "language": "es", + "type": "LANGUAGE" + }, + { + "question": "¿Cuál es la población de Grecia?", + "answers": [ + "10566531", + "7079575", + "9721208", + "14264816" + ], + "language": "es", + "type": "POPULATION" + }, + { + "question": "¿Cuál es la población de Kenia?", + "answers": [ + "47564296", + "13176196", + "2236408", + "12700553" + ], + "language": "es", + "type": "POPULATION" + }, + { + "question": "¿Cuál es la población de Rumania?", + "answers": [ + "19053815", + "11241750", + "13147132", + "20197043" + ], + "language": "es", + "type": "POPULATION" + }, + { + "question": "¿Cuál es el área (km cuadrados) de Letonia?", + "answers": [ + "64593.79", + "51029.094", + "46507.53", + "49737.22" + ], + "language": "es", + "type": "SIZE" + }, + { + "question": "¿Cuál es el área (km cuadrados) de Estados Unidos?", + "answers": [ + "9826675", + "5896005", + "10318008", + "10514542" + ], + "language": "es", + "type": "SIZE" + }, + { + "question": "¿Cuál es el área (km cuadrados) de México?", + "answers": [ + "1972550", + "2426236", + "2189530", + "1617491" + ], + "language": "es", + "type": "SIZE" + }] + + //No need of loading questions for these tests + //await Question.bulkSave(questions); +} + +startServer(); diff --git a/webapp/openapi.yaml b/webapp/openapi.yaml new file mode 100644 index 00000000..98968bbf --- /dev/null +++ b/webapp/openapi.yaml @@ -0,0 +1,313 @@ +openapi: 3.0.0 +info: + title: wiq_en1b API + description: Our project's OpenAPI specification. + version: 0.1.2 + contact: + name: Project github + url: https://github.com/Arquisoft/wiq_en1b +servers: + - url: http://localhost:8000 + description: Development server + - url: http://SOMEIP:8000 + description: Production server +paths: + /adduser: + post: + summary: Add a new user to the database. + operationId: addUser + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: User ID. + example: student + password: + type: string + description: User password. + example: pass + responses: + '200': + description: User added successfully. + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: User ID + '400': + description: Failed to add user + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Username already in use + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error + /health: + get: + summary: Check the health status of the service. + operationId: checkHealth + responses: + '200': + description: Service is healthy. + content: + application/json: + schema: + type: object + properties: + status: + type: string + description: Health status. + example: OK + /login: + post: + summary: Log in to the system. + operationId: loginUser + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: User ID. + example: student + password: + type: string + description: User password. + example: pass + responses: + '200': + description: Login successful. Returns user token, and username. + content: + application/json: + schema: + type: object + properties: + token: + type: string + description: User token. + example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NWY3NTZkYjNmYTIyZDIyN2E0YjdjN2QiLCJpYXQiOjE3MTA3MDg3NDUsImV4cCI6MTcxMDcxMjM0NX0.VMG_5DOyQ4GYlJQRcu1I6ICG1IGzuo2Xuei093ONHxw + username: + type: string + description: Username. + example: student + '400': + description: Invalid credentials. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Shows the error info.. + example: Invalid credentials + '500': + description: Internal server error. + content: + application/json: + schema: + type: object + properties: + error: + type: string + description: Error information. + example: Internal Server Error + /questions: + get: + summary: Get 5 random questions from the system in any language + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/QuestionResponse' + /questions/{lang}: + get: + summary: Get 5 random questions from the system in the lang specified + parameters: + - name: lang + in: path + required: true + schema: + type: string + description: Language code for filtering questions must be es or en + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/QuestionResponse' + /record: + post: + summary: Add a new record to the database + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/Record' + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + user: + type: string + /record/{user}: + get: + summary: Gets the records from a given user + parameters: + - name: user + in: path + required: true + schema: + type: string + description: Username for filtering records + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/RecordResponse' +components: + schemas: + LoginRequest: + type: object + properties: + username: + type: string + password: + type: string + required: + - username + - password + LoginResponse: + type: object + properties: + token: + type: string + User: + type: object + properties: + username: + type: string + email: + type: string + required: + - username + - email + UserResponse: + type: object + properties: + message: + type: string + QuestionResponse: + type: array + items: + type: object + properties: + question: + type: string + answers: + type: array + items: + type: string + correct_answer: + type: string + Record: + type: object + properties: + user: + type: string + game: + type: object + properties: + questions: + type: array + items: + type: object + properties: + question: + type: string + example: What is the capital of Oviedo? + answers: + type: array + items: + type: string + answerGiven: + type: string + correctAnswer: + type: string + points: + type: number + date: + type: string + required: + - user + - game + RecordResponse: + type: object + properties: + user: + type: string + games: + type: array + items: + type: object + properties: + questions: + type: array + items: + type: object + properties: + question: + type: string + example: What is the capital of Oviedo? + answers: + type: array + items: + type: string + answerGiven: + type: string + correctAnswer: + type: string + points: + type: number + date: + type: string + Error: + type: object + properties: + error: + type: string \ No newline at end of file diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 92ac6303..076761a2 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -379,9 +379,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", + "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", "engines": { "node": ">=6.9.0" } @@ -1313,12 +1313,12 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz", - "integrity": "sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", + "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", "dependencies": { "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-plugin-utils": "^7.24.0", "@babel/helper-simple-access": "^7.22.5" }, "engines": { @@ -11671,19 +11671,6 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", diff --git a/webapp/package.json b/webapp/package.json index d4f91476..2ea16917 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -13,9 +13,9 @@ "bcrypt": "^5.1.1", "express": "^4.19.2", "i18n": "^0.15.1", + "jquery": "^3.7.1", "jsonwebtoken": "^9.0.2", "mongoose": "^8.3.0", - "jquery": "^3.7.1", "react": "^18.2.0", "react-countdown": "^2.3.5", "react-dom": "^18.2.0", @@ -64,6 +64,7 @@ }, "jest": { "testMatch": [ + "**/*.test.js", "**/*.feature", "**/*.steps.js" ] diff --git a/webapp/src/components/loginAndRegistration/AddUser.js b/webapp/src/components/loginAndRegistration/AddUser.js index b065f007..2324ecab 100644 --- a/webapp/src/components/loginAndRegistration/AddUser.js +++ b/webapp/src/components/loginAndRegistration/AddUser.js @@ -43,6 +43,7 @@ const AddUser = () => {

    {t("addUser.username_placeholder")}:

    {

    {t("addUser.password_placeholder")}:

    {

    {t("addUser.repeat_password_placeholder")}:

    Date: Mon, 8 Apr 2024 00:06:22 +0200 Subject: [PATCH 60/66] Update README.md Updated readme for new configurations --- README.md | 86 ++----------------------------------------------------- 1 file changed, 3 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index 1ac29d77..5575e13d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,6 @@ This is a base repo for the [Software Architecture course](http://arquisoft.github.io/) in [2023/2024 edition](https://arquisoft.github.io/course2324.html). -The project can be seing [here](http://4.231.170.30:3000) This repo is a basic application composed of several components. @@ -18,6 +17,7 @@ This repo is a basic application composed of several components. Both the user and auth service share a Mongo database that is accessed with mongoose. ## Quick start guide +In order to deployed it locally you can check out the docker configuration below: ### Using docker @@ -33,88 +33,8 @@ and launch it with docker compose: docker compose --profile dev up --build ``` -### Starting Component by component - -First, start the database. Either install and run Mongo or run it using docker: - -```docker run -d -p 27017:27017 --name=my-mongo mongo:latest``` - -You can also use services like Mongo Altas for running a Mongo database in the cloud. - -Now, launch the auth, user and gateway services. Just go to each directory and run `npm install` followed by `npm start`. - -Lastly, go to the webapp directory and launch this component with `npm install` followed by `npm start`. - -After all the components are launched, the app should be available in localhost in port 3000. - -## Deployment - -For the deployment, we have several options. - -The first and more flexible is to deploy to a virtual machine using SSH. This will work with any cloud service (or with our own server). - -Other options include using the container services that most cloud services provide. This means, deploying our Docker containers directly. - -We are going to use the first approach, creating a virtual machine in a cloud service and after installing docker and docker-compose, deploy our containers there using GitHub Actions and SSH. - -### Machine requirements for deployment - -The machine for deployment can be created in services like Microsoft Azure or Amazon AWS. These are in general the settings that it must have: - -- Linux machine with Ubuntu > 20.04. -- Docker and docker-compose installed. -- Open ports for the applications installed (in this case, ports 3000 for the webapp and 8000 for the gateway service). - -Once you have the virtual machine created, you can install **docker** and **docker-compose** using the following instructions: - -```ssh -sudo apt update -sudo apt install apt-transport-https ca-certificates curl software-properties-common -curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - -sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable" -sudo apt update -sudo apt install docker-ce -sudo usermod -aG docker ${USER} -sudo curl -L "https://github.com/docker/compose/releases/download/1.28.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose -sudo chmod +x /usr/local/bin/docker-compose -``` - -### Continuous delivery (GitHub Actions) - -Once we have our machine ready, we could deploy by hand the application, taking our docker-compose file and executing it in the remote machine. - -In this repository, this process is done automatically using **GitHub Actions**. The idea is to trigger a series of actions when some condition is met in the repository. - -As you can see, unitary tests of each module and e2e tests are executed before pushing the docker images and deploying them. Using this approach we avoid deploying versions that do not pass the tests. - -The deploy action is the following: - -```yml -deploy: - name: Deploy over SSH - runs-on: ubuntu-latest - needs: [docker-push-userservice,docker-push-authservice,docker-push-gatewayservice,docker-push-webapp] - steps: - - name: Deploy over SSH - uses: fifsky/ssh-action@master - with: - host: ${{ secrets.DEPLOY_HOST }} - user: ${{ secrets.DEPLOY_USER }} - key: ${{ secrets.DEPLOY_KEY }} - command: | - wget https://raw.githubusercontent.com/arquisoft/wiq_en1b/master/docker-compose.yml -O docker-compose.yml - wget https://raw.githubusercontent.com/arquisoft/wiq_en1b/master/.env - docker compose down - docker compose --profile prod up -d -``` - -This action uses three secrets that must be configured in the repository: -- DEPLOY_HOST: IP of the remote machine. -- DEPLOY_USER: user with permission to execute the commands in the remote machine. -- DEPLOY_KEY: key to authenticate the user in the remote machine. - -Note that this action logs in the remote machine and downloads the docker-compose file from the repository and launches it. Obviously, previous actions have been executed which have uploaded the docker images to the GitHub Packages repository. - +### Deployed in Cloud +In order to view the application deploy in the cloud click [here](http://172.203.216.60:3000) ### Members - Lucía Ruiz Núñez uo289267@uniovi.es From e1d5b64180571cc6f2e3173fd3b44040f90dd09d Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Mon, 8 Apr 2024 00:21:01 +0200 Subject: [PATCH 61/66] Modified realse.yml to include tests --- .github/workflows/release.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 26d1dd2c..202b2c05 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,6 +5,30 @@ on: types: [published] jobs: + unit-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - run: npm --perfix questionservice ci + - run: npm --prefix users/recordservice ci + - run: npm --prefix users/authservice ci + - run: npm --prefix users/userservice ci + - run: npm --prefix gatewayservice ci + - run: npm --prefix webapp ci + - run: npm --perfix questionservice test -- --coverage + - run: npm --prefix users/recordservice test -- --coverage + - run: npm --prefix users/authservice test -- --coverage + - run: npm --prefix users/userservice test -- --coverage + - run: npm --prefix gatewayservice test -- --coverage + - run: npm --prefix webapp test -- --coverage + - name: Analyze with SonarCloud + uses: sonarsource/sonarcloud-github-action@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} docker-push-webapp: name: Push webapp Docker Image to GitHub Packages runs-on: ubuntu-latest From 23c80ee30ab5229cc76057b6553175eb0f607c85 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Mon, 8 Apr 2024 00:23:49 +0200 Subject: [PATCH 62/66] Added needs: [unit-tests] to some jobs --- .github/workflows/release.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 202b2c05..439bfc00 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,6 +32,7 @@ jobs: docker-push-webapp: name: Push webapp Docker Image to GitHub Packages runs-on: ubuntu-latest + needs: [unit-tests] permissions: contents: read packages: write @@ -51,6 +52,7 @@ jobs: docker-push-authservice: name: Push auth service Docker Image to GitHub Packages runs-on: ubuntu-latest + needs: [unit-tests] permissions: contents: read packages: write @@ -67,6 +69,7 @@ jobs: docker-push-userservice: name: Push user service Docker Image to GitHub Packages runs-on: ubuntu-latest + needs: [unit-tests] permissions: contents: read packages: write @@ -83,6 +86,7 @@ jobs: docker-push-recordservice: name: Push record service Docker Image to GitHub Packages runs-on: ubuntu-latest + needs: [unit-tests] permissions: contents: read packages: write @@ -99,6 +103,7 @@ jobs: docker-push-gatewayservice: name: Push gateway service Docker Image to GitHub Packages runs-on: ubuntu-latest + needs: [unit-tests] permissions: contents: read packages: write @@ -115,6 +120,7 @@ jobs: docker-push-questionservice: name: Push question service Docker Image to GitHub Packages runs-on: ubuntu-latest + needs: [unit-tests] permissions: contents: read packages: write @@ -131,6 +137,7 @@ jobs: docker-push-questiongenerator: name: Push question generator Docker Image to GitHub Packages runs-on: ubuntu-latest + needs: [unit-tests] permissions: contents: read packages: write From 51a7c281bf210f0148e3f727bdd9aa047aa293c6 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Mon, 8 Apr 2024 00:27:28 +0200 Subject: [PATCH 63/66] Small typo had perfix should be prefix --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 439bfc00..604c124e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,13 +12,13 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 20 - - run: npm --perfix questionservice ci + - run: npm --prefix questionservice ci - run: npm --prefix users/recordservice ci - run: npm --prefix users/authservice ci - run: npm --prefix users/userservice ci - run: npm --prefix gatewayservice ci - run: npm --prefix webapp ci - - run: npm --perfix questionservice test -- --coverage + - run: npm --prefix questionservice test -- --coverage - run: npm --prefix users/recordservice test -- --coverage - run: npm --prefix users/authservice test -- --coverage - run: npm --prefix users/userservice test -- --coverage From a97af7873504430a31761f304d72b5a45d99c9b9 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Mon, 8 Apr 2024 00:34:08 +0200 Subject: [PATCH 64/66] Deleting unnecessary mock --- .../questionView/mocks/QuestionGenerator.js | 20 ------------------- 1 file changed, 20 deletions(-) delete mode 100644 webapp/src/components/questionView/mocks/QuestionGenerator.js diff --git a/webapp/src/components/questionView/mocks/QuestionGenerator.js b/webapp/src/components/questionView/mocks/QuestionGenerator.js deleted file mode 100644 index 4dec7679..00000000 --- a/webapp/src/components/questionView/mocks/QuestionGenerator.js +++ /dev/null @@ -1,20 +0,0 @@ -export default class QuestionGenerator { - async generateQuestions() { - return [ - { - getQuestion: () => 'Mocked Question 1', - getAnswers: () => ['Mocked Answer 1', 'Mocked Answer 2','Mocked Answer 3', 'Mocked Answer 4'], - getCorrectAnswer: () => 'Mocked Answer 1' - }, - { - getQuestion: () => 'Mocked Question 2', - getAnswers: () => ['Mocked Answer 1', 'Mocked Answer 2','Mocked Answer 3', 'Mocked Answer 4'], - getCorrectAnswer: () => 'Mocked Answer 4' - },{ - getQuestion: () => 'Mocked Question 3', - getAnswers: () => ['Mocked Answer 1', 'Mocked Answer 2','Mocked Answer 3', 'Mocked Answer 4'], - getCorrectAnswer: () => 'Mocked Answer 2' - } - ]; - } - } \ No newline at end of file From 18cc5ee4c9e446d84b8fd738557afee94b7799fb Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Mon, 8 Apr 2024 00:35:19 +0200 Subject: [PATCH 65/66] Updated build.yml for pushes to master --- .github/workflows/build.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c9265703..d60d0f89 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,15 +10,17 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - with: - fetch-depth: 0 - uses: actions/setup-node@v4 with: node-version: 20 + - run: npm --prefix questionservice ci + - run: npm --prefix users/recordservice ci - run: npm --prefix users/authservice ci - run: npm --prefix users/userservice ci - run: npm --prefix gatewayservice ci - run: npm --prefix webapp ci + - run: npm --prefix questionservice test -- --coverage + - run: npm --prefix users/recordservice test -- --coverage - run: npm --prefix users/authservice test -- --coverage - run: npm --prefix users/userservice test -- --coverage - run: npm --prefix gatewayservice test -- --coverage @@ -26,5 +28,5 @@ jobs: - name: Analyze with SonarCloud uses: sonarsource/sonarcloud-github-action@master env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file From 360f401dd0d9fc2468996eab11bfe358a4a7d098 Mon Sep 17 00:00:00 2001 From: Mister-Mario Date: Mon, 8 Apr 2024 00:39:14 +0200 Subject: [PATCH 66/66] Modified SOMEIP in the openapi.yaml --- gatewayservice/openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gatewayservice/openapi.yaml b/gatewayservice/openapi.yaml index 98968bbf..7129380e 100644 --- a/gatewayservice/openapi.yaml +++ b/gatewayservice/openapi.yaml @@ -9,7 +9,7 @@ info: servers: - url: http://localhost:8000 description: Development server - - url: http://SOMEIP:8000 + - url: http://172.203.216.60:8000 description: Production server paths: /adduser: