From 23c58459af57218824e8ed80044197626598a484 Mon Sep 17 00:00:00 2001 From: Damien Broqua Date: Fri, 8 Apr 2022 15:03:01 +0200 Subject: [PATCH] Version 1.0 (#26) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issues : * [x] Pouvoir partager sa collection #1 * [x] Exporter sa collection #2 * [x] Pouvoir visualiser le détail d'un album #3 * [x] Pouvoir visualiser les médias d'un album #5 * [x] Avoir un titre distinct par page #29 * [x] Avoir des statistiques avec Matomo #30 * [x] Avoir un logo pour les pages d'erreurs #32 Co-authored-by: dbroqua Reviewed-on: https://git.darkou.fr/dbroqua/MusicTopus/pulls/26 --- README.md | 8 +- docker-compose.yml.dev | 3 + docker-compose.yml.prod | 3 + package.json | 13 +- public/500.html | 39 +- public/font/icon.eot | Bin 9752 -> 9976 bytes public/font/icon.svg | 2 + public/font/icon.ttf | Bin 9600 -> 9824 bytes public/font/icon.woff | Bin 6060 -> 6224 bytes public/font/icon.woff2 | Bin 5052 -> 5208 bytes public/img/404.svg | 344 +++++++++++++++++- public/img/logo.svg | 1 - public/js/main.js | 7 +- public/mstile-310x150.png | Bin 7242 -> 0 bytes sass/500.scss | 22 ++ sass/button.scss | 2 +- sass/{ma-collection.scss => collection.scss} | 7 +- sass/colors.scss | 27 +- sass/composants.scss | 13 + sass/global.scss | 4 + sass/icons.scss | 3 +- sass/index.scss | 6 +- sass/list.scss | 29 +- sass/ma-collection-details.scss | 1 + sass/toast.scss | 5 + src/app.js | 9 +- src/config/index.js | 3 + src/libs/error.js | 4 +- src/middleware/Albums.js | 71 +++- src/middleware/Me.js | 45 +++ src/middleware/Pages.js | 4 + src/models/users.js | 16 +- src/routes/api/v1/albums.js | 4 +- src/routes/api/v1/me.js | 24 ++ src/routes/collection.js | 22 ++ src/routes/index.js | 12 + src/routes/ma-collection.js | 4 +- views/error.ejs | 2 + views/index.ejs | 20 +- views/pages/ajouter-un-album.ejs | 2 +- .../ma-collection.ejs => collection.ejs} | 57 +-- views/pages/composants.ejs | 173 ++++++++- .../mon-compte/ma-collection/exporter.ejs | 4 +- .../pages/mon-compte/ma-collection/index.ejs | 279 ++++++++++++++ 44 files changed, 1161 insertions(+), 133 deletions(-) delete mode 100644 public/img/logo.svg delete mode 100644 public/mstile-310x150.png create mode 100644 sass/500.scss rename sass/{ma-collection.scss => collection.scss} (90%) create mode 100644 sass/composants.scss create mode 100644 src/middleware/Me.js create mode 100644 src/routes/api/v1/me.js create mode 100644 src/routes/collection.js rename views/pages/{mon-compte/ma-collection.ejs => collection.ejs} (78%) create mode 100644 views/pages/mon-compte/ma-collection/index.ejs diff --git a/README.md b/README.md index fdc754d..1da497b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Le code source est publié sous licence libre [GNU GPL-3.0-or-later](LICENSE) et Vous pouvez librement utiliser le service en vous inscrivant sur [https://www.musictopus.fr/](https://www.musictopus.fr/). -Une fois inscrit vous pourrez saisir vos CDs et Vinyles sur votre espace personnel le tout gratuitement, sans tracker et sans utilisation de vos données personnelles ! +Une fois inscrit vous pourrez saisir vos CDs et Vinyles sur votre espace personnel le tout gratuitement, sans tracker (en dehors de statistiques web via [Matomo](https://fr.matomo.org/)) et sans utilisation de vos données personnelles ! ## Auto hébergement @@ -195,9 +195,13 @@ MONGODB_URI # Url du serveur mongo (par défaut mongodb://musictopus-db/musictop SECRET # Hash utilisé pour pour sauvegardé les dessions (par défaut waemaeMe5ahc6ce1chaeKohKa6Io8Eik) DISCOGS_TOKEN # Token Discogs (vous devez créer un compte sur discogs afin d'en obtenir un gratuitement) FORMSPREE_ID # Id du formulaire formspree pour la page "nous-contacter" +MATOMO_URL # Url vers l'instance matomo (exemple: https://analytics.darkou.fr/) +MATOMO_ID # Id du site sur votre instance matomo (exemple: 1) +SITE_NAME # Nom du site (utilisé dans le titre des pages) ``` ## Contributeurs - Damien Broqua (développeur principal du projet) -- Brunus (Logo et fournisseur d'idées :wink: ) \ No newline at end of file +- Brunus (Logo et fournisseur d'idées :wink: ) + diff --git a/docker-compose.yml.dev b/docker-compose.yml.dev index b14864f..9391624 100644 --- a/docker-compose.yml.dev +++ b/docker-compose.yml.dev @@ -25,6 +25,9 @@ services: SECRET: ${SECRET} DISCOGS_TOKEN: ${DISCOGS_TOKEN} FORMSPREE_ID: ${FORMSPREE_ID} + MATOMO_URL: ${MATOMO_URL} + MATOMO_ID: ${MATOMO_ID} + SITE_NAME: ${SITE_NAME} networks: - musictopus musictopus-db: diff --git a/docker-compose.yml.prod b/docker-compose.yml.prod index d314748..9077877 100644 --- a/docker-compose.yml.prod +++ b/docker-compose.yml.prod @@ -25,6 +25,9 @@ services: SECRET: ${SECRET} DISCOGS_TOKEN: ${DISCOGS_TOKEN} FORMSPREE_ID: ${FORMSPREE_ID} + MATOMO_URL: ${MATOMO_URL} + MATOMO_ID: ${MATOMO_ID} + SITE_NAME: ${SITE_NAME} networks: - musictopus musictopus-db: diff --git a/package.json b/package.json index 8c53d5a..b5aea27 100644 --- a/package.json +++ b/package.json @@ -27,9 +27,6 @@ }, "license": "GPL-3.0-or-later", "devDependencies": { - "@babel/cli": "^7.17.0", - "@babel/core": "^7.17.2", - "@babel/preset-env": "^7.16.11", "eslint": "^8.9.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-config-prettier": "^8.3.0", @@ -38,11 +35,12 @@ "husky": "^7.0.4", "lint-staged": "^12.3.3", "nodemon": "^2.0.15", - "npm-run-all": "^4.1.5", - "prettier": "^2.5.1", - "rimraf": "^3.0.2" + "prettier": "^2.5.1" }, "dependencies": { + "@babel/cli": "^7.17.0", + "@babel/core": "^7.17.2", + "@babel/preset-env": "^7.16.11", "axios": "^0.26.0", "connect-ensure-login": "^0.1.1", "connect-flash": "^0.1.1", @@ -54,14 +52,17 @@ "excel4node": "^1.7.2", "express": "^4.17.2", "express-session": "^1.17.2", + "joi": "^17.6.0", "knacss": "^8.0.4", "moment": "^2.29.1", "moment-timezone": "^0.5.34", "mongoose": "^6.2.1", "mongoose-unique-validator": "^3.0.0", + "npm-run-all": "^4.1.5", "passport": "^0.5.2", "passport-http": "^0.3.0", "passport-local": "^1.0.0", + "rimraf": "^3.0.2", "sass": "^1.49.7", "vue": "^3.2.31" }, diff --git a/public/500.html b/public/500.html index 072dfd0..76eb123 100644 --- a/public/500.html +++ b/public/500.html @@ -4,7 +4,7 @@ - Site en maintenance + MusicTopus - Erreur applicative @@ -17,37 +17,10 @@ - - - -
-
-

Site inaccessible

- -

- Pas de panique on revient très vite ! -

-
- - + + Image représentant la mascotte tenant un vinyle cassé + Nous sommes désolé mais quelque chose a mal tourné de notre côté. +
+ On devrait revenir très vite ! 😅 diff --git a/public/font/icon.eot b/public/font/icon.eot index 5a5d395769630de6dfb612635456a30fcfc3b97b..a17c0f6c12920aacff321df497143f171c000437 100644 GIT binary patch delta 707 zcmYL{T}YEr7{~wTocAMjZqrw`0`p_KNn|nn*pSK$!kRAVrl1AotIoZQE#Fi`3$&nh zv5U~&5O0hwq@r$&rAP#Q(2X~B(_K*pUPuVJL9njY<4iga&v~Bz?>y(>9L|{!=g%p5 zAJFHURRU6axv(+Yb#wYQz|Mo{KvFl;-#@=6y#(-E1LI?L#A&#n(qtbpW6A!be{PUo zC25Q4qb6}D=|>dz#S)W47a}z=K=K0)zY*03YiF+f0<=C_4;Tbgzvw4DPrA`aj!kq< zT`X)7cunAJVt7EWe|#_vR7s?LNqxd(?e-B*=ykvl>ZlO>hf+9)%C&fN{6Qg~eqBVlddc_;$3hJw5esIp5uoVlx{wuGra^iXYI*=uY zgJOQysS9!oyN-&?OX*$NG#$9`LPUfOUYzbaRjYAXG?sFX62`a)LlRO7LKZ2=kW&f+ zM+%(r6c`(4sHr}%ztUM=CQI-#ud28XvldsC;_(IBf=x<;$JZ8UZE**E?QNZ`hAB;+ zCe>A?x&!=4k6}EBvktb_+TCjyz1^*A%$OVE@z5E{h%$HlemovhZG(PF{DU^N$KZ*X z1f$eWFmv7chF5PCmeW@q$A7~iHg~T7EmZz&FIr(O$SSQn+6i$9u-x>dueY fd8W!tPW!^C;G@gKnPzRfBJ!xAk3=&e_b2;bQOd8o delta 485 zcmez2JHv-fLXCl;L3JXV8H>&$ak+^O)%8sb42%H`3=9d$xrqgTxMt@7`5PD*n6i?~ zN)&+NKp=JkNbsc50V!Kyd*e{{WEYNYANEbI#^H&cMJT1C%ex zNKH(U?`a%)(Tr7--!SIK&thN%$}%uaVPFQcbbvG$(37(mSQs*Z;(QDo3``7cFF0RV ze(3wy_VLH3x&Qw&FuY&@^IKtjuo)175vWH243!v^CLdx_1{%yZ`6JVxNzCm0JYY2! zpvna%|6yJ&{)2(xBM>w2GcbIb3&Egp+kArMAopfh!QD(Ua^j10;`wd9GVn9M0BODF yKJOfio-89`&L}uJM8tOTR1po%9(F6RKLj_Q61mL;lvpONH2IWx)MhP-b9?|QAb+R; diff --git a/public/font/icon.svg b/public/font/icon.svg index 51f7015..d5ac2f6 100644 --- a/public/font/icon.svg +++ b/public/font/icon.svg @@ -34,6 +34,8 @@ + + diff --git a/public/font/icon.ttf b/public/font/icon.ttf index 488fa0b950dfb203d41f048e34aa311fcb6ee045..4ccfa6dc9101474be2e0317776cd1611e5a2667a 100644 GIT binary patch delta 716 zcmYL{OH30{6o&tM?>s0iEwp5+N##*!(TJwu(FPx=i9vZRG*P29Q3fcTG_6d45O6_p zQ5RhpbPREWaY5AR22vz0OpL}2D>rV8Mp?KZhD1wZQr*gT_bDyTQ8S(zI{f=4>6auOaecxhUQPND z)rxp>X7pmTE)GZ`z!frL`bho!wI6_Ikmg~7fEp4*q#uxOHd2$*-Lsd9TLfMaIGY?B z)*B!1%L26$>0nBqHd&{0nRF}Zh8ub+W=(G&B0WGGTr|ffCPUE^3xGx*$eH6Yb9U|M z8W4DQw{VrsSQpq>dI^k%z(a^~*GjdL&bR~#=aCFKjOsi$qW+ zng68hv%4^Q&R>pZl!7e5$w`6?1u80FqxaaYBit_6&``0?^FP)gx49f;i_iazYOJVu z-naqeDdD18*h%uo_To;WCg+ph*wb{B;);k02Ld>K@>IQt%c8lGbJ!T;VgQnmG7z%J z&?e-JQrb}lobe18n_{T*?cL+9uCmJ#0xX~^+CkQ))hhmAq$ARzH2H%a;r2FfB-q)} z&FYxa;%`y4TGbooPx=hweu8ze_4b~A!|3m6UuVX`C{OgBp^hl?ChjE?y{cm*L``VK zq4pU(IiF`0U%~@$;nSnl!}qP#lRqJ08)^fSW&=e!nXm)4*~KO z@)C1XCs%yZ1@cRP4xC$%UtF@^vh*;}0U|*8)dfYV1$Eo3w*j?2nfN1`v1)P%V}ATB z21cMH1H%*sW-v4BBAs}Co39M~%r8J%@43%A2csvq2%9qsPTnJIJNd7$24@eu71-^9 Yn~g+nGXW*|#FZu+iAQaoBz}$$0B4qXHvj+t diff --git a/public/font/icon.woff b/public/font/icon.woff index 7c3262dd2702cebd300972a85c85e47075a2dd86..32621989e6e774018e5a3e688d923ab43ac1a6f8 100644 GIT binary patch delta 3673 zcmXY!byU;e8^=d?jnT+xq&8ZRl#mc4l#tF5!U*Y_$Y`m}F_Bi7N=QmbN=Zn3kw#LQ zfjCfFe)F8)J?C}q=f3XyIiKhLb~|;Oz++WkN}8-(+t4$Zx(gV25BPV-27Yu z005F%qUiwuNS~%IPj0KN}mvG{b*&2vz{(q1tGS1H5adCu*3&keAbH&!i@p0#5ijccK^=MKWD#T-7&3ZNR_)Rj{yBJfe(CqYd0*t5Sl}V-7o9JCtg~z0tSIx5obc-vr@31ruQY5$+mhvQ^5C@<;A*270IR962E^X-7KF6zkl&?@RMghFEmn(q@FF*ef{=tZcvy@~mXgO1Yh*ZI3+pWcF5YY?OFp71?Z!s{j0(qL<3tm+l^u zmGxjT(0+?iwLAw6N+ty(s7rYUBFkC_Arwc7n5qMIeYuXu=dUtc|MCm)xSUdjZ7U?=IY_m(GEVxOCjks zfo^TekKIhu0Q6~*;OR%WIx5*HvJ%9{o<-GX})Y!ed`uDuZ3Nhe!q1H zKH-Ft2;$fgDznf}2m6(fJo~II#C4vM9npXSD&KL(4+cZ$r4XMvUrFxs0}bL^GNvp? zOfpzw>;qPDGzuVK;N=MytVE-LX?>o5l=U|Ygnqc8+d=>hsnhN-Lq20-d0GfPtvfST zPrTGa94@eyB!(z9eBykh7^|@z7MR1qZPqXRcO%5tPhCcA>TFNK;bAo+k4waXvvR8d z&jle;hp$dH2a)L!((D?Zd2DT!a=ihTemxJEb?+-wo+mzJFLvb3`1=C1Zj@%V3!C62~Ct(k?B7MWpA2RrA}x}HTB zV&b#~4P}=r8&cYB^A!Uqv)RYkfx}_ZBI!@4mA6K%qPE%$s|W41_Kf@XbG|-3N%s60 z)@!G+i%?nf>q`t9MIS#hMtA4zvVSV|ianK5L`6$P2)DpYcHcL)G&W{8CNwUz&q$5s z&-lwhPm2FTiRN~cdXE0!`qNE^J4v3AU-RzM3p8o6>np{ML(2~&p`ncoO=TGk>KNO4 zO6((p4B>@M)LU#6r)D0Od3k_Lz`}|4A`9h=cPJ-9jr5S#f>z!`~ zd3s{MPxzmoM;jHd;)|d%oqR$XKmo1^yWI(Kj2DHR01S)d<*$v1rbpv@tAu|bjq(wK zVgq$OG=%$k?TOO$pQ){0J*)PK3-8vQH`a#Ot&pBE#dCA8@F{!^<{KF+J*pFEemIlW zrMzi(r%tA#aYR2$O7Lhw>58OO6SI80+b-|;ZJ}VI{ZKXL-q{i1%f?vK_Bp#5KjRSl zjd{}#{y*n0)YMx$D`Kt&d)}JrfHhPR-`+&EN0u*K!1)h*`_fFw*ZME@B6pCr_@7PN z6w@a3t{D1&OFs_Mq{q@}gduj!E5?4HQomJ=9>*|P8;vvB5om9_H?xXjpT;Si#}o87 zmp2mS^3Q(> zqZ^AQG~8Hl4Y+qI-v#yoo12@Y}-23MNa@L_hTl5Y8@_G!1^Z0>#}@o$N( z-C$0qhUfBi$%{M^v;&0}NFkix`CZFi2V1L5DXK4iOy=G4evc`8t>b0Dj zyD{alYNa?1-!`sN8*e)EWaCAeI$)RT%0)3IjY^5-Y>~wl9_I}7C`19`9>Oj%KV~Sh z=2N)Q2P^)o`~OkEKlUE>2ENtprHgoODgeeca^T(OuS2~J+yigZ2x6W1>W%YZZtALy z*O3>&Cl94;9okK3n|*GhQ|;cVPg&xoraBQb3l1%<#UH%)#-m!n8s~@WSAOP3Gwf|X zrVWK(fQt_@!BM_{Nf3iTjclpuhwrXVOqXvhPWhikDTUc{a&yf-+D+Ci7H8hxS5=Uc z{bQ6FK}B_og^DJKiR%oi_kDxT66fw1`@i*HiXqY2M<{%#BYkdDjO=jiaAFEJ z82z#A`#il!WxdcGNKrW}fUT^H63_bPua0QXhY|N+u_4;q`C|#vI%}4VpGx2`Pl)>R-}y3iAD`>%A6Wzu#&dPhhT@v%+o1^?jt@d|qV6Vp z1{qsB4a@4WdXC=guw%_%esw7BIZAD}jH&HdH$OQyOch4llcqJG&rLSOPu}o5`Tgyd zl2XI;!aM|4p>orm4$ge{CHq8#?;L4$mb8W1+kpO(EXew=uH&kJ{X)s8;;V7N22-dn z@9m4AgZLkA%c>38Ieed#Z9T{>yg4I6OY3_G;uEqFoBFLx#?#kp+x-cHf_t%tJa1dK zAnAS=2dj< zU%h-=TrT6Xd}lE($%;y>zbTy_zBImInW|43cmdsQ#9*L2P2RVYb5po-p_iE&?#zAW z5O+jxDBWq!H?>tAtkhP6G(x_Sc%vW-go7bti{20)*B0>xg8yH0p+V~w@**FjSP{D? zf7UU`d7lm!#flWL#5}c{UnVAVe&%`txAR-hD6Ojb*cxFH8Yb%9HRmV6`K(5^jD@G; z9@98<&T6tmPcFFcoRY6w>W;U*IfuQsGOqmhySI7Drl;y&o!222?St|XGG<3bk z0Ct+@w%A>{@ljGZv%ztIiuRQ22hQBZ^o#k+d5RI*V$El`nkh-S4y^*TP5hCZYd`$U zuX=%`&agLgzWz#d9R~5|g{5X$;kSGqZUDY?&9%5CTNins5r1HvKQk`KwML3 zI+SW!;TGBM^jD-Or!3*)M8KF9QOpN}=RxN|k#0G-^KTnJk(aM7;*Z2|hhW`lOT;&;wLj48*m8s}upOu;T`OcU0oEYGYpt80to&aPI- zF3}zY(`LP7H~}lKZwCs z>-pHQBnaR$8D?_%x;tIB3gdP39889?O6y8!{h{oge`X$C0};U4+r@+EZ~#EDNmO+9633w~c7DWO>Qv%3 z)&F5~aSw4Ox*PzY871cYHQea?9y{4N0syN!F(XSvj`vxl{9~d70FV_&6ud+blv1R2 zk3IZ@iNTM=TABz_N$_&R-OGU(WZnOl`3I*J&xD6vF!5k0j9A0}0lCib+SAU%iRf+; z9}`HtXnscUuDG|CpFaSwy(VTNh*Whb1ay1*IuU!>rHFMXkYNPTh1h50LKMLs`s=}Y zn`v$IU21e%Hab+%(@7EK7I3b5s^_MrIvYJO359DPwvUH&=pqdzM_eA|;TdyCnr_BZ zRB}PB%>t@^*I6t)?KTSO&ZDjgkW-di&6}z_y@^iSTg?S4N0eGn2Z{y4*zuJCaasNK z>tKIE6TxFOplH#i>I{Wk3s>zXe`_Bphava;Mk4PT$`TK)?k6aykJb!rmYgug$gqL2<^9dUmG+jlmb|_EEtEz?>f*3P>MFtj zyNQ@h0th~?sB%A23Mh#%X~oWuBbB+>`A2B%G>YfU@jK>ka{Bl)hoK1;VuaWv z*O&&54D$6axqp`+4gYys8hz9nRg8d^?Ua5$t;e*@rkI6&33X8{3NEPHSKLdL!lXy@ z2(ajsaR71OqfL~#1^2J>EqqIbQkiosU#HgS0lDn^QMEl{vL=H_4q2oaeT>N0^>ep@ zXKtrWpR-1=k?T?7fBNHhfA8>uQK}(}rqd_={eOAp4{N;8&$u#5c1~w%`ZI)WY;b+l zMFRr^r{j9nXp!Pb$BhF;V2+%^KmMK;JGC&`&2jCoDpH!jm_b*>GfN)<*5^ol(S;E> zNY_9X;o?fkoKoV7(XMd9XX$o?T(s>SMLm94=Ho#a!yng;`=57~WM?zf#JjE+c3w#BQ(ty_;RvHp*;V|3uGNlfX~f)7P^KI`+kLkId6pc~mX3U(J?IH5bY`xL%r6zbQ`RTiw`9IsxKM$lRC zrD7!8+BF;}ms8_k@RZTFZmLpJ&lDn*M92Bl$Z&nA%d9*{fA;@g`l~5Tw?z$6>boih z;m{9+@eCtkHU+Nny-6roLQ+V8Tf(MPikc!&B@E8K@sss(D;^Qh8Dc{5Vf(UO(J8D< zNL+Np@%{rdPHefG{=(NWX%5nt3_b#{M41$|cyeBZ0h{x5Cl8boDz5hiH^>MzuX&Gt zWJX%bnBA>W-pQm(=9~E~{BXYTu8CeC54>k`z5ze!a7Cn6c}Hl;a;+ZC*I*tE2AmcEtcS!h^j;aYUb zZG9Uhz=+g|;-QBNb~5#XFfs&b(o^_@cejO^x8#ARJz6dWu-S^ws zQ~30YnguSME_fc8VsNz#ijRgp;#P=gAkT|c58Qo_N`3o14o{s9F8HDwzuVOr4Y*(L z$}AOo@{sR^Oq$&H)M02$(pj8={%2`sxxu@Tl)^8p2o1K@cIlX>VvUfuQkBi(J*i^$ zw3Bk@kfXxSUMGJq6gpP7Hou;4D~0PFH|%OJ4mYoyu-$`Ge`e!RH1t^67(Z3M^|r3e zue+k#W#}U?l)wJ{9DLgL>er=#$bL_6qG5FUr!LLV)#7^lt+y-WKlSMB$0^<&1hPa9 zG-YXOI#u1#XLqJ*74sJ!*Au0@ae%1xvUXzz3Uepzu=)B=;J>;&6)hcf>ZabO<^-Mr#+ zLp~do%&nq@?I&ApXu*)sI5X?&Scx%pB03G`rVIuN0y1gu#5M&zCj<(9A+h($!aQ9lz1wlkwSXyH4!5`2=!VgurrH`Xi>4{w|sDh@d+S zrnLyAkT>zQf#60Ty5ZJha>4j`f#AYT8@K!(J&Cl=FihUk;nklNTv)@bFBOGjf9^Nl zeju1qUPniANXC`BQFJTF@Wq>rA6_e8eTOV4rq&C{Q?{jT;+I$!8G`CxeL#fWr*Gs^ zG!bQ_bHA{N0Tghx!|oL|tN4;hEdLLhTlXqt&M6f8F&*Gyhq&sHid}flBUE!4Jsy|q zuWnvL-Rd)<&)jbhIX4kQRydF^V~2j}(pPXZl&KG~KR6M)5;u;VPTuU8QkhiBh&MCy zn&&gr53=0({KO_8)AcVMVe)UF;e|xG*OcNefuNnNB6F@5mNych*)hTH#e^~48l3Ml z5L3pBD}eAay&KTA8PbNs;R8C(&h{^l*tI^z22MPxhh2}meNGzpsZ_{%Q+8`+MraPM zN#N5sP`eUA1;p5M3VeVdhT`IZSt>e=uPfv@?~dr#8MRANmi!wS6kl5AB@aUm#I4ig zQWR#T$w~vWF5Z3k@e^4KR@$qDw;=0=z65XEJcueW`sSI#9By_T(m(9MH!~ygXa9E1 za72;3=jlX#(ByY75tuh`=H-TLIi(G2S5_+_k$JCK{Geg_jnSNNn`3^yO?F9iKu}5U zd@R6H^OAKe)z4uR#5<1p=Ohu37V6rx$K_7mMvLWKYff6vGs^{0$xl& zww4lHj$fEy*%fDbWjX7a)m04_M*Xr7yR-UDnt_heHL=SiG1Uy04=0udSFxyrYL<65 z;5{{w5xxi28!Ig`OW7oAQ}9)|Ys-BIIFyQkxs+`^ZmFAUuc)Z6>HHQ*t^Gw^+H4=~ zj&zka`G^(RPI%AK8}`{#l~uNv#5$)PS~KbA#OVK@C3e)h}Z!QoiHxyUMN&RRR4%vU#Vtt;LW8BlbjI+3c0 z=!p^IQ?cZG&2p^*xOilaq16U&JM)~Q$&ruXExmq0m3r7#y z6E(%rnr=KfC|}KXs*hnPdQV9Bvmnm7oV6|MK?=!p8po3Rrzg3Ygh!09qO5`&DlUCpA8Iov-IX?uvRlo2)KVvCPDsuZX{a#bM9R< z`cs9lQRwo{p@DMt`tTy0$<1_nk%n9%)GlnK3ZGU!tvAc})9zl8E6Xpm)okOMkzupK z5&QGYvy@B@FU=gx69Lfq<&9HY1vSAUpHmta)30VSTz-uXQYIIHi1HBC%ruhsZ;m$? zN!f&;b=-RuQoef^^VX#L3Fu~$kn_{6xWV167iy1gdGOZN4N#c0)AZI=jnqB0o*$Iy zC1nE6bXbmspHH}q2Io20I@;O-_6j@Y@;hg8HXKJUYyeFd;l0AJ66LE)@ThR`466Xc zFWTCYU`PPhQ2H_8|4j@hh2#jEv&-#E$vrm;92E@{8PH@$nU!G%y-Lei%oq)6dVWO- z05TGx{M1R5iom}=6LZ4{Xf_07=z_D7D=Zp6MEwl+H!3&dGlr{WdU z{nY_)NdF|kTZCe3QMoFH_)-w4>7nyH#BdyJwc5WuRGyA$8JCgGOPOvOA;~N}(KppM zGrN0tlFdN?#dg9U617y(}>ap3Wu!U9b>aUV-bzWHk1~&ufUJ~TOt4%8jM4yOv^2xV&k%%n`wmu z01%-0blJFW%`)O@69xm6$^z+TZJ%6<2Xwza16(-$_2p{@iUJC6^meIX_0*NTkaFrK zn^#)TQoDzn=yd>7n1>mDAI`?*PQ1Js@UVKdpnJ>iF{PsqAde4{j7Vp|ePb=)Bw&-P4p11x z0f9s{b|A22>%f7ASKPvr2`S-{LXb=grQ~csK|H-AXaU4B4#6%iJL>CW5G1>=EQn=i zEKcseA`n?RSLe$h3^?FN+6CH|8L$>E!KY_@90DitKn)EE|1QAd&#s`8tOqrO>@7Ig z<6pkB)ua=K0~g;iwgCq7WrIhh4D~offjVovMH;F>1pg8=ru3^kpvaJ^1X?L`(u1B3 zs(l*)IW!Ichdf|+Roc`wl&rR|9>;r22G}j!^HQr0qXLsE_n_N}fGq03gK7fvI3$Ry z@FNZaiG{}6{$}MMsG2iKOR`uCB?wV{!@3x2zy)0g-?o(lC#A&KA5FP2=wR{4heH#O z)w5b9#MhoFqZ5aX)j5cO%w7j%Vvv$@5GH`TO9a(pU`Io2>qrK1nlw1LXHshkEQ%{l zu7xUGmx4~764o+jtp?OiEAll8Atr`mFb_$T(#4>*q61hm#!4jC5i3iB^QK=N|J~^O zjw15|LeB^cAYQ~jk*P1^N~s(y04pMx+}_&?OM)n@H9Uk?-NA;n z6|!EsXVOXO0-J%-1-p3_c)bpGPJLz{mA;4G<;x7*c}ITdq&{k_PPupVkip@Z>zvO6 z7J;2qoF(Lv%?4V}0xmIubEmTE+QD4XFU#`jR@*YLEPaCmvUa);-qMYAJ5421z?;5Zv ze?ty^6wj6&2I;Cm(CXdD5Se7jsh}2+K2uKNR{FIcT8`xV#wsvKH&9)CJm)Y1Aovc0 zfH|0_(OHvtpvvAT)dJCS8sK{wk5NHu0fZog5#hqs$+P22f5mLp%(*1auBlwfE>%b= zO{}>I^0NryTwKu=Zjh#63_}LbI5a#OjfSakCD)Zaj7)-WVcTEw2MFxmV?sTq1UzN`Sb(rWu5-`q3(7ZffPETu4aBhP|hN1w=Gqf#8 zLCZWFal{w2%+@?!pG)A)5JK?eEn9b63I^=y=uSbYVDII5S7^T2;_fpO)i^GiSI6KH zp+UZ{Kcqi2$LeWWi`>wKUgMtYk3Kes@4RtX-^AZ~6Bwn;l3RdrN(n36>jS1iI^L?Y zKw}uT)*x_AKWbe^Xr>^xXuI4$p9-F*-M$T38E}Eu+n)astpf{r#8udrmwDb;R~fg; zBW#}oqofhJBjI-3ax5h25FdB?{wW`HaCWH~=|Sp(+c~_vrXJ!j5U_+w zdf6KME_G%PGFP-g4oTtNIs#eb6ow*jw#9URd03a<3l@u&q0vDRQ85w0QmI^?Iy*C2 zA=QRNCI&52`o@d((jW^!?n{&$cZ!$L`@_IHg@TkL3Az&mF?J=ey^Bbv#E*7?l-qs% zu})wJMz|^nEdUo)mpfF=l+aF6s3iKy3v?rp}c$(+o)P1BJ;~0dn4n#9$D7&F&r1E4jNI4RiF-vd4(NAWh7wBC4 z5>?lDWjZX6xXk2W7s={|>(l3T)9?VyU%MvdAc7GdUQBUZe(cuyDM_@CwYc!B0O@p9 zcA&_K3c@<~0L9B_CqQzHwcCZxaSNbd*OUKT2#Dcir0hg8E0NGo!ac~RI)7#g1S!OdSa-Lgtb~U5 zfS`m%ofs#R(Qqh#?3gQ*+Pd@b<;(Zo?lK6ZlB`fhRg1Hu=ED0o5^e%FtgQr!ac{7!M8@ucVV;6+vebfv_ArA8TYtI9GIHXT5zoWa zm;+p9Nmxn^j*mYE$GLms*2muCOhkXg*-Y)FOTERG`th7WW8MaEd)7MBf^``?J=YbO z`m;D7XDRNzbg5XK83Y{&sbhzlDo$ry-0l(jR>V!Bf*Yy}IUqV;uNT>Xxd9RJ@v26> zXwti*F@K)H+^YU3;up&i56C8Dy;opvH5uHRhEi>3f+k-dk9pps3HtXqs-HNJ|IOy< z+GDYoy(5wT>V2o)(qPfE{~t1cKkNU7`sp7x!#@lSO;=Fd@IR*ecJTYzz(DNg95MVs zmw2jgulnVQpkJ00GX4Il4+K9J2Li47-c(n9*ZuVGR(?NZesA^WdEN6%ZGgSC?t2?2 zSJow1)~y)^Vq4^`r}3KOf0QVrN7gaFjg7U`+F~-Lndq{yd}Yz#`0J0s@eRfzWx~yR zE0=t*%Il+5<>k=ywrRb+C07!r&MhjMD+j%KKV(M@DY7MsYx2^u>ffMbk&-Mjsn$7 zgu$#^;c1>lw5k@-8^8Et#jdWz%L8o9$kH8JhxqHEGucby!KHmPyAdkvOF?5gv`%T~mqp2Jy+f)H5<`qXYtkFlwcluuIMH^&Y zTC@?7ZMN#~(0pzF(R%IIjl0&Ym(JD{B|J&c6!?ee4jXVFv2FSJ`eVrEWx+jYE(J~Z zcg3m7H6>tPr7CD3T$-`&!7qAq5U3%Fs)3vOzt3}x_FQ`J_otD*^Xojmn9~wsi7?o# z-gC$0x?#Ofuwu^(Q^zzZ@^53+IuO)<*gB@Nd?4EIO-dfyG6~POFv3lF`Tu7!an(fZ zs_y)}!)he3YJv9v_sIl+(o=S=%{1%#vxf`{>td0m4zCyNnr zXW_)v51m#QO2ym`C3J*|Up!r5wON(Oa*KLXGA(GNv!Bksm=lJ9x5WAFNTlF)VmKe$ zIuamCxQRm)7p+G_&^)SP89~F`)^Yk?4fDy-_;ZOwkH+UeKcOPOq;sVYG@4``n`Ct?z6G=6~G$X$T zcThx%Xz2X8b7ptVE_aLBwwxXF>*MWm0F9w}ywepuP(rn+4DUxyJBoKMN04AItMTgm zQM{?o0$lfFKXKGjw%g0LCD}>cpiOX-#@32yPY_mHl8WVs12KEbseq@w^M9y}{J`h6yvHcuyh@}nquUk8U8X7HD z4f@s{-dZx`!ZkpVw1_THCA9OpnSAGr%}(W+=0G%UN8GW1vd_)^pW`iAel62}2^2Lz1S*Xj_vf zkgigI=x9^nm`whXN=~l(7Z9S&l*A8aFZx6{ujo+mTPQ`T9#Psscr7?za3mUH=y)|o z&01r%;|(h9k6&Cf=*jb|{Sr&tXcRxU((wlCpnbqhW(!-{$9C4ShPCXZ13j2bPdYG& z0hEid1IwGT!;np2;hQ$IjE&(kb`5)Lk#Yx?6Lz^ek(&Xzswp?VVLw*5a1-lpfy8;? z8g|LK%h--6hH_Cu(DBxV&+NcJ`Y|BD=^P8Jw~TsaC12qVb_+QO;L=;ofww)!&+5Q5 zUS@V+D_XA4X^>#1DQY%6ZKwSB}N=rC^rWs(q^xj}g`P%cE^)u@|NA%^tMdvDK-V)b0Dl zU1P_t&92;%=S!u;e&_aOVbm|LZGI&%`w4hs-iZfMF3tm=T7L1?2O*mDAkb@i&&-#f z1jtso+lT>E9?ammbNvJH{}bzQg%qMEBw~@+$hZERuO^<7jv{Vk;_~TE(Hs0ARP=fR SOZR}g=t0ffALdsEwoCy}C+chf literal 5052 zcmV;t6GQBGPew8T0RR910290b4*&oF040C`025>Y0RR9100000000000000000000 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 S!>haXIZX>+@S6g2<^TY&bBksG diff --git a/public/img/404.svg b/public/img/404.svg index c963bb6..b4dbe78 100644 --- a/public/img/404.svg +++ b/public/img/404.svg @@ -1 +1,343 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/img/logo.svg b/public/img/logo.svg deleted file mode 100644 index 7ceed9f..0000000 --- a/public/img/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/public/js/main.js b/public/js/main.js index 994b2ae..895683a 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -2,13 +2,16 @@ * Fonction permettant d'afficher un message dans un toastr * @param {String} message */ - function showToastr(message) { + function showToastr(message, success = false) { let x = document.getElementById("toastr"); if ( message ) { x.getElementsByTagName("SPAN")[0].innerHTML = message; } - x.className = `${x.className} show`; + x.className = `${x.className} show`.replace("sucess", ""); + if ( success ) { + x.className = `${x.className} success`; + } setTimeout(function(){ x.className = x.className.replace("show", ""); }, 3000); }; diff --git a/public/mstile-310x150.png b/public/mstile-310x150.png deleted file mode 100644 index ed34b0c499418d137767f8a34d7a9aeba9893d3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7242 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 H+kgHC6DwZ$ diff --git a/sass/500.scss b/sass/500.scss new file mode 100644 index 0000000..910f8dd --- /dev/null +++ b/sass/500.scss @@ -0,0 +1,22 @@ +.body-500 { + padding: 0; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + font-weight: 400; + font-size: larger; + line-height: 200%; + + text-align: center; + + img { + max-width: 60%; + margin-bottom: 32px; + + @include respond-to("small-up") { + max-width: 30%; + } + } +} \ No newline at end of file diff --git a/sass/button.scss b/sass/button.scss index 1d8c946..1fd0e5d 100644 --- a/sass/button.scss +++ b/sass/button.scss @@ -54,7 +54,7 @@ &.is-link { background-color: transparent; border-color: $nord9; - color: $nord9; + color: var(--button-link-text-color); &:hover { border-color: darken($nord9, $hoverAmount); diff --git a/sass/ma-collection.scss b/sass/collection.scss similarity index 90% rename from sass/ma-collection.scss rename to sass/collection.scss index af22f2a..6412fe1 100644 --- a/sass/ma-collection.scss +++ b/sass/collection.scss @@ -1,4 +1,9 @@ -.ma-collection { +.collection { + h1 { + i { + cursor: pointer; + } + } .filters { display: flex; justify-content: end; diff --git a/sass/colors.scss b/sass/colors.scss index 5759f90..441062c 100644 --- a/sass/colors.scss +++ b/sass/colors.scss @@ -29,7 +29,7 @@ $danger-color-hl: darken($danger-color, $hoverAmount); $warning-color-hl: darken($warning-color, $hoverAmount); $success-color-hl: darken($success-color, $hoverAmount); -$button-font-color: $nord1; +$button-font-color: #2C364A; $button-alternate-color: #01103C; $pagination-border-color: $nord3; @@ -38,6 +38,7 @@ $pagination-hover-color: rgb(115, 151, 186); :root { --default-color: #{$white}; --bg-color: #{darken($white, 5%)}; + --bg-alternate-color: #{darken($white, 8%)}; --font-color: #{$nord3}; --footer-color: #{$darken-white}; --link-color: #{$nord1}; @@ -45,18 +46,38 @@ $pagination-hover-color: rgb(115, 151, 186); --input-font-color: #{$nord3}; --input-color: #{$white}; --input-active-color: #{$nord5}; - + --navbar-color: #{darken($white, 5%)}; --box-bg-color: #F8F9FB; --box-shadow-color: #{rgba($nord4, 0.35)}; --border-color: #{$nord4}; + + --button-link-text-color: #2C364A; + + --nord0: #{$nord0}; + --nord1: #{$nord1}; + --nord2: #{$nord2}; + --nord3: #{$nord3}; + --nord4: #{$nord4}; + --nord5: #{$nord5}; + --nord6: #{$nord6}; + --nord7: #{$nord7}; + --nord8: #{$nord8}; + --nord9: #{$nord9}; + --nord10: #{$nord10}; + --nord11: #{$nord11}; + --nord12: #{$nord12}; + --nord13: #{$nord13}; + --nord14: #{$nord14}; + --nord15: #{$nord15}; } [data-theme="dark"] { --default-color: #{$nord3}; --bg-color: #{lighten($nord0, 2%)}; + --bg-alternate-color: #{lighten($nord3, 8%)}; --font-color: #{$nord6}; --footer-color: #{$nord1}; --link-color: #{$nord4}; @@ -71,4 +92,6 @@ $pagination-hover-color: rgb(115, 151, 186); --box-shadow-color: #{rgba($nord4, 0.2)}; --border-color: #{$nord1}; + + --button-link-text-color: #{$white}; } \ No newline at end of file diff --git a/sass/composants.scss b/sass/composants.scss new file mode 100644 index 0000000..b9d4e65 --- /dev/null +++ b/sass/composants.scss @@ -0,0 +1,13 @@ +.composants { + .couleur { + margin-bottom: 1rem; + text-align: center; + + border: 1px solid var(--input-active-color); + box-shadow: var(--box-shadow-color) 0px 3px 6px 0px; + + div { + height: 56px; + } + } +} \ No newline at end of file diff --git a/sass/global.scss b/sass/global.scss index 491b9ca..454cd14 100644 --- a/sass/global.scss +++ b/sass/global.scss @@ -82,4 +82,8 @@ html { @include respond-to("small-up") { display: initial; } +} + +.is-danger { + color: $nord12; } \ No newline at end of file diff --git a/sass/icons.scss b/sass/icons.scss index ca297ea..4250307 100644 --- a/sass/icons.scss +++ b/sass/icons.scss @@ -46,6 +46,7 @@ .icon-link-ext:before { content: '\f08e'; } /* '' */ .icon-sun:before { content: '\f185'; } /* '' */ .icon-moon:before { content: '\f186'; } /* '' */ +.icon-share:before { content: '\f1e0'; } /* '' */ .icon-trash:before { content: '\f1f8'; } /* '' */ .icon-blind:before { content: '\f29d'; } /* '' */ @@ -61,4 +62,4 @@ 100% { transform: rotate(359deg); } -} \ No newline at end of file +} diff --git a/sass/index.scss b/sass/index.scss index aa7557a..3a53fd2 100644 --- a/sass/index.scss +++ b/sass/index.scss @@ -41,7 +41,9 @@ @import './box'; @import './error'; +@import './500'; @import './home'; @import './ajouter-un-album'; -@import './ma-collection'; -@import './ma-collection-details'; \ No newline at end of file +@import './collection'; +@import './ma-collection-details'; +@import './composants'; \ No newline at end of file diff --git a/sass/list.scss b/sass/list.scss index 7c479ff..9dbd03a 100644 --- a/sass/list.scss +++ b/sass/list.scss @@ -3,30 +3,35 @@ .item{ padding: 0.5rem 0.75rem; - border-bottom: 1px solid var(--border-color); + border-bottom: 2px solid var(--border-color); + background-color: var(--bg-alternate-color); @include transition() {} @include respond-to("medium") { &:nth-child(2n) { background-color: var(--default-color); } + border: none; } + @include respond-to("medium-up") { - border-left: 1px solid var(--border-color); + border-left: 2px solid var(--border-color); + + &:nth-child(4n), + &:nth-child(4n-1) + { + background-color: var(--default-color); + } &:first-child, &:nth-child(2) { - border-top: 1px solid var(--border-color); + border-top: 2px solid var(--border-color); } &:nth-child(2n), &:last-child { - border-right: 1px solid var(--border-color); - margin-right: -1px; - } - - &:hover { - background-color: var(--default-color); + border-right: 2px solid var(--border-color); + margin-right: -2px; } } @@ -44,4 +49,10 @@ max-width: 90%; } } + + &.hover { + .item:hover { + background-color: var(--border-color); + } + } } \ No newline at end of file diff --git a/sass/ma-collection-details.scss b/sass/ma-collection-details.scss index 6d4ba32..952a026 100644 --- a/sass/ma-collection-details.scss +++ b/sass/ma-collection-details.scss @@ -16,6 +16,7 @@ img { max-width: 90%; + max-height: 90%; } } } diff --git a/sass/toast.scss b/sass/toast.scss index 21d1730..46777e7 100644 --- a/sass/toast.scss +++ b/sass/toast.scss @@ -13,6 +13,11 @@ color: $button-alternate-color; border-radius: 6px; + &.success { + background-color: $success-color; + color: $button-font-color; + } + &.show { visibility: visible; animation: toastrFadein 0.5s, toastrFadeout 0.5s 2.5s; diff --git a/src/app.js b/src/app.js index 0b32d82..6d1e507 100644 --- a/src/app.js +++ b/src/app.js @@ -13,9 +13,11 @@ import { isXhr } from "./helpers"; import indexRouter from "./routes"; import maCollectionRouter from "./routes/ma-collection"; +import collectionRouter from "./routes/collection"; import importAlbumRouterApiV1 from "./routes/api/v1/albums"; import importSearchRouterApiV1 from "./routes/api/v1/search"; +import importMeRouterApiV1 from "./routes/api/v1/me"; // Mongoose schema init require("./models/users"); @@ -82,8 +84,10 @@ app.use( app.use("/", indexRouter); app.use("/ma-collection", maCollectionRouter); +app.use("/collection", collectionRouter); app.use("/api/v1/albums", importAlbumRouterApiV1); app.use("/api/v1/search", importSearchRouterApiV1); +app.use("/api/v1/me", importMeRouterApiV1); // Handle 404 app.use((req, res) => { @@ -113,7 +117,10 @@ app.use((error, req, res, next) => { } else { res.status(error.errorCode || 500); res.render("index", { - page: { title: "500: Oups… le serveur a crashé !", error }, + page: { + title: error.title || "500: Oups… le serveur a crashé !", + error, + }, errorCode: error.errorCode || 500, viewname: "error", user: req.user || null, diff --git a/src/config/index.js b/src/config/index.js index 43158f5..19f16ea 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -5,4 +5,7 @@ module.exports = { secret: process.env.SECRET || "waemaeMe5ahc6ce1chaeKohKa6Io8Eik", discogsToken: process.env.DISCOGS_TOKEN, formspreeId: process.env.FORMSPREE_ID, + matomoUrl: process.env.MATOMO_URL || "", + matomoId: process.env.MATOMO_ID || "", + siteName: process.env.SITE_NAME || "MusicTopus", }; diff --git a/src/libs/error.js b/src/libs/error.js index 562265f..13470f2 100644 --- a/src/libs/error.js +++ b/src/libs/error.js @@ -4,9 +4,10 @@ class ErrorEvent extends Error { /** * @param {Number} errorCode + * @param {String} title * @param {Mixed} ...params */ - constructor(errorCode, ...params) { + constructor(errorCode, title, ...params) { super(...params); if (Error.captureStackTrace) { @@ -14,6 +15,7 @@ class ErrorEvent extends Error { } this.errorCode = parseInt(errorCode, 10); + this.title = title; this.date = new Date(); } } diff --git a/src/middleware/Albums.js b/src/middleware/Albums.js index 4796207..6caa29b 100644 --- a/src/middleware/Albums.js +++ b/src/middleware/Albums.js @@ -5,12 +5,19 @@ import xl from "excel4node"; import Pages from "./Pages"; import AlbumsModel from "../models/albums"; +import UsersModel from "../models/users"; import ErrorEvent from "../libs/error"; /** * Classe permettant la gestion des albums d'un utilisateur */ class Albums extends Pages { + /** + * Méthode permettant de remplacer certains cartactères par leur équivalents html + * @param {String} str + * + * @return {String} + */ static replaceSpecialChars(str) { if (!str) { return ""; @@ -487,7 +494,7 @@ class Albums extends Pages { static async getAllDistincts(field, user) { const distincts = await AlbumsModel.find( { - user, + User: user, }, [], { @@ -513,8 +520,11 @@ class Albums extends Pages { order = "asc", artists_sort, format, + userId: collectionUserId, } = this.req.query; + let userId = this.req.user?._id; + const where = {}; if (artists_sort) { @@ -524,8 +534,35 @@ class Albums extends Pages { where["formats.name"] = format; } + if (!this.req.user && !collectionUserId) { + throw new ErrorEvent( + 401, + "Cette collection n'est pas publique", + "Cette collection n'est pas publique" + ); + } + + if (collectionUserId) { + const userIsSharingCollection = await UsersModel.findById( + collectionUserId + ); + + if ( + !userIsSharingCollection || + !userIsSharingCollection.isPublicCollection + ) { + throw new ErrorEvent( + 401, + "Cette collection n'est pas publique", + "Cette collection n'est pas publique" + ); + } + + userId = userIsSharingCollection._id; + } + const count = await AlbumsModel.count({ - user: this.req.user._id, + User: userId, ...where, }); @@ -547,7 +584,7 @@ class Albums extends Pages { const rows = await AlbumsModel.find( { - user: this.req.user._id, + User: userId, ...where, }, [], @@ -604,6 +641,7 @@ class Albums extends Pages { this.setPageContent("artists", artists); this.setPageContent("formats", formats); + this.setPageTitle("Ma collection"); } /** @@ -618,6 +656,33 @@ class Albums extends Pages { }); this.setPageContent("item", item); + this.setPageTitle( + `Détails de l'album ${item.title} de ${item.artists_sort}` + ); + } + + /** + * Méthode permettant de créer la page "collection/:userId" + */ + async loadPublicCollection() { + const { userId } = this.req.params; + + const user = await UsersModel.findById(userId); + + if (!user || !user.isPublicCollection) { + throw new ErrorEvent( + 401, + "Cet utilisateur ne souhaite pas partager sa collection" + ); + } + + const artists = await Albums.getAllDistincts("artists_sort", userId); + const formats = await Albums.getAllDistincts("formats.name", userId); + + this.setPageContent("username", user.username); + this.setPageTitle(`Collection publique de ${user.username}`); + this.setPageContent("artists", artists); + this.setPageContent("formats", formats); } } diff --git a/src/middleware/Me.js b/src/middleware/Me.js new file mode 100644 index 0000000..ae2712c --- /dev/null +++ b/src/middleware/Me.js @@ -0,0 +1,45 @@ +import Joi from "joi"; + +import UsersModel from "../models/users"; + +/** + * Classe permettant la gestion de l'utilisateur connecté + */ +class Me { + constructor(req) { + this.req = req; + } + + /** + * Méthode permettant de modifier le profil d'un utilisateur + * @return {Object} + */ + async patchMe() { + const { body, user } = this.req; + + const schema = Joi.object({ + isPublicCollection: Joi.boolean(), + }); + + const value = await schema.validateAsync(body); + const update = await UsersModel.findByIdAndUpdate( + user._id, + { $set: value }, + { new: true } + ); + + await new Promise((resolve, reject) => { + this.req.login(update, (err) => { + if (err) { + return reject(err); + } + + return resolve(null); + }); + }); + + return update; + } +} + +export default Me; diff --git a/src/middleware/Pages.js b/src/middleware/Pages.js index e5a59af..eb3ea75 100644 --- a/src/middleware/Pages.js +++ b/src/middleware/Pages.js @@ -34,6 +34,10 @@ class Pages { } } + setPageTitle(title) { + this.pageContent.page.title = title; + } + setPageContent(field, value) { this.pageContent.page[field] = value; } diff --git a/src/models/users.js b/src/models/users.js index 0807ccb..96629c0 100644 --- a/src/models/users.js +++ b/src/models/users.js @@ -1,5 +1,7 @@ /* eslint-disable func-names */ /* eslint-disable no-invalid-this */ +/* eslint-disable no-param-reassign */ + import mongoose from "mongoose"; import uniqueValidator from "mongoose-unique-validator"; import crypto from "crypto"; @@ -23,8 +25,20 @@ const UserSchema = new mongoose.Schema( }, hash: String, salt: String, + isPublicCollection: { + type: Boolean, + default: false, + }, }, - { timestamps: true } + { + timestamps: true, + toJSON: { + transform(doc, ret) { + delete ret.hash; + delete ret.salt; + }, + }, + } ); UserSchema.plugin(uniqueValidator, { message: "est déjà utilisé" }); diff --git a/src/routes/api/v1/albums.js b/src/routes/api/v1/albums.js index 164ea40..e1caa1f 100644 --- a/src/routes/api/v1/albums.js +++ b/src/routes/api/v1/albums.js @@ -9,7 +9,7 @@ const router = express.Router(); router .route("/") - .get(ensureLoggedIn("/connexion"), async (req, res, next) => { + .get(async (req, res, next) => { try { const albums = new Albums(req); const data = await albums.getAll(); @@ -19,9 +19,11 @@ router case "csv": case "musictopus": res.header("Content-Type", "text/csv"); + res.attachment("export-musictopus.csv"); return res.status(200).send(data); case "xml": res.header("Content-type", "text/xml"); + res.attachment("export-musictopus.xml"); return res.status(200).send(data); case "xls": return data.write("musictopus.xls", res); diff --git a/src/routes/api/v1/me.js b/src/routes/api/v1/me.js new file mode 100644 index 0000000..42c46b9 --- /dev/null +++ b/src/routes/api/v1/me.js @@ -0,0 +1,24 @@ +import express from "express"; +import { ensureLoggedIn } from "connect-ensure-login"; + +import { sendResponse } from "../../../libs/format"; + +import Me from "../../../middleware/Me"; + +// eslint-disable-next-line new-cap +const router = express.Router(); + +router + .route("/") + .patch(ensureLoggedIn("/connexion"), async (req, res, next) => { + try { + const me = new Me(req); + const data = await me.patchMe(); + + return sendResponse(req, res, data); + } catch (err) { + return next(err); + } + }); + +export default router; diff --git a/src/routes/collection.js b/src/routes/collection.js new file mode 100644 index 0000000..6584992 --- /dev/null +++ b/src/routes/collection.js @@ -0,0 +1,22 @@ +import express from "express"; + +import Albums from "../middleware/Albums"; + +import render from "../libs/format"; + +// eslint-disable-next-line new-cap +const router = express.Router(); + +router.route("/:userId").get(async (req, res, next) => { + try { + const page = new Albums(req, "collection"); + + await page.loadPublicCollection(); + + render(res, page); + } catch (err) { + next(err); + } +}); + +export default router; diff --git a/src/routes/index.js b/src/routes/index.js index 95c9a45..ac43a51 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -14,6 +14,8 @@ router.route("/").get((req, res, next) => { try { const page = new Pages(req, "home"); + page.setPageTitle("Présentation du projet"); + render(res, page); } catch (err) { next(err); @@ -26,6 +28,8 @@ router try { const page = new Pages(req, "connexion"); + page.setPageTitle("Connexion"); + render(res, page); } catch (err) { next(err); @@ -61,6 +65,8 @@ router try { const page = new Pages(req, "inscription"); + page.setPageTitle("Inscription"); + render(res, page); } catch (err) { next(err); @@ -82,6 +88,8 @@ router try { const page = new Pages(req, "ajouter-un-album"); + page.setPageTitle("Ajouter un album"); + render(res, page); } catch (err) { next(err); @@ -92,6 +100,8 @@ router.route("/nous-contacter").get(async (req, res, next) => { try { const page = new Pages(req, "nous-contacter"); + page.setPageTitle("Nous contacter"); + render(res, page); } catch (err) { next(err); @@ -102,6 +112,8 @@ router.route("/composants").get(async (req, res, next) => { try { const page = new Pages(req, "composants"); + page.setPageTitle("Les composants"); + render(res, page); } catch (err) { next(err); diff --git a/src/routes/ma-collection.js b/src/routes/ma-collection.js index 51ff0ee..9c217bf 100644 --- a/src/routes/ma-collection.js +++ b/src/routes/ma-collection.js @@ -10,7 +10,7 @@ const router = express.Router(); router.route("/").get(ensureLoggedIn("/connexion"), async (req, res, next) => { try { - const page = new Albums(req, "mon-compte/ma-collection"); + const page = new Albums(req, "mon-compte/ma-collection/index"); await page.loadMyCollection(); @@ -30,6 +30,8 @@ router try { const page = new Albums(req, "mon-compte/ma-collection/exporter"); + page.setPageTitle("Exporter ma collection"); + render(res, page); } catch (err) { next(err); diff --git a/views/error.ejs b/views/error.ejs index b0e5112..8f80430 100644 --- a/views/error.ejs +++ b/views/error.ejs @@ -5,7 +5,9 @@ Erreur 404

<% } %> + <% if ( process.env.NODE_ENV !== 'production' ) { %>
<%= page.error %>
+ <% } %> \ No newline at end of file diff --git a/views/index.ejs b/views/index.ejs index ddf0b8c..a2a98b5 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -4,7 +4,7 @@ - <% if (page.title) { %><%= page.title %> <% } else { %> DarKou - MusicTopus <% } %> + <%= config.siteName %> :: <%= page.title %> @@ -19,6 +19,24 @@ + + <% if ( config.matomoUrl ) { %> + + + + <% } %> - - diff --git a/views/pages/composants.ejs b/views/pages/composants.ejs index 7c17b38..79b8ee6 100644 --- a/views/pages/composants.ejs +++ b/views/pages/composants.ejs @@ -1,8 +1,9 @@ -
+

Les composants

  • Les titres
  • +
  • Les couleurs
  • Les grilles
  • Les boutons
  • Les formulaires
  • @@ -24,11 +25,92 @@
    Titre de niveau 5
    Titre de niveau 6
    +

    Les couleurs

    +

    Polar Night

    +
    +
    +
     
    + nord0 +
    +
    +
     
    + nord1 +
    +
    +
     
    + nord2 +
    +
    +
     
    + nord3 +
    +
    +

    Snow Storm

    +
    +
    +
     
    + nord4 +
    +
    +
     
    + nord5 +
    +
    +
     
    + nord6 +
    +
    +

    Frost

    +
    +
    +
     
    + nord7 +
    +
    +
     
    + nord8 +
    +
    +
     
    + nord9 +
    +
    +
     
    + nord10 +
    +
    +

    Aurora

    +
    +
    +
     
    + nord11 +
    +
    +
     
    + nord12 +
    +
    +
     
    + nord13 +
    +
    +
     
    + nord14 +
    +
    +
     
    + nord15 +
    +
    +

    + Vous pourrez trouver plus d'informations sur le site offciel du projet nord. +

    +

    Les grilles

    Se référer à la documentation de Knacss.

    - +

    Les boutons

    .button
    @@ -39,13 +121,13 @@

    Les formulaires

    - - + +
     <div class="field">
    -    <label for="email">Adresse e-mail</label>
    -    <input type="email" name="email" id="email" placeholder="ex : damien@darkou.fr">
    +    <label for="demo-email">Adresse e-mail</label>
    +    <input type="email" name="email" id="demo-email" placeholder="ex : damien@darkou.fr">
     </div>
         
    @@ -86,30 +168,38 @@ </select> </div> -
    +
    +
    +
    - + +
    +
    +
    +
    -<div class="field">
    +<div class="field inline">
         <label for="choix1">choix 1</label>
    -    <input type="radio" id="choix1" name="choix" value="choix1" checked> 
    +    <input type="radio" id="choix1" name="choix" value="choix1" checked>
    +</div>
    +<div class="field inline">
         <label for="choix2">choix 2</label>
         <input type="radio" id="choix2" name="choix" value="choix2">
     </div>
         
    - +
     <div class="field">
         <label for="checkbox1">choix 1</label>
    -    <input type="checkbox" id="checkbox1" name="checkbox" value="checkbox1" checked> 
    +    <input type="checkbox" id="checkbox1" name="checkbox" value="checkbox1" checked>
         <label for="checkbox2">choix 2</label>
         <input type="checkbox" id="checkbox2" name="checkbox" value="checkbox2">
     </div>
    @@ -161,11 +251,11 @@
                     
                     
                 
    - +

    Pas encore inscrit ? Inscrivez-vous

    - +
    @@ -196,20 +286,41 @@

    Les notifications

    +

    Erreur

    -<button 
    +<button
         type="button"
    -    class="button is-primary" 
    +    class="button is-primary"
         onclick="showToastr('Ceci est une notification');"
     >
         Afficher une notification
     </button>
     
    +<div id="toastr">
    +    <button class="delete" onclick="hideToastr()" aria-label="Masquer la notification"></button>
    +    <span></span>
    +</div>
    +    
    +

    Succès

    + +
    + + +
    +
    +<button
    +    type="button"
    +    class="button is-primary"
    +    onclick="showToastr('Ceci est une notification', true);"
    +>
    +    Afficher une notification
    +</button>
    +
     <div id="toastr">
         <button class="delete" onclick="hideToastr()" aria-label="Masquer la notification"></button>
         <span></span>
    @@ -225,15 +336,18 @@
         .icon-link-ext
         .icon-heart
         .icon-eye
    +    .icon-left-open
    +    .icon-right-open
    +    .icon-export
    +    .icon-share
         .icon-spin
         .icon-sun
         .icon-moon
         .icon-trash
         .icon-blind
    -    .icon-left-open
    -    .icon-right-open
     
         

    Les listes

    +

    Liste normale

    @@ -256,6 +370,29 @@ </div> </div>
    +

    Liste avec effet au hover

    +
    +
    + + {{ item.title }} + +
    +
    + +
    +
    + {{ item.lorem }} +
    +
    +
    +
    +
    +<div class="grid grid-cols-1 md:grid-cols-2 list hover">
    +    <div class="item">
    +        Contenu
    +    </div>
    +</div>
    +    

    Les paginations