diff --git a/.gitignore b/.gitignore index 8c2c770..3054b59 100644 --- a/.gitignore +++ b/.gitignore @@ -124,4 +124,3 @@ public/css public/js docker-compose.yml dump -data diff --git a/docker-compose.yml.dev b/docker-compose.yml.dev index d33ff77..6b6a0d5 100644 --- a/docker-compose.yml.dev +++ b/docker-compose.yml.dev @@ -1,62 +1,61 @@ version: "2.4" services: - musictopus-www: - container_name: musictopus-www - image: "node:18" - restart: always - user: "node" - working_dir: /home/node/app - command: > - bash -c " - yarn install && - yarn watch" - volumes: - - ./:/home/node/app - - /home/node/node_modules - ports: - - 3001:3001 - depends_on: - - musictopus-db - environment: - NODE_ENV: ${NODE_ENV} - PORT: ${PORT} - MONGODB_URI: ${MONGODB_URI} - SECRET: ${SECRET} - DISCOGS_TOKEN: ${DISCOGS_TOKEN} - FORMSPREE_ID: ${FORMSPREE_ID} - MATOMO_URL: ${MATOMO_URL} - MATOMO_ID: ${MATOMO_ID} - SITE_NAME: ${SITE_NAME} - AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} - AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} - S3_BASEFOLDER: ${S3_BASEFOLDER} - S3_BUCKET: ${S3_BUCKET} - S3_ENDPOINT: ${S3_ENDPOINT} - S3_SIGNATURE: ${S3_SIGNATURE} - JOBS_HEADER_KEY: ${JOBS_HEADER_KEY} - JOBS_HEADER_VALUE: ${JOBS_HEADER_VALUE} - REGISTRATION_OPEN: ${REGISTRATION_OPEN} - MAIL_METHOD: ${MAIL_METHOD} - MAIL_HOST: ${MAIL_HOST} - MAIL_PORT: ${MAIL_PORT} - MAIL_USER: ${MAIL_USER} - MAIL_PASSWORD: ${MAIL_PASSWORD} - MAIL_TO: ${MAIL_TO} - networks: - - musictopus - musictopus-db: - container_name: musictopus-db - image: mongo:4.4 - restart: always - ports: - - 27617:27017 - networks: - - musictopus - volumes: - - ./dump:/dump - - ./data:/data/db + musictopus-www: + container_name: musictopus-www + image: "node:18" + restart: always + user: "node" + working_dir: /home/node/app + command: > + bash -c " + yarn install && + yarn watch" + volumes: + - ./:/home/node/app + - /home/node/node_modules + ports: + - 3001:3001 + depends_on: + - musictopus-db + environment: + NODE_ENV: ${NODE_ENV} + PORT: ${PORT} + MONGODB_URI: ${MONGODB_URI} + SECRET: ${SECRET} + DISCOGS_TOKEN: ${DISCOGS_TOKEN} + FORMSPREE_ID: ${FORMSPREE_ID} + MATOMO_URL: ${MATOMO_URL} + MATOMO_ID: ${MATOMO_ID} + SITE_NAME: ${SITE_NAME} + AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} + AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} + S3_BASEFOLDER: ${S3_BASEFOLDER} + S3_BUCKET: ${S3_BUCKET} + S3_ENDPOINT: ${S3_ENDPOINT} + S3_SIGNATURE: ${S3_SIGNATURE} + JOBS_HEADER_KEY: ${JOBS_HEADER_KEY} + JOBS_HEADER_VALUE: ${JOBS_HEADER_VALUE} + REGISTRATION_OPEN: ${REGISTRATION_OPEN} + MAIL_METHOD: ${MAIL_METHOD} + MAIL_HOST: ${MAIL_HOST} + MAIL_PORT: ${MAIL_PORT} + MAIL_USER: ${MAIL_USER} + MAIL_PASSWORD: ${MAIL_PASSWORD} + MAIL_TO: ${MAIL_TO} + networks: + - musictopus + musictopus-db: + container_name: musictopus-db + image: mongo:4.4 + restart: always + ports: + - 27617:27017 + networks: + - musictopus + volumes: + - ./dump:/dump networks: - musictopus: - driver: bridge + musictopus: + driver: bridge diff --git a/fontello.json b/fontello.json index efb7b52..11e03d9 100644 --- a/fontello.json +++ b/fontello.json @@ -6,12 +6,6 @@ "units_per_em": 1000, "ascent": 850, "glyphs": [ - { - "uid": "ca90da02d2c6a3183f2458e4dc416285", - "css": "adjust", - "code": 59408, - "src": "fontawesome" - }, { "uid": "44e04715aecbca7f266a17d5a7863c68", "css": "plus", diff --git a/gulpfile.js b/gulpfile.js index fe1fe6f..8e76f38 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -10,7 +10,6 @@ const babel = require("gulp-babel"); const sourceJs = "javascripts/**/*.js"; const sourceRemoteJS = [ "./node_modules/vue/dist/vue.global.prod.js", - "./node_modules/chart.js/dist/chart.umd.js", "./node_modules/axios/dist/axios.min.js", ]; diff --git a/javascripts/ajouter-un-album.js b/javascripts/ajouter-un-album.js index 3bce60c..02f50d4 100644 --- a/javascripts/ajouter-un-album.js +++ b/javascripts/ajouter-un-album.js @@ -1,4 +1,3 @@ -/* eslint-disable no-undef */ Vue.createApp({ data() { return { @@ -79,12 +78,6 @@ Vue.createApp({ ], }; }, - created() { - window.addEventListener("keydown", this.keyDown); - }, - destroyed() { - window.removeEventListener("keydown", this.keyDown); - }, methods: { search(event) { event.preventDefault(); @@ -178,15 +171,12 @@ Vue.createApp({ this.submitting = true; return axios - .post(`/api/v1/${action}`, { + .post("/api/v1/albums", { album: this.details, share: this.share, }) .then(() => { - window.location.href = - action === "albums" - ? "/ma-collection" - : "/ma-liste-de-souhaits"; + window.location.href = "/ma-collection"; }) .catch((err) => { this.submitting = false; @@ -199,13 +189,5 @@ Vue.createApp({ orderedItems(items) { return items.sort(); }, - keyDown(event) { - const keycode = event.code; - - if (this.modalIsVisible && keycode === "Escape") { - event.preventDefault(); - this.modalIsVisible = false; - } - }, }, }).mount("#ajouter-album"); diff --git a/javascripts/collection.js b/javascripts/collection.js index 9e222d2..21ff703 100644 --- a/javascripts/collection.js +++ b/javascripts/collection.js @@ -1,4 +1,3 @@ -/* eslint-disable no-undef */ Vue.createApp({ data() { return { @@ -8,8 +7,8 @@ Vue.createApp({ total: 0, // eslint-disable-next-line no-undef page: query.page || 1, - limit: 16, totalPages: 1, + limit: 16, artist: "", format: "", year: "", @@ -35,18 +34,10 @@ Vue.createApp({ }, created() { this.fetch(); - - window.addEventListener("keydown", this.keyDown); - }, - destroyed() { - window.removeEventListener("keydown", this.keyDown); }, methods: { formatParams(param) { - return param - .replace("&", "%26") - .replace("+", "%2B") - .replace('"', "%22"); + return param.replace("&", "%26").replace("+", "%2B"); }, fetch() { this.loading = true; @@ -66,7 +57,7 @@ Vue.createApp({ const [key, value] = entry; switch (key) { case "artists_sort": - this.artist = value.replaceAll('"', "%22"); + this.artist = value; break; default: if (["order", "sort"].indexOf(key) !== -1) { @@ -78,7 +69,7 @@ Vue.createApp({ this.sortOrder = `${sortOrder.sort}-${sortOrder.order}`; - let url = `/api/v1/${action}?page=${this.page}&sort=${this.sort}&order=${this.order}`; + let url = `/api/v1/albums?page=${this.page}&limit=${this.limit}&sort=${this.sort}&order=${this.order}`; if (this.artist) { url += `&artist=${this.formatParams(this.artist)}`; } @@ -103,7 +94,6 @@ Vue.createApp({ .get(url) .then((response) => { this.items = response.data.rows; - this.limit = response.data.limit; this.total = response.data.count || 0; this.totalPages = parseInt(response.data.count / this.limit, 10) + @@ -190,7 +180,7 @@ Vue.createApp({ return false; } return axios - .delete(`/api/v1/${action}/${this.itemId}`) + .delete(`/api/v1/albums/${this.itemId}`) .then(() => { this.fetch(); }) @@ -250,16 +240,5 @@ Vue.createApp({ return render; }, - keyDown(event) { - const keycode = event.code; - if (this.showModalDelete && keycode === "Escape") { - event.preventDefault(); - this.showModalDelete = false; - } - if (this.showModalShare && keycode === "Escape") { - event.preventDefault(); - this.showModalShare = false; - } - }, }, }).mount("#collection"); diff --git a/javascripts/mon-compte/index.js b/javascripts/mon-compte/index.js index 464c8b6..2fb6f0f 100644 --- a/javascripts/mon-compte/index.js +++ b/javascripts/mon-compte/index.js @@ -1,3 +1,4 @@ + if (typeof email !== "undefined" && typeof username !== "undefined") { Vue.createApp({ data() { @@ -11,21 +12,15 @@ if (typeof email !== "undefined" && typeof username !== "undefined") { password: "", passwordConfirm: "", // eslint-disable-next-line no-undef - pagination, - // eslint-disable-next-line no-undef mastodon: mastodon || { publish: false, url: "", token: "", message: "Je viens d'ajouter {artist} - {album} à ma collection !", - wantlist: - "Je viens d'ajouter {artist} - {album} à ma liste de souhaits !", }, - delete: false, }, loading: false, - deleting: false, errors: [], }; }, @@ -62,13 +57,8 @@ if (typeof email !== "undefined" && typeof username !== "undefined") { // eslint-disable-next-line no-unused-vars async updateProfil() { this.errors = []; - const { - oldPassword, - password, - passwordConfirm, - mastodon, - pagination, - } = this.formData; + const { oldPassword, password, passwordConfirm, mastodon } = + this.formData; if (password && !oldPassword) { this.errors.push("emptyPassword"); @@ -93,8 +83,6 @@ if (typeof email !== "undefined" && typeof username !== "undefined") { data.oldPassword = oldPassword; } - data.pagination = pagination; - try { await axios.patch(`/api/v1/me`, data); @@ -110,20 +98,6 @@ if (typeof email !== "undefined" && typeof username !== "undefined") { return true; }, - async deleteAccount() { - try { - await axios.delete(`/api/v1/me`); - - showToastr("Compte supprimé", true); - - window.location.href = "/se-deconnecter"; - } catch (err) { - showToastr( - err.response?.data?.message || - "Impossible de mettre à jour votre profil" - ); - } - }, }, }).mount("#mon-compte"); } diff --git a/javascripts/mon-compte/ma-collection/details.js b/javascripts/mon-compte/ma-collection/details.js index 2297bdd..af0414f 100644 --- a/javascripts/mon-compte/ma-collection/details.js +++ b/javascripts/mon-compte/ma-collection/details.js @@ -1,4 +1,3 @@ -/* eslint-disable no-undef */ if (typeof item !== "undefined") { Vue.createApp({ data() { @@ -26,10 +25,10 @@ if (typeof item !== "undefined") { this.setTrackList(); this.setIdentifiers(); - window.addEventListener("keydown", this.keyDown); + window.addEventListener("keydown", this.changeImage); }, destroyed() { - window.removeEventListener("keydown", this.keyDown); + window.removeEventListener("keydown", this.changeImage); }, watch: { shareMessage(message) { @@ -41,8 +40,6 @@ if (typeof item !== "undefined") { this.shareMessageTransformed = message .replaceAll("{artist}", this.item.artists[0].name) .replaceAll("{format}", this.item.formats[0].name) - .replaceAll("{genres}", this.item.genres.join(", ")) - .replaceAll("{styles}", this.item.styles.join(", ")) .replaceAll("{year}", this.item.year) .replaceAll("{video}", video) .replaceAll("{album}", this.item.title); @@ -142,12 +139,12 @@ if (typeof item !== "undefined") { this.setImage(); }, changeImage(event) { - event.preventDefault(); const direction = event.code; if ( + this.modalIsVisible && ["ArrowRight", "ArrowLeft", "Escape"].indexOf(direction) !== - -1 + -1 ) { switch (direction) { case "ArrowRight": @@ -162,20 +159,6 @@ if (typeof item !== "undefined") { return true; }, - keyDown(event) { - const keycode = event.code; - if (this.modalIsVisible) { - this.changeImage(event); - } - if (this.showModalDelete && keycode === "Escape") { - event.preventDefault(); - this.showModalDelete = false; - } - if (this.showModalShare && keycode === "Escape") { - event.preventDefault(); - this.showModalShare = false; - } - }, showAllIdentifiers() { this.identifiersMode = "all"; this.setIdentifiers(); @@ -197,7 +180,7 @@ if (typeof item !== "undefined") { updateItem() { showToastr("Mise à jour en cours…", true); axios - .patch(`/api/v1/${action}/${this.item._id}`) + .patch(`/api/v1/albums/${this.item._id}`) .then((res) => { showToastr("Mise à jour réalisée avec succès", true); this.item = res.data; @@ -216,12 +199,9 @@ if (typeof item !== "undefined") { }, deleteItem() { axios - .delete(`/api/v1/${action}/${this.item._id}`) + .delete(`/api/v1/albums/${this.item._id}`) .then(() => { - window.location.href = - action === "albums" - ? "/ma-collection" - : "/ma-liste-de-souhaits"; + window.location.href = "/ma-collection"; }) .catch((err) => { showToastr( @@ -242,7 +222,7 @@ if (typeof item !== "undefined") { } this.shareSubmiting = true; axios - .post(`/api/v1/${action}/${this.item._id}/share`, { + .post(`/api/v1/albums/${this.item._id}/share`, { message: this.shareMessageTransformed, }) .then(() => { diff --git a/javascripts/mon-compte/ma-collection/exporter.js b/javascripts/mon-compte/ma-collection/exporter.js index 90ef809..b391436 100644 --- a/javascripts/mon-compte/ma-collection/exporter.js +++ b/javascripts/mon-compte/ma-collection/exporter.js @@ -1,4 +1,3 @@ -/* eslint-disable no-undef */ Vue.createApp({ data() { return { @@ -11,10 +10,7 @@ Vue.createApp({ exportCollection(event) { event.preventDefault(); - window.open( - `/api/v1/${action}?exportFormat=${this.format}`, - "_blank" - ); + window.open(`/api/v1/albums?exportFormat=${this.format}`, "_blank"); }, }, }).mount("#exporter"); diff --git a/javascripts/mon-compte/ma-collection/importer.js b/javascripts/mon-compte/ma-collection/importer.js index 6103bfa..08f2b6f 100644 --- a/javascripts/mon-compte/ma-collection/importer.js +++ b/javascripts/mon-compte/ma-collection/importer.js @@ -1,4 +1,3 @@ -/* eslint-disable no-undef */ Vue.createApp({ data() { return { @@ -67,11 +66,11 @@ Vue.createApp({ try { const res = await axios.get( - `/api/v1/${action}?discogsId=${release_id}` + `/api/v1/albums?discogsId=${release_id}` ); if (res.status === 204) { - await axios.post(`/api/v1/${action}`, { + await axios.post("/api/v1/albums", { discogsId: release_id, share: false, }); diff --git a/javascripts/theme.js b/javascripts/theme.js index e39836b..4625673 100644 --- a/javascripts/theme.js +++ b/javascripts/theme.js @@ -1,3 +1,19 @@ +/** + * Fonction permettant de sauvegarder dans le stockage local le choix du thème + * @param {String} scheme + */ +function saveColorScheme(scheme) { + localStorage.setItem("theme", scheme); +} + +/** + * Fonction permettant de changer le thème du site + * @param {String} scheme + */ +function setColorScheme(scheme) { + document.documentElement.setAttribute("data-theme", scheme); +} + /** * Fonction permettant de récupérer le thème du système * @return {String} @@ -12,56 +28,10 @@ function getPreferredColorScheme() { return "light"; } -/** - * @param {String} scheme - */ -function setPictoOnMenu(scheme) { - document.querySelectorAll(".icon-theme").forEach((item) => { - item.classList.add("hidden"); - }); - document - .querySelector(`.icon-theme.theme-${scheme}`) - .classList.remove("hidden"); -} - -/** - * Fonction permettant de sauvegarder dans le stockage local le choix du thème - * @param {String} scheme - */ -function saveColorScheme(scheme) { - localStorage.setItem("theme", scheme); -} - -/** - * Fonction permettant de changer le thème du site - * @param {String} scheme - */ -function setColorScheme(scheme) { - document.documentElement.setAttribute( - "data-theme", - scheme === "system" ? getPreferredColorScheme() : scheme - ); - - setPictoOnMenu(scheme); -} - -/** - * Fonction déclenchée lorsqu'un utilisateur clique sur un bouton dans le menu déroulant - * @param {Object} e - */ -function changeTheme(e) { - e.preventDefault(); - - const scheme = this.dataset.value; - - saveColorScheme(scheme); - setColorScheme(scheme); -} - // INFO: On place un event sur le bouton -const buttonsTheme = document.getElementsByClassName("theme"); -// INFO: On récupère du local storage (ou des préférences navigateur) le thème actuel -const currentTheme = localStorage.getItem("theme") || getPreferredColorScheme(); +const toggleSwitch = document.querySelector( + '.theme-switch input[type="checkbox"]' +); /** * Event permettant de détecter les changements de thème du système @@ -74,14 +44,28 @@ if (window.matchMedia) { if (selectedColorScheme === "system") { const preferedColorScheme = getPreferredColorScheme(); setColorScheme(preferedColorScheme); + + toggleSwitch.checked = preferedColorScheme === "dark"; } }); } +const currentTheme = localStorage.getItem("theme") || getPreferredColorScheme(); + // INFO: Au chargement de la page on détecte le thème à charger setColorScheme(currentTheme); -// INFO: On place un event au click sur chacun des boutons du menu -for (let i = 0; i < buttonsTheme.length; i += 1) { - buttonsTheme[i].addEventListener("click", changeTheme, false); -} +toggleSwitch.checked = currentTheme === "dark"; + +toggleSwitch.addEventListener( + "change", + (e) => { + e.preventDefault(); + + const scheme = e.target.checked ? "dark" : "light"; + + saveColorScheme(scheme); + setColorScheme(scheme); + }, + false +); diff --git a/package-lock.json b/package-lock.json index 64fdc92..1a49ca9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,6 @@ "@babel/core": "^7.17.2", "@babel/preset-env": "^7.16.11", "axios": "^0.26.0", - "chart.js": "^4.4.1", "connect-ensure-login": "^0.1.1", "connect-flash": "^0.1.1", "connect-mongo": "^4.6.0", @@ -5258,11 +5257,6 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "license": "MIT" }, - "node_modules/@kurkle/color": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", - "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" - }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.4.tgz", @@ -7919,17 +7913,6 @@ "node": ">=4" } }, - "node_modules/chart.js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz", - "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==", - "dependencies": { - "@kurkle/color": "^0.3.0" - }, - "engines": { - "pnpm": ">=7" - } - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", diff --git a/package.json b/package.json index 690739a..e8815fb 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,6 @@ "@babel/core": "^7.17.2", "@babel/preset-env": "^7.16.11", "axios": "^0.26.0", - "chart.js": "^4.4.1", "connect-ensure-login": "^0.1.1", "connect-flash": "^0.1.1", "connect-mongo": "^4.6.0", diff --git a/public/font/icon.eot b/public/font/icon.eot index 20368e4..424368f 100644 Binary files a/public/font/icon.eot and b/public/font/icon.eot differ diff --git a/public/font/icon.svg b/public/font/icon.svg index 04a06e1..52ad914 100644 --- a/public/font/icon.svg +++ b/public/font/icon.svg @@ -1,7 +1,7 @@ -Copyright (C) 2024 by original authors @ fontello.com +Copyright (C) 2022 by original authors @ fontello.com @@ -28,8 +28,6 @@ - - diff --git a/public/font/icon.ttf b/public/font/icon.ttf index 3941480..6688a79 100644 Binary files a/public/font/icon.ttf and b/public/font/icon.ttf differ diff --git a/public/font/icon.woff b/public/font/icon.woff index add6217..9543cf5 100644 Binary files a/public/font/icon.woff and b/public/font/icon.woff differ diff --git a/public/font/icon.woff2 b/public/font/icon.woff2 index eb6196f..c2acb70 100644 Binary files a/public/font/icon.woff2 and b/public/font/icon.woff2 differ diff --git a/sass/box.scss b/sass/box.scss index 5f3d322..95c138e 100644 --- a/sass/box.scss +++ b/sass/box.scss @@ -3,20 +3,17 @@ border-radius: 6px; box-shadow: var(--box-shadow-color) 0px 3px 6px 0px; color: var(--font-color); + display: block; padding: 1.25rem; - + width: calc(100% - 2rem); + margin: auto; @include transition() {} - &.mini { - margin: auto; - width: calc(100% - 2rem); - - @include respond-to("small-up") { - width: 65%; - } - @include respond-to("medium-up") { - width: 35%; - } + @include respond-to("small-up") { + width: 65%; + } + @include respond-to("medium-up") { + width: 35%; } h1 { diff --git a/sass/colors.scss b/sass/colors.scss index ae39df3..4328cf3 100644 --- a/sass/colors.scss +++ b/sass/colors.scss @@ -45,7 +45,6 @@ $close-background-dark: rgba(240,240,240,.6); --bg-color: #{darken($white, 5%)}; --bg-alternate-color: #{darken($white, 8%)}; --font-color: #{$nord3}; - --hover-font-color: #{lighten($nord3, 16%)}; --footer-color: #{$darken-white}; --link-color: #{$nord1}; @@ -89,7 +88,6 @@ $close-background-dark: rgba(240,240,240,.6); --bg-color: #{lighten($nord0, 2%)}; --bg-alternate-color: #{lighten($nord3, 8%)}; --font-color: #{$nord6}; - --hover-font-color: #{darken($nord6, 16%)}; --footer-color: #{$nord1}; --link-color: #{$nord4}; diff --git a/sass/forms.scss b/sass/forms.scss index 1e71919..125527a 100644 --- a/sass/forms.scss +++ b/sass/forms.scss @@ -70,4 +70,78 @@ background-size: 1.2rem; padding-right: 2.4rem; } -} \ No newline at end of file +} + +.theme-switch-wrapper { + display: flex; + align-items: center; + + em { + margin-left: 10px; + font-size: 1rem; + } +} + +.theme-switch { + display: inline-block; + height: 34px; + position: relative; + width: 60px; +} + +.theme-switch input { + display:none; +} + +.slider { + background-color: #ccc; + bottom: 0; + cursor: pointer; + left: 0; + position: absolute; + right: 0; + top: 0; + transition: .4s; + @include transition() {} +} + +.slider:before { + background-color: #fff; + bottom: 4px; + content: '\f185'; + height: 26px; + left: 4px; + position: absolute; + transition: .4s; + width: 26px; + padding: 0; + + font-family: "icon"; + font-style: normal; + font-weight: normal; + display: inline-block; + text-decoration: inherit; + text-align: center; + font-variant: normal; + text-transform: none; +} + +input:checked + .slider { + background-color: $primary-color; + @include transition() {} +} + +input:checked + .slider:before { + transform: translateX(26px); + content: '\f186'; + background-color: var(--input-active-color); + @include transition() {} +} + +.slider.round { + border-radius: 34px; +} + +.slider.round:before { + border-radius: 50%; +} diff --git a/sass/icons.scss b/sass/icons.scss index c841cf3..7b2150b 100644 --- a/sass/icons.scss +++ b/sass/icons.scss @@ -1,76 +1,66 @@ @font-face { font-family: 'icon'; - src: url('/font/icon.eot?15219908'); - src: url('/font/icon.eot?15219908#iefix') format('embedded-opentype'), - url('/font/icon.woff2?15219908') format('woff2'), - url('/font/icon.woff?15219908') format('woff'), - url('/font/icon.ttf?15219908') format('truetype'), - url('/font/icon.svg?15219908#icon') format('svg'); + src: url('/font/icon.eot?41426785'); + src: url('/font/icon.eot?41426785#iefix') format('embedded-opentype'), + url('/font/icon.woff2?41426785') format('woff2'), + url('/font/icon.woff?41426785') format('woff'), + url('/font/icon.ttf?41426785') format('truetype'), + url('/font/icon.svg?41426785#icon') format('svg'); font-weight: normal; font-style: normal; - } - /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ - /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ - /* - @media screen and (-webkit-min-device-pixel-ratio:0) { - @font-face { - font-family: 'icon'; - src: url('../font/icon.svg?15219908#icon') format('svg'); - } - } - */ - [class^="icon-"]:before, [class*=" icon-"]:before { +} + +[class^="icon-"]:before, [class*=" icon-"]:before { font-family: "icon"; font-style: normal; font-weight: normal; - speak: never; display: inline-block; text-decoration: inherit; width: 1em; margin-right: .2em; text-align: center; - /* opacity: .8; */ - /* For safety - reset parent styles, that can break glyph codes*/ font-variant: normal; text-transform: none; - /* fix buttons height, for twitter bootstrap */ line-height: 1em; - /* Animation center compensation - margins should be symmetric */ - /* remove if not needed */ margin-left: .2em; - /* you can be more comfortable with increased icons size */ - /* font-size: 120%; */ - - /* Font smoothing. That was taken from TWBS */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; +} - /* Uncomment for 3D effect */ - /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ - } +.icon-plus:before { content: '\e800'; } /* '' */ +.icon-user:before { content: '\e801'; } /* '' */ +.icon-search:before { content: '\e802'; } /* '' */ +.icon-mail:before { content: '\e803'; } /* '' */ +.icon-link:before { content: '\e804'; } /* '' */ +.icon-heart:before { content: '\e805'; } /* '' */ +.icon-eye:before { content: '\e806'; } /* '' */ +.icon-left-open:before { content: '\e807'; } /* '' */ +.icon-right-open:before { content: '\e808'; } /* '' */ +.icon-export:before { content: '\e809'; } /* '' */ +.icon-refresh:before { content: '\e80a'; } /* '' */ +.icon-spin:before { content: '\e839'; } /* '' */ +.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'; } /* '' */ - .icon-plus:before { content: '\e800'; } /* '' */ - .icon-user:before { content: '\e801'; } /* '' */ - .icon-search:before { content: '\e802'; } /* '' */ - .icon-mail:before { content: '\e803'; } /* '' */ - .icon-link:before { content: '\e804'; } /* '' */ - .icon-heart:before { content: '\e805'; } /* '' */ - .icon-eye:before { content: '\e806'; } /* '' */ - .icon-left-open:before { content: '\e807'; } /* '' */ - .icon-right-open:before { content: '\e808'; } /* '' */ - .icon-export:before { content: '\e809'; } /* '' */ - .icon-refresh:before { content: '\e80a'; } /* '' */ - .icon-adjust:before { content: '\e810'; } /* '' */ - .icon-spin:before { content: '\e839'; } /* '' */ - .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'; } /* '' */ +.animate-spin { + animation: spin 2s infinite linear; + display: inline-block; +} +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(359deg); + } +} diff --git a/sass/index.scss b/sass/index.scss index 808151b..476e4b8 100644 --- a/sass/index.scss +++ b/sass/index.scss @@ -16,7 +16,6 @@ @import './list'; @import './box'; @import './loader'; -@import './table'; @import './error'; @import './messages.scss'; diff --git a/sass/navbar.scss b/sass/navbar.scss index 593bb5f..b1aab70 100644 --- a/sass/navbar.scss +++ b/sass/navbar.scss @@ -103,7 +103,7 @@ .navbar-item { line-height: 1.5; - padding: .5rem; + padding: .5rem .75rem; position: relative; flex-grow: 0; flex-shrink: 0; @@ -117,6 +117,7 @@ @include respond-to("medium-up") { display: flex; align-items: stretch; + color: rgba(0,0,0,.7); .navbar-dropdown { background-color: var(--default-color); @@ -126,7 +127,8 @@ box-shadow: 0 8px 8px rgba(10,10,10,.1); display: none; font-size: .875rem; - min-width: 280px; + left: 0; + min-width: 100%; position: absolute; top: 100%; } @@ -136,7 +138,7 @@ .navbar-link { background-color: var(--default-hl-color); - color: var(--hover-font-color); + color: rgba(0,0,0,.7); } .navbar-dropdown { @@ -165,29 +167,6 @@ @include respond-to("medium-up") { display: flex; align-items: center; - - &::after { - border: 3px solid transparent; - border-radius: 2px; - border-right: 0; - border-top: 0; - content: " "; - display: block; - height: .625em; - pointer-events: none; - position: absolute; - top: 50%; - transform: rotate(-45deg); - transform-origin: center; - width: .625em; - border-color: var(--secondary-color); - margin-top: -0.375em; - right: 1.125em; - - @include respond-to("medium-up") { - border-color: var(--font-color); - } - } } .icon { @@ -198,7 +177,28 @@ width: 1.5rem; } + &::after { + border: 3px solid transparent; + border-radius: 2px; + border-right: 0; + border-top: 0; + content: " "; + display: block; + height: .625em; + pointer-events: none; + position: absolute; + top: 50%; + transform: rotate(-45deg); + transform-origin: center; + width: .625em; + border-color: var(--secondary-color); + margin-top: -0.375em; + right: 1.125em; + @include respond-to("medium-up") { + border-color: rgba(0,0,0,.7); + } + } } .navbar-menu { @@ -260,7 +260,13 @@ background-color: var(--font-color); border: none; height: 2px; - margin: .5rem 0 0 1.5rem; + margin: .5rem 0; + } + + .navbar-item { + cursor: pointer; + padding-left: 1.5rem; + padding-right: 1.5rem; } @include respond-to("medium-up") { @@ -271,19 +277,16 @@ box-shadow: 0 8px 8px rgba(10,10,10,.1); display: none; font-size: .875rem; - right: 0; + left: 0; min-width: 100%; position: absolute; top: 100%; - hr { - margin: 0.5rem 0; + .navbar-item { + white-space: nowrap; + padding: .375rem 1rem; + padding-right: 3rem; } - - // .navbar-item { - // white-space: nowrap; - // padding-block: .375rem; - // } } } @@ -317,10 +320,4 @@ .navbar { box-shadow: none; } -} - -nav { - ul { - padding-inline: 16px; - } } \ No newline at end of file diff --git a/sass/table.scss b/sass/table.scss deleted file mode 100644 index 44565df..0000000 --- a/sass/table.scss +++ /dev/null @@ -1,23 +0,0 @@ -table { - th, - td { - padding: 0.75rem; - text-align: left; - } - - thead { - tr { - border-bottom: 2px solid var(--font-color); - } - } - tbody { - tr { - background-color: var(--default-color); - - &:nth-child(2n) { - background-color: var(--bg-alternate-color); - } - } - - } -} \ No newline at end of file diff --git a/src/app.js b/src/app.js index 4f9e4aa..b293a37 100644 --- a/src/app.js +++ b/src/app.js @@ -9,20 +9,18 @@ import MongoStore from "connect-mongo"; import passportConfig from "./libs/passport"; -import config, { env, mongoDbUri, port, secret } from "./config"; +import config, { env, mongoDbUri, secret } from "./config"; import { isXhr } from "./helpers"; import indexRouter from "./routes"; import maCollectionRouter from "./routes/ma-collection"; -import wantlistRouter from "./routes/wantlist"; import monCompteRouter from "./routes/mon-compte"; import collectionRouter from "./routes/collection"; import importJobsRouter from "./routes/jobs"; import importAlbumRouterApiV1 from "./routes/api/v1/albums"; -import importWantlistRouterApiV1 from "./routes/api/v1/wantlist"; import importSearchRouterApiV1 from "./routes/api/v1/search"; import importMastodonRouterApiV1 from "./routes/api/v1/mastodon"; import importMeRouterApiV1 from "./routes/api/v1/me"; @@ -83,11 +81,9 @@ app.use(express.static(path.join(__dirname, "../public"))); app.use("/", indexRouter); app.use("/mon-compte", monCompteRouter); app.use("/ma-collection", maCollectionRouter); -app.use("/ma-liste-de-souhaits", wantlistRouter); app.use("/collection", collectionRouter); app.use("/jobs", importJobsRouter); app.use("/api/v1/albums", importAlbumRouterApiV1); -app.use("/api/v1/wantlist", importWantlistRouterApiV1); app.use("/api/v1/search", importSearchRouterApiV1); app.use("/api/v1/mastodon", importMastodonRouterApiV1); app.use("/api/v1/me", importMeRouterApiV1); @@ -154,6 +150,4 @@ app.use((error, req, res, next) => { } }); -console.log(`Server listening on port ${port}!`); - export default app; diff --git a/src/helpers/index.js b/src/helpers/index.js index 59d92ca..d07fe14 100644 --- a/src/helpers/index.js +++ b/src/helpers/index.js @@ -53,28 +53,3 @@ export const isXhr = (req) => { return is; }; - -/** - * Méthode permettant de récupérer les éléments distincts d'une collection - * @param {Object} model - * @param {String} field - * @param {import("mongoose").ObjectId} user - * @returns - */ -export const getAllDistincts = async (model, field, user) => { - const distincts = await model - .find( - { - User: user, - }, - [], - { - sort: { - [field]: 1, - }, - } - ) - .distinct(field); - - return distincts; -}; diff --git a/src/libs/format.js b/src/libs/format.js index 4d0da37..14dfaf9 100644 --- a/src/libs/format.js +++ b/src/libs/format.js @@ -34,23 +34,6 @@ export const sendResponse = (req, res, data) => { } }; -export const setHashTags = (arr) => { - let hashTags = ""; - - for (let i = 0; i < arr.length; i += 1) { - let currentHash = `${hashTags ? ", " : ""} #`; - const currentItem = arr[i].split(" "); - for (let j = 0; j < currentItem.length; j += 1) { - currentHash += - currentItem[j].toLowerCase().charAt(0).toUpperCase() + - currentItem[j].toLowerCase().slice(1); - } - hashTags += currentHash; - } - - return hashTags; -}; - export default (res, page) => { res.status(200).render("index", page.render()); }; diff --git a/src/middleware/Albums.js b/src/middleware/Albums.js index ac19eac..59d6c5c 100644 --- a/src/middleware/Albums.js +++ b/src/middleware/Albums.js @@ -1,4 +1,4 @@ -import { format as formatDate, startOfYear, subYears } from "date-fns"; +import { format as formatDate } from "date-fns"; import fs from "fs"; import Mastodon from "mastodon"; @@ -12,8 +12,7 @@ import JobsModel from "../models/jobs"; import UsersModel from "../models/users"; import ErrorEvent from "../libs/error"; -import { getAlbumDetails, getAllDistincts } from "../helpers"; -import { setHashTags } from "../libs/format"; +import { getAlbumDetails } from "../helpers"; /** * Classe permettant la gestion des albums d'un utilisateur @@ -43,11 +42,8 @@ class Albums extends Pages { discogsId: albumDetails.id, User: user._id, }; - // eslint-disable-next-line no-nested-ternary data.released = data.released - ? typeof data.released === "string" - ? new Date(data.released.replace("-00", "-01")) - : data.released + ? new Date(data.released.replace("-00", "-01")) : null; delete data.id; @@ -87,9 +83,6 @@ class Albums extends Pages { ) .replaceAll("{artist}", data.artists[0].name) .replaceAll("{format}", data.formats[0].name) - .replaceAll("{#genres}", setHashTags(data.genres)) - .replaceAll("{styles}", data.styles.join(", ")) - .replaceAll("{#styles}", setHashTags(data.styles)) .replaceAll("{year}", data.year) .replaceAll("{video}", video) .replaceAll("{album}", data.title)} @@ -147,22 +140,26 @@ Publié automatiquement via #musictopus`; return album; } - constructor(req, viewname) { - super(req, viewname); + /** + * Méthode permettant de récupérer les éléments distincts d'une collection + * @param {String} field + * @param {ObjectId} user + * @return {Array} + */ + static async getAllDistincts(field, user) { + const distincts = await AlbumsModel.find( + { + User: user, + }, + [], + { + sort: { + [field]: 1, + }, + } + ).distinct(field); - this.colors = [ - "#2e3440", - "#d8dee9", - "#8fbcbb", - "#5e81ac", - "#d08770", - "#bf616a", - "#ebcb8b", - "#a3be8c", - "#b48ead", - ]; - - this.setPageContent("action", "albums"); + return distincts; } /** @@ -172,6 +169,7 @@ Publié automatiquement via #musictopus`; async getAll() { const { page, + limit, exportFormat = "json", sort = "artists_sort", order = "asc", @@ -185,8 +183,6 @@ Publié automatiquement via #musictopus`; discogsId, } = this.req.query; - const limit = this.req.user?.pagination || 16; - let userId = this.req.user?._id; const where = {}; @@ -252,7 +248,7 @@ Publié automatiquement via #musictopus`; }, }; - if (exportFormat === "json" && page && limit) { + if (page && limit) { const skip = (page - 1) * limit; params = { @@ -284,7 +280,6 @@ Publié automatiquement via #musictopus`; default: return { rows, - limit, count, }; } @@ -442,28 +437,20 @@ Publié automatiquement via #musictopus`; * Méthode permettant de créer la page "ma-collection" */ async loadMyCollection() { - const artists = await getAllDistincts( - AlbumsModel, + const artists = await Albums.getAllDistincts( "artists.name", this.req.user._id ); - const formats = await getAllDistincts( - AlbumsModel, + const formats = await Albums.getAllDistincts( "formats.name", this.req.user._id ); - const years = await getAllDistincts( - AlbumsModel, - "year", - this.req.user._id - ); - const genres = await getAllDistincts( - AlbumsModel, + const years = await Albums.getAllDistincts("year", this.req.user._id); + const genres = await Albums.getAllDistincts( "genres", this.req.user._id ); - const styles = await getAllDistincts( - AlbumsModel, + const styles = await Albums.getAllDistincts( "styles", this.req.user._id ); @@ -513,230 +500,6 @@ Publié automatiquement via #musictopus`; await this.loadItem(); } - /** - * Méthode permettant d'afficher des statistiques au sujet de ma collection - */ - async statistics() { - const { _id: User } = this.req.user; - const top = {}; - const byGenres = {}; - const byStyles = {}; - const byFormats = {}; - const top10 = []; - let byStyles10 = []; - const max = this.colors.length - 1; - const startYear = startOfYear(new Date()); - const lastStartYear = startOfYear(subYears(new Date(), 1)); - const currentYear = { - year: formatDate(startYear, "yyyy"), - total: 0, - byGenres: {}, - byStyles: {}, - byFormats: {}, - }; - const lastYear = { - year: formatDate(lastStartYear, "yyyy"), - total: 0, - byGenres: {}, - byStyles: {}, - byFormats: {}, - }; - - const colorsCount = this.colors.length; - - const albums = await AlbumsModel.find({ - User, - artists: { $exists: true, $not: { $size: 0 } }, - }); - - for (let i = 0; i < albums.length; i += 1) { - const currentFormats = []; - const { artists, genres, styles, formats, createdAt } = albums[i]; - - // INFO: On s'occupe de la rétrospective - if (createdAt > startYear) { - currentYear.total += 1; - } else if (createdAt > lastStartYear) { - lastYear.total += 1; - } - - // INFO: On regroupe les artistes par nom pour en faire le top10 - for (let j = 0; j < artists.length; j += 1) { - const { name } = artists[j]; - if (!top[name]) { - top[name] = { - name, - count: 0, - }; - } - top[name].count += 1; - } - - // INFO: On regroupe les genres - for (let j = 0; j < genres.length; j += 1) { - const name = genres[j]; - if (!byGenres[name]) { - byGenres[name] = { - name, - count: 0, - color: this.colors[ - Object.keys(byGenres).length % colorsCount - ], - }; - } - - byGenres[name].count += 1; - - // INFO: On s'occupe de la rétrospective - if (createdAt > startYear) { - if (!currentYear.byGenres[name]) { - currentYear.total += 1; - currentYear.byGenres[name] = { - name, - count: 0, - color: byGenres[name].color, - }; - } - currentYear.byGenres[name].count += 1; - } else if (createdAt > lastStartYear) { - if (!lastYear.byGenres[name]) { - lastYear.byGenres[name] = { - name, - count: 0, - color: byGenres[name].color, - }; - } - lastYear.byGenres[name].count += 1; - } - } - - // INFO: On regroupe les styles - for (let j = 0; j < styles.length; j += 1) { - const name = styles[j]; - if (!byStyles[name]) { - byStyles[name] = { - name, - count: 0, - color: this.colors[ - Object.keys(byStyles).length % colorsCount - ], - }; - } - - byStyles[name].count += 1; - - // INFO: On s'occupe de la rétrospective - if (createdAt > startYear) { - if (!currentYear.byStyles[name]) { - currentYear.total += 1; - currentYear.byStyles[name] = { - name, - count: 0, - color: byStyles[name].color, - }; - } - currentYear.byStyles[name].count += 1; - } else if (createdAt > lastStartYear) { - if (!lastYear.byStyles[name]) { - lastYear.byStyles[name] = { - name, - count: 0, - color: byStyles[name].color, - }; - } - lastYear.byStyles[name].count += 1; - } - } - - // INFO: On regroupe les formats - for (let j = 0; j < formats.length; j += 1) { - const { name } = formats[j]; - // INFO: On évite qu'un album avec 2 vinyles soit compté 2x - if (!currentFormats.includes(name)) { - if (!byFormats[name]) { - byFormats[name] = { - name, - count: 0, - color: this.colors[ - Object.keys(byFormats).length % colorsCount - ], - }; - } - - byFormats[name].count += 1; - currentFormats.push(name); - - // INFO: On s'occupe de la rétrospective - if (createdAt > startYear) { - if (!currentYear.byFormats[name]) { - currentYear.total += 1; - currentYear.byFormats[name] = { - name, - count: 0, - color: byFormats[name].color, - }; - } - currentYear.byFormats[name].count += 1; - } else if (createdAt > lastStartYear) { - if (!lastYear.byFormats[name]) { - lastYear.byFormats[name] = { - name, - count: 0, - color: byFormats[name].color, - }; - } - lastYear.byFormats[name].count += 1; - } - } - } - } - - // INFO: On convertit le top en tableau - Object.keys(top).forEach((index) => { - top10.push(top[index]); - }); - - // INFO: On convertit les styles en tableau - Object.keys(byStyles).forEach((index) => { - byStyles10.push(byStyles[index]); - }); - - // INFO: On ordonne les artistes par quantité d'albums - top10.sort((a, b) => (a.count > b.count ? -1 : 1)); - - // INFO: On ordonne les styles par quantité - byStyles10.sort((a, b) => (a.count > b.count ? -1 : 1)); - const tmp = []; - - // INFO: On recupère le top N des styles et on mets le reste dans le label "autre" - for (let i = 0; i < byStyles10.length; i += 1) { - if (i < max) { - tmp.push({ - ...byStyles10[i], - color: this.colors[max - i], - }); - } else if (i === max) { - tmp.push({ - name: "Autre", - count: 0, - color: this.colors[0], - }); - tmp[max].count += byStyles10[i].count; - } else { - tmp[max].count += byStyles10[i].count; - } - } - byStyles10 = tmp; - - this.setPageTitle("Mes statistiques"); - this.setPageContent("top10", top10.splice(0, 10)); - this.setPageContent("byGenres", byGenres); - this.setPageContent("byStyles", byStyles10); - this.setPageContent("byFormats", byFormats); - this.setPageContent("currentYear", currentYear); - this.setPageContent("lastYear", lastYear); - } - /** * Méthode permettant de créer la page "collection/:userId" */ @@ -753,22 +516,14 @@ Publié automatiquement via #musictopus`; ); } - const artists = await getAllDistincts( - AlbumsModel, - "artists.name", - userId - ); - const formats = await getAllDistincts( - AlbumsModel, - "formats.name", - userId - ); - const years = await getAllDistincts(AlbumsModel, "year", userId); - const genres = await getAllDistincts(AlbumsModel, "genres", userId); - const styles = await getAllDistincts(AlbumsModel, "styles", userId); + const artists = await Albums.getAllDistincts("artists.name", userId); + const formats = await Albums.getAllDistincts("formats.name", userId); + const years = await Albums.getAllDistincts("year", userId); + const genres = await Albums.getAllDistincts("genres", userId); + const styles = await Albums.getAllDistincts("styles", userId); - this.setPageTitle(`Collection publique de ${user.username}`); this.setPageContent("username", user.username); + this.setPageTitle(`Collection publique de ${user.username}`); this.setPageContent("artists", artists); this.setPageContent("formats", formats); this.setPageContent("years", years); diff --git a/src/middleware/Export.js b/src/middleware/Export.js index de06604..513e440 100644 --- a/src/middleware/Export.js +++ b/src/middleware/Export.js @@ -123,8 +123,8 @@ class Export { ws.cell(currentRow, 1).string(artists_sort).style(style); ws.cell(currentRow, 2).string(title).style(style); - ws.cell(currentRow, 3).string(genres.join(", ")).style(style); - ws.cell(currentRow, 4).string(styles.join(", ")).style(style); + ws.cell(currentRow, 3).string(genres.join()).style(style); + ws.cell(currentRow, 4).string(styles.join()).style(style); if (country) { ws.cell(currentRow, 5).string(country).style(style); } diff --git a/src/middleware/Jobs.js b/src/middleware/Jobs.js index 4273d83..91964f2 100644 --- a/src/middleware/Jobs.js +++ b/src/middleware/Jobs.js @@ -5,7 +5,6 @@ import { getAlbumDetails } from "../helpers"; import JobsModel from "../models/jobs"; import AlbumsModel from "../models/albums"; -import WantListModel from "../models/wantlist"; class Jobs { /** @@ -52,50 +51,6 @@ class Jobs { return true; } - /** - * Méthode permettant de télécharger toute les images d'un album - * @param {ObjectId} itemId - */ - static async importAlbumForWantListAssets(itemId) { - const album = await WantListModel.findById(itemId); - - if (!album) { - throw new ErrorEvent( - 404, - "Item non trouvé", - `L'album avec l'id ${itemId} n'existe plus dans la collection` - ); - } - - const item = await getAlbumDetails(album.discogsId); - - if (!item) { - throw new ErrorEvent( - 404, - "Erreur de communication", - "Erreur lors de la récupération des informations sur Discogs" - ); - } - - if (item.thumb) { - album.thumb = await uploadFromUrl(item.thumb); - album.thumbType = "local"; - } - const { images } = item; - if (images && images.length > 0) { - for (let i = 0; i < images.length; i += 1) { - images[i].uri150 = await uploadFromUrl(images[i].uri150); - images[i].uri = await uploadFromUrl(images[i].uri); - } - } - - album.images = images; - - await album.save(); - - return true; - } - /** * Point d'entrée * @param {String} state @@ -123,9 +78,6 @@ class Jobs { case "Albums": await Jobs.importAlbumAssets(job.id); break; - case "WantList": - await Jobs.importAlbumForWantListAssets(job.id); - break; default: throw new ErrorEvent( 500, diff --git a/src/middleware/Me.js b/src/middleware/Me.js index 5a477cc..edf40db 100644 --- a/src/middleware/Me.js +++ b/src/middleware/Me.js @@ -1,8 +1,6 @@ import Joi from "joi"; import UsersModel from "../models/users"; -import AlbumsModel from "../models/albums"; -import WantlistModel from "../models/wantlist"; import Pages from "./Pages"; /** @@ -18,7 +16,6 @@ class Me extends Pages { const { _id } = this.req.user; const schema = Joi.object({ - pagination: Joi.number(), isPublicCollection: Joi.boolean(), oldPassword: Joi.string(), password: Joi.string(), @@ -28,7 +25,6 @@ class Me extends Pages { url: Joi.string().uri().allow(null, ""), token: Joi.string().allow(null, ""), message: Joi.string().allow(null, ""), - wantlist: Joi.string().allow(null, ""), }, }); @@ -49,10 +45,6 @@ class Me extends Pages { user.salt = value.password; } - if (value.pagination) { - user.pagination = value.pagination; - } - if (value.isPublicCollection !== undefined) { user.isPublicCollection = value.isPublicCollection; } @@ -71,23 +63,6 @@ class Me extends Pages { return user; } - - /** - * Méthode permettant de supprimer un utilisateur et toutes ses données - * - * @return {Object} - */ - async deleteMe() { - const { _id } = this.req.user; - - await AlbumsModel.deleteMany({ User: _id }); - await WantlistModel.deleteMany({ User: _id }); - await UsersModel.deleteOne({ _id }); - - return { - deleted: true, - }; - } } export default Me; diff --git a/src/middleware/Wantlist.js b/src/middleware/Wantlist.js deleted file mode 100644 index 0f51ec3..0000000 --- a/src/middleware/Wantlist.js +++ /dev/null @@ -1,690 +0,0 @@ -import { format as formatDate } from "date-fns"; -import fs from "fs"; - -import Mastodon from "mastodon"; -import { v4 } from "uuid"; -import axios from "axios"; -import Pages from "./Pages"; -import Export from "./Export"; - -import WantListModel from "../models/wantlist"; -import JobsModel from "../models/jobs"; -import UsersModel from "../models/users"; -import ErrorEvent from "../libs/error"; - -import { getAlbumDetails, getAllDistincts } from "../helpers"; -import { setHashTags } from "../libs/format"; - -/** - * Classe permettant la gestion da la liste de souhaits d'un utilisateur - */ -class Wantlist extends Pages { - /** - * Méthode permettant d'ajouter un album dans une collection - * @param {Object} req - * @return {Object} - */ - static async postAddOne(req) { - const { body, user } = req; - const { share, discogsId } = body; - - let albumDetails = body.album; - if (discogsId) { - albumDetails = await getAlbumDetails(discogsId); - body.id = discogsId; - } - - if (!albumDetails) { - throw new ErrorEvent(406, "Aucun album à ajouter"); - } - - const data = { - ...albumDetails, - discogsId: albumDetails.id, - User: user._id, - }; - // eslint-disable-next-line no-nested-ternary - data.released = data.released - ? typeof data.released === "string" - ? new Date(data.released.replace("-00", "-01")) - : data.released - : null; - delete data.id; - - const album = new WantListModel(data); - - await album.save(); - - const jobData = { - model: "WantList", - id: album._id, - }; - const job = new JobsModel(jobData); - - job.save(); - - try { - const User = await UsersModel.findOne({ _id: user._id }); - - const { mastodon: mastodonConfig } = User; - - const { publish, token, url, wantlist } = mastodonConfig; - - if (share && publish && url && token) { - const M = new Mastodon({ - access_token: token, - api_url: url, - }); - - const video = - data.videos && data.videos.length > 0 - ? data.videos[0].uri - : ""; - - const status = `${( - wantlist || - "Je viens d'ajouter {artist} - {album} à ma liste de souhaits !" - ) - .replaceAll("{artist}", data.artists[0].name) - .replaceAll("{format}", data.formats[0].name) - .replaceAll("{genres}", data.genres.join(", ")) - .replaceAll("{#genres}", setHashTags(data.genres)) - .replaceAll("{styles}", data.styles.join(", ")) - .replaceAll("{#styles}", setHashTags(data.styles)) - .replaceAll("{year}", data.year) - .replaceAll("{video}", video) - .replaceAll("{album}", data.title)} - -Publié automatiquement via #musictopus`; - - const media_ids = []; - - if (data.images.length > 0) { - for (let i = 0; i < data.images.length; i += 1) { - if (media_ids.length === 4) { - break; - } - - const filename = `${v4()}.jpg`; - const file = `/tmp/${filename}`; - - // eslint-disable-next-line no-await-in-loop - const { data: buff } = await axios.get( - data.images[i].uri, - { - headers: { - "User-Agent": - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/117.0", - }, - responseType: "arraybuffer", - } - ); - - fs.writeFileSync(file, buff); - - // eslint-disable-next-line no-await-in-loop - const { data: media } = await M.post("media", { - file: fs.createReadStream(file), - }); - - const { id } = media; - - media_ids.push(id); - - fs.unlinkSync(file); - } - } - - await M.post("statuses", { status, media_ids }); - } - } catch (err) { - throw new ErrorEvent( - 500, - "Mastodon", - "Album ajouté à votre collection mais impossible de publier sur Mastodon" - ); - } - - return album; - } - - constructor(req, viewname) { - super(req, viewname); - - this.colors = [ - "#2e3440", - "#d8dee9", - "#8fbcbb", - "#5e81ac", - "#d08770", - "#bf616a", - "#ebcb8b", - "#a3be8c", - "#b48ead", - ]; - - this.setPageContent("action", "wantlist"); - } - - /** - * Méthode permettant de récupérer la liste des albums d'une collection - * @return {Object} - */ - async getAll() { - const { - page, - exportFormat = "json", - sort = "artists_sort", - order = "asc", - artist, - format, - year, - genre, - style, - userId: collectionUserId, - discogsIds, - discogsId, - } = this.req.query; - - const limit = this.req.user?.pagination || 16; - - let userId = this.req.user?._id; - - const where = {}; - - if (artist) { - where["artists.name"] = artist; - } - if (format) { - where["formats.name"] = format; - } - if (year) { - where.year = year; - } - if (genre) { - where.genres = genre; - } - if (style) { - where.styles = style; - } - - if (!this.req.user && !collectionUserId) { - throw new ErrorEvent( - 401, - "Collection", - "Cette collection n'est pas publique" - ); - } - - if (collectionUserId) { - const userIsSharingCollection = await UsersModel.findById( - collectionUserId - ); - - if ( - !userIsSharingCollection || - !userIsSharingCollection.isPublicCollection - ) { - throw new ErrorEvent( - 401, - "Collection", - "Cette collection n'est pas publique" - ); - } - - userId = userIsSharingCollection._id; - } - - if (discogsIds) { - where.discogsId = { $in: discogsIds }; - } - if (discogsId) { - where.discogsId = Number(discogsId); - } - - const count = await WantListModel.count({ - User: userId, - ...where, - }); - - let params = { - sort: { - [sort]: order.toLowerCase() === "asc" ? 1 : -1, - }, - }; - - if (exportFormat === "json" && page && limit) { - const skip = (page - 1) * limit; - - params = { - ...params, - skip, - limit, - }; - } - - const rows = await WantListModel.find( - { - User: userId, - ...where, - }, - [], - params - ); - - switch (exportFormat) { - case "csv": - return Export.convertToCsv(rows); - case "xls": - return Export.convertToXls(rows); - case "xml": - return Export.convertToXml(rows); - case "musictopus": - return Export.convertToMusicTopus(rows); - case "json": - default: - return { - rows, - limit, - count, - }; - } - } - - /** - * Méthode permettant de récupérer le détails d'un album - * - * @return {Object} - */ - async getOne() { - const { itemId: _id } = this.req.params; - const { _id: User } = this.req.user; - const album = await WantListModel.findOne({ - _id, - User, - }); - - return { - ...album.toJSON(), - released: album.released - ? formatDate(album.released, "MM/dd/yyyy") - : null, - }; - } - - /** - * Méthode permettant de mettre à jour un album - * - * @return {Object} - */ - async patchOne() { - const { itemId: _id } = this.req.params; - const { _id: User } = this.req.user; - const query = { - _id, - User, - }; - const album = await WantListModel.findOne(query); - - if (!album) { - throw new ErrorEvent( - 404, - "Mise à jour", - "Impossible de trouver cet album" - ); - } - - const values = await getAlbumDetails(album.discogsId); - - await WantListModel.findOneAndUpdate(query, values, { new: true }); - - return this.getOne(); - } - - /** - * Méthode permettant de supprimer un élément d'une collection - * @return {Boolean} - */ - async deleteOne() { - const res = await WantListModel.findOneAndDelete({ - User: this.req.user._id, - _id: this.req.params.itemId, - }); - - if (res) { - return true; - } - - throw new ErrorEvent( - 404, - "Suppression", - "Impossible de trouver cet album" - ); - } - - async shareOne() { - const { message: status } = this.req.body; - const { itemId: _id } = this.req.params; - const { _id: User } = this.req.user; - const query = { - _id, - User, - }; - - const album = await WantListModel.findOne(query); - - if (!album) { - throw new ErrorEvent( - 404, - "Mise à jour", - "Impossible de trouver cet album" - ); - } - - const { mastodon: mastodonConfig } = this.req.user; - const { publish, token, url } = mastodonConfig; - - if (publish && url && token) { - const M = new Mastodon({ - access_token: token, - api_url: url, - }); - - const media_ids = []; - - if (album.images.length > 0) { - for (let i = 0; i < album.images.length; i += 1) { - if (media_ids.length === 4) { - break; - } - - const filename = `${v4()}.jpg`; - const file = `/tmp/${filename}`; - - // eslint-disable-next-line no-await-in-loop - const { data: buff } = await axios.get( - album.images[i].uri, - { - headers: { - "User-Agent": - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/117.0", - }, - responseType: "arraybuffer", - } - ); - - fs.writeFileSync(file, buff); - - // eslint-disable-next-line no-await-in-loop - const { data: media } = await M.post("media", { - file: fs.createReadStream(file), - }); - - const { id } = media; - - media_ids.push(id); - - fs.unlinkSync(file); - } - } - - await M.post("statuses", { status, media_ids }); - } else { - throw new ErrorEvent( - 406, - `Vous n'avez pas configuré vos options de partage sur votre compte` - ); - } - - return true; - } - - /** - * Méthode permettant de créer la page "ma-collection" - */ - async loadMyCollection() { - const artists = await getAllDistincts( - WantListModel, - "artists.name", - this.req.user._id - ); - const formats = await getAllDistincts( - WantListModel, - "formats.name", - this.req.user._id - ); - const years = await getAllDistincts( - WantListModel, - "year", - this.req.user._id - ); - const genres = await getAllDistincts( - WantListModel, - "genres", - this.req.user._id - ); - const styles = await getAllDistincts( - WantListModel, - "styles", - this.req.user._id - ); - - this.setPageContent("artists", artists); - this.setPageContent("formats", formats); - this.setPageContent("years", years); - this.setPageContent("genres", genres); - this.setPageContent("styles", styles); - this.setPageTitle("Ma collection"); - } - - /** - * Méthode permettant d'afficher le détails d'un album - */ - async loadItem() { - const item = await this.getOne(); - - this.setPageContent("item", item); - this.setPageTitle( - `Détails de l'album ${item.title} de ${item.artists_sort}` - ); - } - - /** - * Méthode permettant de choisir un album de manière aléatoire dans la collection d'un utilisateur - */ - async onAir() { - const { _id: User } = this.req.user; - const count = await WantListModel.count({ - User, - }); - - const items = await WantListModel.find( - { - User, - }, - [], - { - skip: Math.floor(Math.random() * (count + 1)), - limit: 1, - } - ); - - this.req.params.itemId = items[0]._id; - - await this.loadItem(); - } - - /** - * Méthode permettant d'afficher des statistiques au sujet de ma collection - */ - async statistics() { - const { _id: User } = this.req.user; - const top = {}; - const byGenres = {}; - const byStyles = {}; - const byFormats = {}; - const top10 = []; - let byStyles10 = []; - const max = this.colors.length - 1; - - const colorsCount = this.colors.length; - - const albums = await WantListModel.find({ - User, - artists: { $exists: true, $not: { $size: 0 } }, - }); - - for (let i = 0; i < albums.length; i += 1) { - const currentFormats = []; - const { artists, genres, styles, formats } = albums[i]; - - // INFO: On regroupe les artistes par nom pour en faire le top10 - for (let j = 0; j < artists.length; j += 1) { - const { name } = artists[j]; - if (!top[name]) { - top[name] = { - name, - count: 0, - }; - } - top[name].count += 1; - } - - // INFO: On regroupe les genres - for (let j = 0; j < genres.length; j += 1) { - const name = genres[j]; - if (!byGenres[name]) { - byGenres[name] = { - name, - count: 0, - color: this.colors[ - Object.keys(byGenres).length % colorsCount - ], - }; - } - - byGenres[name].count += 1; - } - - // INFO: On regroupe les styles - for (let j = 0; j < styles.length; j += 1) { - const name = styles[j]; - if (!byStyles[name]) { - byStyles[name] = { - name, - count: 0, - color: this.colors[ - Object.keys(byStyles).length % colorsCount - ], - }; - } - - byStyles[name].count += 1; - } - - // INFO: On regroupe les formats - for (let j = 0; j < formats.length; j += 1) { - const { name } = formats[j]; - // INFO: On évite qu'un album avec 2 vinyles soit compté 2x - if (!currentFormats.includes(name)) { - if (!byFormats[name]) { - byFormats[name] = { - name, - count: 0, - color: this.colors[ - Object.keys(byFormats).length % colorsCount - ], - }; - } - - byFormats[name].count += 1; - currentFormats.push(name); - } - } - } - - // INFO: On convertit le top en tableau - Object.keys(top).forEach((index) => { - top10.push(top[index]); - }); - - // INFO: On convertit les styles en tableau - Object.keys(byStyles).forEach((index) => { - byStyles10.push(byStyles[index]); - }); - - // INFO: On ordonne les artistes par quantité d'albums - top10.sort((a, b) => (a.count > b.count ? -1 : 1)); - - // INFO: On ordonne les styles par quantité - byStyles10.sort((a, b) => (a.count > b.count ? -1 : 1)); - const tmp = []; - - // INFO: On recupère le top N des styles et on mets le reste dans le label "autre" - for (let i = 0; i < byStyles10.length; i += 1) { - if (i < max) { - tmp.push({ - ...byStyles10[i], - color: this.colors[max - i], - }); - } else if (i === max) { - tmp.push({ - name: "Autre", - count: 0, - color: this.colors[0], - }); - tmp[max].count += byStyles10[i].count; - } else { - tmp[max].count += byStyles10[i].count; - } - } - byStyles10 = tmp; - - this.setPageTitle("Mes statistiques"); - this.setPageContent("top10", top10.splice(0, 10)); - this.setPageContent("byGenres", byGenres); - this.setPageContent("byStyles", byStyles10); - this.setPageContent("byFormats", byFormats); - } - - /** - * 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, - "Collection non partagée", - "Cet utilisateur ne souhaite pas partager sa collection" - ); - } - - const artists = await getAllDistincts( - WantListModel, - "artists.name", - userId - ); - const formats = await getAllDistincts( - WantListModel, - "formats.name", - userId - ); - const years = await getAllDistincts(WantListModel, "year", userId); - const genres = await getAllDistincts(WantListModel, "genres", userId); - const styles = await getAllDistincts(WantListModel, "styles", userId); - - this.setPageTitle(`Collection publique de ${user.username}`); - this.setPageContent("username", user.username); - this.setPageContent("artists", artists); - this.setPageContent("formats", formats); - this.setPageContent("years", years); - this.setPageContent("genres", genres); - this.setPageContent("styles", styles); - } -} - -export default Wantlist; diff --git a/src/models/users.js b/src/models/users.js index e0c8a5d..b8a047a 100644 --- a/src/models/users.js +++ b/src/models/users.js @@ -25,10 +25,6 @@ const UserSchema = new mongoose.Schema( }, hash: String, salt: String, - pagination: { - type: Number, - default: 16, - }, isPublicCollection: { type: Boolean, default: false, @@ -38,7 +34,6 @@ const UserSchema = new mongoose.Schema( token: String, url: String, message: String, - wantlist: String, }, }, { diff --git a/src/models/wantlist.js b/src/models/wantlist.js deleted file mode 100644 index 1f8b334..0000000 --- a/src/models/wantlist.js +++ /dev/null @@ -1,37 +0,0 @@ -import mongoose from "mongoose"; - -const { Schema } = mongoose; - -const WantListSchema = new mongoose.Schema( - { - User: { - type: Schema.Types.ObjectId, - ref: "Users", - }, - discogsId: Number, - year: Number, - released: Date, - uri: String, - artists: Array, - artists_sort: String, - labels: Array, - series: Array, - companies: Array, - formats: Array, - title: String, - country: String, - notes: String, - identifiers: Array, - videos: Array, - genres: Array, - styles: Array, - tracklist: Array, - extraartists: Array, - images: Array, - thumb: String, - thumbType: String, - }, - { timestamps: true } -); - -export default mongoose.model("WantList", WantListSchema); diff --git a/src/routes/api/v1/me.js b/src/routes/api/v1/me.js index d9e4da0..42c46b9 100644 --- a/src/routes/api/v1/me.js +++ b/src/routes/api/v1/me.js @@ -15,16 +15,6 @@ router const me = new Me(req); const data = await me.patchMe(); - return sendResponse(req, res, data); - } catch (err) { - return next(err); - } - }) - .delete(ensureLoggedIn("/connexion"), async (req, res, next) => { - try { - const me = new Me(req); - const data = await me.deleteMe(); - return sendResponse(req, res, data); } catch (err) { return next(err); diff --git a/src/routes/api/v1/wantlist.js b/src/routes/api/v1/wantlist.js deleted file mode 100644 index 82738b5..0000000 --- a/src/routes/api/v1/wantlist.js +++ /dev/null @@ -1,84 +0,0 @@ -import express from "express"; -import { ensureLoggedIn } from "connect-ensure-login"; - -import { sendResponse } from "../../../libs/format"; -import Albums from "../../../middleware/Wantlist"; - -// eslint-disable-next-line new-cap -const router = express.Router(); - -router - .route("/") - .get(async (req, res, next) => { - try { - const albums = new Albums(req, null); - const data = await albums.getAll(); - const { exportFormat = "json" } = req.query; - - switch (exportFormat) { - 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); - case "json": - default: - return sendResponse(req, res, data); - } - } catch (err) { - return next(err); - } - }) - .post(ensureLoggedIn("/connexion"), async (req, res, next) => { - try { - const data = await Albums.postAddOne(req); - - sendResponse(req, res, data); - } catch (err) { - next(err); - } - }); - -router - .route("/:itemId") - .patch(ensureLoggedIn("/connexion"), async (req, res, next) => { - try { - const albums = new Albums(req, null); - const data = await albums.patchOne(); - - sendResponse(req, res, data); - } catch (err) { - next(err); - } - }) - .delete(ensureLoggedIn("/connexion"), async (req, res, next) => { - try { - const albums = new Albums(req, null); - const data = await albums.deleteOne(); - - sendResponse(req, res, data); - } catch (err) { - next(err); - } - }); - -router - .route("/:itemId/share") - .post(ensureLoggedIn("/connexion"), async (req, res, next) => { - try { - const albums = new Albums(req, null); - const data = await albums.shareOne(); - - sendResponse(req, res, data); - } catch (err) { - next(err); - } - }); - -export default router; diff --git a/src/routes/index.js b/src/routes/index.js index 301f25e..faa4142 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -104,23 +104,8 @@ router try { const page = new Pages(req, "ajouter-un-album"); - page.setPageContent("action", "albums"); page.setPageTitle("Ajouter un album"); - render(res, page); - } catch (err) { - next(err); - } - }); -router - .route("/ajouter-a-ma-liste-de-souhaits") - .get(ensureLoggedIn("/connexion"), (req, res, next) => { - try { - const page = new Pages(req, "ajouter-un-album"); - - page.setPageContent("action", "wantlist"); - page.setPageTitle("Ajouter un album à ma liste de souhaits"); - render(res, page); } catch (err) { next(err); diff --git a/src/routes/ma-collection.js b/src/routes/ma-collection.js index f7a4084..1100bd9 100644 --- a/src/routes/ma-collection.js +++ b/src/routes/ma-collection.js @@ -38,23 +38,6 @@ router } }); -router - .route("/statistiques") - .get(ensureLoggedIn("/connexion"), async (req, res, next) => { - try { - const page = new Albums( - req, - "mon-compte/ma-collection/statistiques" - ); - - await page.statistics(); - - render(res, page); - } catch (err) { - next(err); - } - }); - router .route("/exporter") .get(ensureLoggedIn("/connexion"), async (req, res, next) => { diff --git a/src/routes/wantlist.js b/src/routes/wantlist.js deleted file mode 100644 index 6c5394d..0000000 --- a/src/routes/wantlist.js +++ /dev/null @@ -1,99 +0,0 @@ -import express from "express"; -import { ensureLoggedIn } from "connect-ensure-login"; - -import Albums from "../middleware/Wantlist"; - -import render from "../libs/format"; - -// eslint-disable-next-line new-cap -const router = express.Router(); - -router.route("/").get(ensureLoggedIn("/connexion"), async (req, res, next) => { - try { - const page = new Albums(req, "collection"); - - await page.loadMyCollection(); - - if (page.getPageContent("artists").length > 0) { - render(res, page); - } else { - res.redirect("/ajouter-a-ma-liste-de-souhaits"); - } - } catch (err) { - next(err); - } -}); - -router - .route("/on-air") - .get(ensureLoggedIn("/connexion"), async (req, res, next) => { - try { - const page = new Albums(req, "mon-compte/ma-collection/details"); - - await page.onAir(); - - render(res, page); - } catch (err) { - next(err); - } - }); - -router - .route("/statistiques") - .get(ensureLoggedIn("/connexion"), async (req, res, next) => { - try { - const page = new Albums( - req, - "mon-compte/ma-collection/statistiques" - ); - - await page.statistics(); - - render(res, page); - } catch (err) { - next(err); - } - }); - -router - .route("/exporter") - .get(ensureLoggedIn("/connexion"), async (req, res, next) => { - try { - const page = new Albums(req, "mon-compte/ma-collection/exporter"); - - page.setPageTitle("Exporter ma collection"); - - render(res, page); - } catch (err) { - next(err); - } - }); -router - .route("/importer") - .get(ensureLoggedIn("/connexion"), async (req, res, next) => { - try { - const page = new Albums(req, "mon-compte/ma-collection/importer"); - - page.setPageTitle("Importer une collection"); - - render(res, page); - } catch (err) { - next(err); - } - }); - -router - .route("/:itemId") - .get(ensureLoggedIn("/connexion"), async (req, res, next) => { - try { - const page = new Albums(req, "mon-compte/ma-collection/details"); - - await page.loadItem(); - - render(res, page); - } catch (err) { - next(err); - } - }); - -export default router; diff --git a/views/components/album.ejs b/views/components/album.ejs index 74d06f2..b834a4d 100644 --- a/views/components/album.ejs +++ b/views/components/album.ejs @@ -1,133 +1,133 @@
-
- -
-
-
-
- Genres -
- -
-
- Styles -
- - {{style}} - -
-
-
-
-
- Pays -
- {{item.country}} -
-
- Année -
- {{item.year}} -
-
- Date de sortie -
- {{item.released}} -
-
-
-
-
- Format -
    -
  • - {{format.name}} - - -
  • -
-
-
-
-
-
- Code barre -
    -
  1. - {{identifier.value}} ({{identifier.type}}) -
  2. -
- -
-
- Label -
    -
  1. - {{label.name}} {{label.catno}} -
  2. -
- Société -
    -
  1. - {{company.entity_type_name}} {{company.name}} -
  2. -
-
-
-
-
-
- Note -
-
-
-
-
-
- Vidéos -
- -
-
-
-
-
\ No newline at end of file +
+ +
+
+
+
+ Genres +
+ +
+
+ Styles +
+ + {{style}} + +
+
+
+
+
+ Pays +
+ {{item.country}} +
+
+ Année +
+ {{item.year}} +
+
+ Date de sortie +
+ {{item.released}} +
+
+
+
+
+ Format +
    +
  • + {{format.name}} + + +
  • +
+
+
+
+
+
+ Code barre +
    +
  1. + {{identifier.value}} ({{identifier.type}}) +
  2. +
+ +
+
+ Label +
    +
  1. + {{label.name}} {{label.catno}} +
  2. +
+ Société +
    +
  1. + {{company.entity_type_name}} {{company.name}} +
  2. +
+
+
+
+
+
+ Note +
+
+
+
+
+
+ Vidéos +
+ +
+
+
+
+ \ No newline at end of file diff --git a/views/components/filters/artist.ejs b/views/components/filters/artist.ejs index e0a919d..4d806a5 100644 --- a/views/components/filters/artist.ejs +++ b/views/components/filters/artist.ejs @@ -4,7 +4,7 @@ <% for (let i = 0; i < page.artists.length; i += 1 ) { - __append(``); + __append(``); } %> diff --git a/views/index.ejs b/views/index.ejs index 829a6cd..2fca1a8 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -16,9 +16,6 @@ - - - <% if ( config.matomoUrl ) { %> + - \ No newline at end of file + diff --git a/views/pages/ajouter-un-album.ejs b/views/pages/ajouter-un-album.ejs index a9a1c2d..f8f7c96 100644 --- a/views/pages/ajouter-un-album.ejs +++ b/views/pages/ajouter-un-album.ejs @@ -200,5 +200,4 @@ \ No newline at end of file diff --git a/views/pages/collection.ejs b/views/pages/collection.ejs index 317ba9b..8d18ab2 100644 --- a/views/pages/collection.ejs +++ b/views/pages/collection.ejs @@ -3,23 +3,19 @@ %>
- <% if (page.action === 'albums') { %> -

- <% if ( pageType === 'private' ) { - __append('Ma collection '); - } else { - __append(`Collection de ${page.username}`); - } %> -

- <% if ( pageType === 'private' ) { %> -
- - Voir ma collection partagée - -
- <% } %> - <% } else { %> -

Ma liste de souhaits

+

+ <% if ( pageType === 'private' ) { + __append('Ma collection '); + } else { + __append(`Collection de ${page.username}`); + } %> +

+ <% if ( pageType === 'private' ) { %> +
+ + Voir ma collection partagée + +
<% } %> <%- include('../components/filters/index') %> @@ -34,7 +30,7 @@
<% if ( pageType === 'private' ) { %> - {{ renderAlbumTitle(item) }} + {{ renderAlbumTitle(item) }} <% } else { %> {{ item.artists_sort}} - {{ item.title }} @@ -43,7 +39,7 @@
<% if ( pageType === 'private' ) { %> - + <% } else { %> <% } %> @@ -151,7 +147,6 @@ diff --git a/views/pages/mon-compte/ma-collection/details.ejs b/views/pages/mon-compte/ma-collection/details.ejs index df52758..f99eed8 100644 --- a/views/pages/mon-compte/ma-collection/details.ejs +++ b/views/pages/mon-compte/ma-collection/details.ejs @@ -2,7 +2,7 @@

- {{item.title}} @@ -79,10 +79,6 @@
  • {format}, exemple : Cassette
  • {year}, exemple: 1984
  • {video}, exemple : https://www.youtube.com/watch?v=Qx0s8OqgBIw
  • -
  • {genres}, exemple : Rock
  • -
  • {#genres}, exemple : #rock
  • -
  • {styles}, exemple : Hard Rock, Heavy Metal
  • -
  • {#styles}, exemple : #hardRock, #heavyMetal
  • @@ -98,6 +94,5 @@ \ No newline at end of file diff --git a/views/pages/mon-compte/ma-collection/exporter.ejs b/views/pages/mon-compte/ma-collection/exporter.ejs index 09a0ca1..28cc559 100644 --- a/views/pages/mon-compte/ma-collection/exporter.ejs +++ b/views/pages/mon-compte/ma-collection/exporter.ejs @@ -1,9 +1,5 @@
    - <% if (page.action === 'albums') { %> -

    Exporter ma collection

    - <% } else { %> -

    Exporter ma liste de souhaits

    - <% } %> +

    Exporter ma collection

    Les formats CSV et Excel sont facilement lisiblent par un humain. Dans ces 2 formats vous trouverez seulement les informations principales de vos albums, à savoir :

    @@ -48,8 +44,4 @@ Exporter -
    - - \ No newline at end of file +
    \ No newline at end of file diff --git a/views/pages/mon-compte/ma-collection/importer.ejs b/views/pages/mon-compte/ma-collection/importer.ejs index 1383d16..f1a8b49 100644 --- a/views/pages/mon-compte/ma-collection/importer.ejs +++ b/views/pages/mon-compte/ma-collection/importer.ejs @@ -1,11 +1,7 @@
    - <% if (page.action === 'albums') { %> -

    Importer une collection

    - <% } else { %> -

    Importer une liste de souhaits

    - <% } %> +

    Importer une collection

    - Il est actuellement possible d'importer <%= page.action === 'albums' ? "une collection" : "une liste de souhaits" %> provenant de discogs. + Il est actuellement possible d'importer une collection provenant de discogs.
    Vous devez dans un premier temps vous rendre sur la page Exporter de discogs.
    @@ -44,8 +40,4 @@ Importatation terminée -

    - - \ No newline at end of file + \ No newline at end of file diff --git a/views/pages/mon-compte/ma-collection/statistiques.ejs b/views/pages/mon-compte/ma-collection/statistiques.ejs deleted file mode 100644 index 605c1b7..0000000 --- a/views/pages/mon-compte/ma-collection/statistiques.ejs +++ /dev/null @@ -1,238 +0,0 @@ -
    -

    - Mes statistiques -

    - -
    -
    -

    Mon top 10

    - - - - - - - - - - <% for ( let i = 0 ; i < page.top10.length ; i += 1 ) { %> - - - - - - <% } %> - -
    ArtisteAlbums
    <%= i+1 %><%= page.top10[i].name %><%= page.top10[i].count %>
    -
    - -
    -

    Genres

    - -
    - -
    -

    Styles

    - -
    - -
    -

    Formats

    - -
    - -
    - -
    -

    <%= page.currentYear.year %> (<%= page.currentYear.total %> ajout<%= page.currentYear.total > 1 ? 's' : '' %>)

    -

    Genres

    - -

    Styles

    - -

    Formats

    - -
    - -
    -

    <%= page.lastYear.year %> (<%= page.lastYear.total %> ajout<%= page.lastYear.total > 1 ? 's' : '' %>)

    -

    Genres

    - -

    Styles

    - -

    Formats

    - -
    -
    -
    - - diff --git a/views/pages/nous-contacter.ejs b/views/pages/nous-contacter.ejs index 39b1c91..f179135 100644 --- a/views/pages/nous-contacter.ejs +++ b/views/pages/nous-contacter.ejs @@ -1,4 +1,4 @@ -
    +

    Nous contacter

    id="contact" method="POST" action="https://formspree.io/f/<%= config.formspreeId %>" <% } %>>