From 748edc9cc4b0c1e5a6d7e814a89536eff8832a3d Mon Sep 17 00:00:00 2001 From: dbroqua Date: Fri, 28 Oct 2022 21:55:31 +0200 Subject: [PATCH 01/16] #63 - Suppression d'un album --- views/pages/mon-compte/ma-collection/details.ejs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/pages/mon-compte/ma-collection/details.ejs b/views/pages/mon-compte/ma-collection/details.ejs index 41c0b24..da1e1a3 100644 --- a/views/pages/mon-compte/ma-collection/details.ejs +++ b/views/pages/mon-compte/ma-collection/details.ejs @@ -319,7 +319,7 @@ deleteItem() { axios.delete(`/api/v1/albums/${this.item._id}`) .then( () => { - return locatiom.href = "/ma-collection"; + window.location.href = "/ma-collection"; }) .catch((err) => { showToastr(err.response?.data?.message || "Impossible de supprimer cet album"); -- 2.39.2 From eac7c1aa84a55bf69a2499812cdc1ad122ffc578 Mon Sep 17 00:00:00 2001 From: dbroqua Date: Fri, 28 Oct 2022 22:01:36 +0200 Subject: [PATCH 02/16] #65 - Afficher les notes discogs d'un album --- views/pages/mon-compte/ma-collection/details.ejs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/views/pages/mon-compte/ma-collection/details.ejs b/views/pages/mon-compte/ma-collection/details.ejs index da1e1a3..a505509 100644 --- a/views/pages/mon-compte/ma-collection/details.ejs +++ b/views/pages/mon-compte/ma-collection/details.ejs @@ -120,14 +120,13 @@ - +
-- 2.39.2 From a74c67e241597eee0b3dcd041974201d712d32df Mon Sep 17 00:00:00 2001 From: dbroqua Date: Fri, 28 Oct 2022 22:06:56 +0200 Subject: [PATCH 03/16] #64 - Depuis un album pouvoir voir tous les albums de cet artiste --- views/pages/mon-compte/ma-collection/details.ejs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/views/pages/mon-compte/ma-collection/details.ejs b/views/pages/mon-compte/ma-collection/details.ejs index a505509..8f5b0ef 100644 --- a/views/pages/mon-compte/ma-collection/details.ejs +++ b/views/pages/mon-compte/ma-collection/details.ejs @@ -1,7 +1,7 @@

- {{item.artists_sort}} - {{item.title}} + {{item.artists_sort}} - {{item.title}}

@@ -327,6 +327,9 @@ this.toggleModal(); }); }, + goToArtist() { + return ""; + }, }, }).mount('#app'); \ No newline at end of file -- 2.39.2 From 8f9e9025872e33077ed918cc74258a4193f6e6f8 Mon Sep 17 00:00:00 2001 From: dbroqua Date: Fri, 28 Oct 2022 22:40:02 +0200 Subject: [PATCH 04/16] #66 - Compiler le JS avant de l'envoyer au client --- .gitignore | 2 +- gulpfile.js | 46 +++++ javascripts/ajouter-un-album.js | 171 ++++++++++++++++ javascripts/collection.js | 133 +++++++++++++ javascripts/conctact.js | 42 ++++ {public/js => javascripts}/main.js | 9 +- javascripts/mon-compte/index.js | 26 +++ .../mon-compte/ma-collection/details.js | 158 +++++++++++++++ .../mon-compte/ma-collection/exporter.js | 18 ++ javascripts/mon-compte/ma-collection/index.js | 178 +++++++++++++++++ package.json | 11 +- src/app.js | 8 - views/index.ejs | 5 +- views/pages/ajouter-un-album.ejs | 178 +---------------- views/pages/collection.ejs | 139 +------------ views/pages/mon-compte/index.ejs | 28 +-- .../mon-compte/ma-collection/details.ejs | 159 +-------------- .../mon-compte/ma-collection/exporter.ejs | 25 +-- .../pages/mon-compte/ma-collection/index.ejs | 186 +----------------- views/pages/nous-contacter.ejs | 49 +---- 20 files changed, 809 insertions(+), 762 deletions(-) create mode 100644 gulpfile.js create mode 100644 javascripts/ajouter-un-album.js create mode 100644 javascripts/collection.js create mode 100644 javascripts/conctact.js rename {public/js => javascripts}/main.js (97%) create mode 100644 javascripts/mon-compte/index.js create mode 100644 javascripts/mon-compte/ma-collection/details.js create mode 100644 javascripts/mon-compte/ma-collection/exporter.js create mode 100644 javascripts/mon-compte/ma-collection/index.js diff --git a/.gitignore b/.gitignore index a8dcba6..3054b59 100644 --- a/.gitignore +++ b/.gitignore @@ -121,6 +121,6 @@ dist dist yarn.lock public/css -public/css +public/js docker-compose.yml dump diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..8e76f38 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,46 @@ +const { parallel, src, dest } = require("gulp"); + +const sourcemaps = require("gulp-sourcemaps"); +const concat = require("gulp-concat"); + +const gulp = require("gulp"); +const uglify = require("gulp-uglify"); +const babel = require("gulp-babel"); + +const sourceJs = "javascripts/**/*.js"; +const sourceRemoteJS = [ + "./node_modules/vue/dist/vue.global.prod.js", + "./node_modules/axios/dist/axios.min.js", +]; + +const destination = "public/js"; + +// TASKS ---------------------------------------------------------------------- + +const compileJs = function () { + return gulp + .src(sourceJs) + .pipe(sourcemaps.init()) + .pipe(concat("main.js")) + .pipe( + babel({ + presets: ["@babel/env"], + }) + ) + .pipe(uglify()) + .pipe(sourcemaps.write(".")) + .pipe(gulp.dest(destination)); +}; +const compileRemoteJs = function () { + return gulp + .src(sourceRemoteJS) + .pipe(sourcemaps.init()) + .pipe(concat("libs.js")) + .pipe(sourcemaps.write(".")) + .pipe(gulp.dest(destination)); +}; +// ---------------------------------------------------------------------------- + +// COMMANDS ------------------------------------------------------------------- +exports.default = parallel(compileJs, compileRemoteJs); +// ---------------------------------------------------------------------------- diff --git a/javascripts/ajouter-un-album.js b/javascripts/ajouter-un-album.js new file mode 100644 index 0000000..d46d5d4 --- /dev/null +++ b/javascripts/ajouter-un-album.js @@ -0,0 +1,171 @@ +Vue.createApp({ + data() { + return { + q: '', + year: '', + country: '', + format: '', + loading: false, + items: [], + details: {}, + modalIsVisible: false, + formats: [ + 'Vinyl', + 'Acetate', + 'Flexi-disc', + 'Lathe Cut', + 'Mighty Tiny', + 'Shellac', + 'Sopic', + 'Pathé Disc', + 'Edison Disc', + 'Cylinder', + 'CD', + 'CDr', + 'CDV', + 'DVD', + 'DVDr', + 'HD DVD', + 'HD DVD-R', + 'Blu-ray', + 'Blu-ray-R', + 'Ultra HD Blu-ray', + 'SACD', + '4-Track Cartridge', + '8-Track Cartridge', + 'Cassette', + 'DC-International', + 'Elcaset', + 'PlayTape', + 'RCA Tape Cartridge', + 'DAT', + 'DCC', + 'Microcassette', + 'NT Cassette', + 'Pocket Rocker', + 'Revere Magnetic Stereo Tape Ca', + 'Tefifon', + 'Reel-To-Reel', + 'Sabamobil', + 'Betacam', + 'Betacam SP', + 'Betamax', + 'Cartrivision', + 'MiniDV', + 'Super VHS', + 'U-matic', + 'VHS', + 'Video 2000', + 'Video8', + 'Film Reel', + 'HitClips', + 'Laserdisc', + 'SelectaVision', + 'VHD', + 'Wire Recording', + 'Minidisc', + 'MVD', + 'UMD', + 'Floppy Disk', + 'File', + 'Memory Stick', + 'Hybrid', + 'All Media', + 'Box Set', + ] + } + }, + methods: { + search(event) { + event.preventDefault(); + + if ( this.loading ) { + return false; + } + + this.loading = true; + let url = `/api/v1/search?q=${this.q}`; + + if ( this.year ) { + url += `&year=${this.year}`; + } + if ( this.country ) { + url += `&country=${this.country}`; + } + if ( this.format ) { + url += `&format=${this.format}`; + } + + axios.get(url) + .then( response => { + const { + results, + } = response.data; + let items = []; + + for (let i = 0 ; i < results.length ; i += 1 ) { + const { + id, + title, + thumb, + year, + country, + format, + genre, + style, + } = results[i]; + items.push({ + id, + title, + thumb, + year, + country, + format, + genre, + style, + }); + } + + this.items = items; + }) + .catch((err) => { + showToastr(err.response?.data?.message || "Aucun résultat trouvé :/"); + }) + .finally(() => { + this.loading = false; + }); + }, + toggleModal() { + this.modalIsVisible = !this.modalIsVisible; + }, + loadDetails(discogsId) { + axios.get(`/api/v1/search/${discogsId}`) + .then( response => { + const { + data, + } = response; + + this.details = data; + this.toggleModal(); + }) + .catch((err) => { + showToastr(err.response?.data?.message || "Impossible de charger les détails de cet album"); + }) + .finally(() => { + this.loading = false; + }); + }, + add() { + axios.post('/api/v1/albums', this.details) + .then(() => { + window.location.href = '/ma-collection'; + }) + .catch((err) => { + showToastr(err.response?.data?.message || "Impossible d'ajouter cet album pour le moment…"); + }); + }, + orderedItems(items) { + return items.sort(); + } + } +}).mount('#ajouter-album'); \ No newline at end of file diff --git a/javascripts/collection.js b/javascripts/collection.js new file mode 100644 index 0000000..c3b3561 --- /dev/null +++ b/javascripts/collection.js @@ -0,0 +1,133 @@ +if ( typeof userId !== 'undefined' ) { + Vue.createApp({ + data() { + return { + loading: false, + moreFilters: false, + items: [], + total: 0, + page: 1, + totalPages: 1, + limit: 16, + artist: '', + format: '', + year: '', + genre: '', + style: '', + sortOrder: 'artists_sort-asc', + sort: 'artists_sort', + order: 'asc', + userId, + } + }, + created() { + this.fetch(); + }, + methods: { + fetch() { + this.loading = true; + this.total = 0; + + const queryString = window.location.search; + const urlParams = new URLSearchParams(queryString); + const entries = urlParams.entries(); + + for(const entry of entries) { + switch(entry[0]) { + case 'artists_sort': + this.artist = entry[1]; + break; + default: + this[entry[0]] = entry[1]; + } + } + + let url = `/api/v1/albums?userId=${this.userId}&page=${this.page}&limit=${this.limit}&sort=${this.sort}&order=${this.order}`; + if ( this.artist ) { + url += `&artists_sort=${this.artist.replace('&', '%26')}`; + } + if ( this.format ) { + url += `&format=${this.format.replace('&', '%26')}`; + } + if ( this.year ) { + url += `&year=${this.year}`; + } + if ( this.genre ) { + url += `&genre=${this.genre.replace('&', '%26')}`; + } + if ( this.style ) { + url += `&style=${this.style.replace('&', '%26')}`; + } + + axios.get(url) + .then( response => { + this.items = response.data.rows; + this.total = response.data.count || 0; + this.totalPages = parseInt(response.data.count / this.limit) + (response.data.count % this.limit > 0 ? 1 : 0); + + }) + .catch((err) => { + showToastr(err.response?.data?.message || "Impossible de charger cette collection"); + }) + .finally(() => { + this.loading = false; + }); + }, + changeUrl() { + let url = `?page=${this.page}&limit=${this.limit}&sort=${this.sort}&order=${this.order}`; + if ( this.artist ) { + url += `&artists_sort=${this.artist.replace('&', '%26')}`; + } + if ( this.format ) { + url += `&format=${this.format.replace('&', '%26')}`; + } + if ( this.year ) { + url += `&year=${this.year}`; + } + if ( this.genre ) { + url += `&genre=${this.genre.replace('&', '%26')}`; + } + if ( this.style ) { + url += `&style=${this.style.replace('&', '%26')}`; + } + + location.href = url; + }, + next(event) { + event.preventDefault(); + + this.page += 1; + + this.changeUrl(); + }, + previous(event) { + event.preventDefault(); + + this.page -= 1; + + this.changeUrl(); + }, + goTo(page) { + this.page = page; + + this.changeUrl(); + }, + changeSort() { + const [sort,order] = this.sortOrder.split('-'); + this.sort = sort; + this.order = order; + this.page = 1; + + this.changeUrl(); + }, + changeFilter() { + this.page = 1; + + this.changeUrl(); + }, + showMoreFilters() { + this.moreFilters = !this.moreFilters; + } + } + }).mount('#collection-publique'); +} \ No newline at end of file diff --git a/javascripts/conctact.js b/javascripts/conctact.js new file mode 100644 index 0000000..51ed1cb --- /dev/null +++ b/javascripts/conctact.js @@ -0,0 +1,42 @@ +if ( typeof contactMethod !== 'undefined' && contactMethod === 'smtp' ) { + Vue.createApp({ + data() { + return { + email: '', + name: '', + message: '', + captcha: '', + loading: false, + } + }, + methods: { + send(event) { + event.preventDefault(); + + if ( this.loading ) { + return false; + } + + this.loading = true; + + const { + email, + message, + name, + captcha, + } = this; + + axios.post('/api/v1/contact', {email, name, message, captcha}) + .then( () => { + showToastr("Message correctement envoyé", true); + }) + .catch((err) => { + showToastr(err.response?.data?.message || "Impossible d'envoyer votre message", false); + }) + .finally(() => { + this.loading = false; + }) + }, + }, + }).mount('#contact'); +} \ No newline at end of file diff --git a/public/js/main.js b/javascripts/main.js similarity index 97% rename from public/js/main.js rename to javascripts/main.js index f203a63..0b0592e 100644 --- a/public/js/main.js +++ b/javascripts/main.js @@ -1,8 +1,13 @@ -/** +const { + protocol, + host +} = window.location; + + /** * Fonction permettant d'afficher un message dans un toastr * @param {String} message */ - function showToastr(message, success = false) { +function showToastr(message, success = false) { let x = document.getElementById("toastr"); if ( message ) { x.getElementsByTagName("SPAN")[0].innerHTML = message; diff --git a/javascripts/mon-compte/index.js b/javascripts/mon-compte/index.js new file mode 100644 index 0000000..ccc1d02 --- /dev/null +++ b/javascripts/mon-compte/index.js @@ -0,0 +1,26 @@ +if ( typeof email !== 'undefined' && typeof username !== 'undefined' ) { + Vue.createApp({ + data() { + return { + email, + username, + oldPassword: '', + password: '', + passwordConfirm: '', + loading: false, + } + }, + methods: { + async updateProfil(event) { + // try { + // if ( this.password !== this.passwordConfirm ) { + // throw "La confirnation du mot de passe ne correspond pas"; + // } + // } catch(err) { + // event.preventDefault(); + // showToastr(err); + // } + }, + } + }).mount('#mon-compte'); +} \ No newline at end of file diff --git a/javascripts/mon-compte/ma-collection/details.js b/javascripts/mon-compte/ma-collection/details.js new file mode 100644 index 0000000..26f069f --- /dev/null +++ b/javascripts/mon-compte/ma-collection/details.js @@ -0,0 +1,158 @@ +if ( typeof item !== 'undefined' ) { + Vue.createApp({ + data() { + return { + item, + tracklist: [], + identifiers: [], + modalIsVisible: false, + identifiersMode: 'preview', + identifiersPreviewLength: 16, + preview: null, + index: null, + showModalDelete: false, + } + }, + created() { + this.setTrackList(); + this.setIdentifiers(); + + window.addEventListener("keydown", this.changeImage); + }, + destroyed() { + window.removeEventListener('keydown', this.changeImage); + }, + methods: { + setIdentifiers() { + this.identifiers = []; + + let max = this.identifiersMode == 'preview' && this.item.identifiers.length > this.identifiersPreviewLength ? this.identifiersPreviewLength : this.item.identifiers.length; + + for ( let i = 0 ; i < max ; i += 1 ) { + this.identifiers.push(this.item.identifiers[i]); + } + }, + setTrackList() { + let subTrack = { + type: null, + title: null, + tracks: [], + }; + for (let i = 0 ; i < this.item.tracklist.length ; i += 1 ) { + const { + type_, + title, + position, + duration, + extraartists, + } = this.item.tracklist[i]; + + if ( type_ === 'heading' ) { + if ( subTrack.type ) { + this.tracklist.push(subTrack); + subTrack = { + type: null, + title: null, + tracks: [], + }; + } + + subTrack.type = type_; + subTrack.title = title; + } else { + subTrack.tracks.push({ + title, + position, + duration, + extraartists + }); + } + } + this.tracklist.push(subTrack); + }, + setImage() { + this.preview = this.item.images[this.index].uri; + }, + showGallery(event) { + const item = event.target.tagName === 'IMG' ? event.target.parentElement : event.target; + + const { + index, + } = item.dataset; + + this.index = Number(index); + this.modalIsVisible = true; + + this.setImage(); + }, + toggleModal() { + this.modalIsVisible = !this.modalIsVisible; + }, + previous() { + this.index = this.index > 0 ? this.index - 1 : this.item.images.length -1; + this.setImage(); + }, + next() { + this.index = (this.index +1) === this.item.images.length ? 0 : this.index + 1; + this.setImage(); + }, + changeImage(event) { + const direction = event.code; + + if ( this.modalIsVisible && ['ArrowRight', 'ArrowLeft', 'Escape'].indexOf(direction) !== -1 ) { + switch (direction) { + case 'ArrowRight': + return this.next(); + case 'ArrowLeft': + return this.previous(); + default: + this.modalIsVisible = false; + return true; + } + } + }, + showAllIdentifiers() { + this.identifiersMode = 'all'; + this.setIdentifiers(); + }, + showLessIdentifiers() { + this.identifiersMode = 'preview'; + this.setIdentifiers(); + + document.querySelector('#identifiers').scrollIntoView({ behavior: 'smooth' }); + }, + showConfirmDelete() { + this.toggleModal(); + }, + toggleModal() { + this.showModalDelete = !this.showModalDelete; + }, + updateItem() { + showToastr("Mise à jour en cours…", true); + axios.patch(`/api/v1/albums/${this.item._id}`) + .then( (res) => { + showToastr("Mise à jour réalisée avec succès", true); + this.item = res.data; + }) + .catch((err) => { + showToastr(err.response?.data?.message || "Impossible de mettre à jour cet album", false); + }); + }, + deleteItem() { + axios.delete(`/api/v1/albums/${this.item._id}`) + .then( () => { + window.location.href = "/ma-collection"; + }) + .catch((err) => { + showToastr(err.response?.data?.message || "Impossible de supprimer cet album"); + }) + .finally(() => { + this.toggleModal(); + }); + }, + goToArtist() { + return ""; + }, + }, + }).mount('#ma-collection-details'); +} \ No newline at end of file diff --git a/javascripts/mon-compte/ma-collection/exporter.js b/javascripts/mon-compte/ma-collection/exporter.js new file mode 100644 index 0000000..f5dcbcb --- /dev/null +++ b/javascripts/mon-compte/ma-collection/exporter.js @@ -0,0 +1,18 @@ +Vue.createApp({ + data() { + return { + format: 'xml', + } + }, + created() { + }, + destroyed() { + }, + methods: { + exportCollection(event) { + event.preventDefault(); + + window.open(`/api/v1/albums?exportFormat=${this.format}`, '_blank'); + } + }, +}).mount('#exporter'); \ No newline at end of file diff --git a/javascripts/mon-compte/ma-collection/index.js b/javascripts/mon-compte/ma-collection/index.js new file mode 100644 index 0000000..7e2bdf5 --- /dev/null +++ b/javascripts/mon-compte/ma-collection/index.js @@ -0,0 +1,178 @@ +if ( typeof isPublicCollection !== 'undefined' ) { + Vue.createApp({ + data() { + return { + loading: false, + moreFilters: false, + items: [], + total: 0, + page: 1, + totalPages: 1, + limit: 16, + artist: '', + format: '', + year: '', + genre: '', + style: '', + sortOrder: 'artists_sort-asc', + sort: 'artists_sort', + order: 'asc', + itemId: null, + showModalDelete: false, + showModalShare: false, + shareLink: `${protocol}//${host}/collection/<%= user._id %>`, + isPublicCollection, + } + }, + created() { + this.fetch(); + }, + methods: { + fetch() { + this.loading = true; + this.total = 0; + + const queryString = window.location.search; + const urlParams = new URLSearchParams(queryString); + const entries = urlParams.entries(); + + for(const entry of entries) { + switch(entry[0]) { + case 'artists_sort': + this.artist = entry[1]; + break; + default: + this[entry[0]] = entry[1]; + } + } + + let url = `/api/v1/albums?page=${this.page}&limit=${this.limit}&sort=${this.sort}&order=${this.order}`; + if ( this.artist ) { + url += `&artists_sort=${this.artist.replace('&', '%26')}`; + } + if ( this.format ) { + url += `&format=${this.format.replace('&', '%26')}`; + } + if ( this.year ) { + url += `&year=${this.year}`; + } + if ( this.genre ) { + url += `&genre=${this.genre.replace('&', '%26')}`; + } + if ( this.style ) { + url += `&style=${this.style.replace('&', '%26')}`; + } + + axios.get(url) + .then( response => { + this.items = response.data.rows; + this.total = response.data.count || 0; + this.totalPages = parseInt(response.data.count / this.limit) + (response.data.count % this.limit > 0 ? 1 : 0); + }) + .catch((err) => { + showToastr(err.response?.data?.message || "Impossible de charger votre collection"); + }) + .finally(() => { + this.loading = false; + }); + }, + changeUrl() { + let url = `?page=${this.page}&limit=${this.limit}&sort=${this.sort}&order=${this.order}`; + if ( this.artist ) { + url += `&artists_sort=${this.artist.replace('&', '%26')}`; + } + if ( this.format ) { + url += `&format=${this.format.replace('&', '%26')}`; + } + if ( this.year ) { + url += `&year=${this.year}`; + } + if ( this.genre ) { + url += `&genre=${this.genre.replace('&', '%26')}`; + } + if ( this.style ) { + url += `&style=${this.style.replace('&', '%26')}`; + } + + location.href = url; + }, + next(event) { + event.preventDefault(); + + this.page += 1; + + this.changeUrl(); + }, + previous(event) { + event.preventDefault(); + + this.page -= 1; + + this.changeUrl(); + }, + goTo(page) { + this.page = page; + + this.changeUrl(); + }, + changeSort() { + const [sort,order] = this.sortOrder.split('-'); + this.sort = sort; + this.order = order; + this.page = 1; + + this.changeUrl(); + }, + changeFilter() { + this.page = 1; + + this.changeUrl(); + }, + showMoreFilters() { + this.moreFilters = !this.moreFilters; + }, + toggleModal() { + this.showModalDelete = !this.showModalDelete; + }, + toggleModalShare() { + this.showModalShare = !this.showModalShare; + }, + showConfirmDelete(itemId) { + this.itemId = itemId; + this.toggleModal(); + }, + deleteItem() { + axios.delete(`/api/v1/albums/${this.itemId}`) + .then( () => { + this.fetch(); + }) + .catch((err) => { + showToastr(err.response?.data?.message || "Impossible de supprimer cet album"); + }) + .finally(() => { + this.toggleModal(); + }); + }, + shareCollection() { + axios.patch(`/api/v1/me`, { + isPublicCollection: !this.isPublicCollection, + }) + .then( (res) => { + this.isPublicCollection = res.data.isPublicCollection; + + if ( this.isPublicCollection ) { + showToastr("Votre collection est désormais publique", true); + } else { + showToastr("Votre collection n'est plus partagée", true); + } + }) + .catch((err) => { + showToastr(err.response?.data?.message || "Impossible de supprimer cet album"); + }) + .finally(() => { + this.toggleModalShare(); + }); + }, + } + }).mount('#ma-collection'); +} \ No newline at end of file diff --git a/package.json b/package.json index 2ee4492..b3dffed 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,10 @@ "description": "Simple application to manage your CD/Vinyl collection", "scripts": { "start": "node ./dist/bin/www", - "run:all": "npm-run-all build sass start", + "run:all": "npm-run-all build sass uglify start", "watch": "nodemon -e js,scss", "sass": "npx sass sass/index.scss public/css/main.css -s compressed --color", + "uglify": "npx gulp", "prebuild": "rimraf dist", "build": "babel ./src --out-dir dist --copy-files", "test": "jest", @@ -55,6 +56,11 @@ "excel4node": "^1.7.2", "express": "^4.17.2", "express-session": "^1.17.2", + "gulp": "^4.0.2", + "gulp-babel": "^8.0.0", + "gulp-concat": "^2.6.1", + "gulp-sourcemaps": "^3.0.0", + "gulp-uglify": "^3.0.2", "joi": "^17.6.0", "knacss": "^8.0.4", "mongoose": "^6.2.1", @@ -75,7 +81,8 @@ "exec": "yarn run:all", "watch": [ "src/*", - "sass/*" + "sass/*", + "javascripts/*" ], "ignore": [ "**/__tests__/**", diff --git a/src/app.js b/src/app.js index 7c40a27..6fa4688 100644 --- a/src/app.js +++ b/src/app.js @@ -75,14 +75,6 @@ app.set("views", path.join(__dirname, "../views")); app.set("view engine", "ejs"); app.use(express.static(path.join(__dirname, "../public"))); -app.use( - "/libs/vue", - express.static(path.join(__dirname, "../node_modules/vue/dist")) -); -app.use( - "/libs/axios", - express.static(path.join(__dirname, "../node_modules/axios/dist")) -); app.use("/", indexRouter); app.use("/mon-compte", monCompteRouter); diff --git a/views/index.ejs b/views/index.ejs index 2386a83..a310984 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -16,9 +16,8 @@ - - - + + <% if ( config.matomoUrl ) { %> diff --git a/views/pages/ajouter-un-album.ejs b/views/pages/ajouter-un-album.ejs index a7306ff..f32ea67 100644 --- a/views/pages/ajouter-un-album.ejs +++ b/views/pages/ajouter-un-album.ejs @@ -1,4 +1,4 @@ -
+

Ajouter un album

@@ -169,178 +169,4 @@
- - - + \ No newline at end of file diff --git a/views/pages/collection.ejs b/views/pages/collection.ejs index 9960983..3272d8b 100644 --- a/views/pages/collection.ejs +++ b/views/pages/collection.ejs @@ -1,4 +1,4 @@ -
+

Collection de <%= page.username %>

@@ -146,140 +146,5 @@
diff --git a/views/pages/mon-compte/index.ejs b/views/pages/mon-compte/index.ejs index d8f7f6a..af7b634 100644 --- a/views/pages/mon-compte/index.ejs +++ b/views/pages/mon-compte/index.ejs @@ -1,4 +1,4 @@ -
+

Mon compte

@@ -72,28 +72,6 @@
diff --git a/views/pages/mon-compte/ma-collection/details.ejs b/views/pages/mon-compte/ma-collection/details.ejs index 8f5b0ef..e8615b4 100644 --- a/views/pages/mon-compte/ma-collection/details.ejs +++ b/views/pages/mon-compte/ma-collection/details.ejs @@ -1,4 +1,4 @@ -
+

{{item.artists_sort}} - {{item.title}} @@ -176,160 +176,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 13e3f98..28cc559 100644 --- a/views/pages/mon-compte/ma-collection/exporter.ejs +++ b/views/pages/mon-compte/ma-collection/exporter.ejs @@ -1,4 +1,4 @@ -
+

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 : @@ -44,25 +44,4 @@ Exporter -

- - \ No newline at end of file +
\ No newline at end of file diff --git a/views/pages/mon-compte/ma-collection/index.ejs b/views/pages/mon-compte/ma-collection/index.ejs index fb67cd3..38993c8 100644 --- a/views/pages/mon-compte/ma-collection/index.ejs +++ b/views/pages/mon-compte/ma-collection/index.ejs @@ -1,4 +1,4 @@ -
+

Ma collection @@ -196,185 +196,5 @@

+ const isPublicCollection = <%= user.isPublicCollection ? 'true' : 'false' %>; + \ No newline at end of file diff --git a/views/pages/nous-contacter.ejs b/views/pages/nous-contacter.ejs index 276b6f4..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 %>" <% } %>>
@@ -34,47 +34,6 @@
-<% if (config.mailMethod === 'smtp' ) { %> - -<% } %> \ No newline at end of file + \ No newline at end of file -- 2.39.2 From 980586d8ebc308d5a373f80788559861391cc580 Mon Sep 17 00:00:00 2001 From: dbroqua Date: Fri, 28 Oct 2022 22:45:38 +0200 Subject: [PATCH 05/16] Correction mineure sur le refresh d'un album --- javascripts/mon-compte/ma-collection/details.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/javascripts/mon-compte/ma-collection/details.js b/javascripts/mon-compte/ma-collection/details.js index 26f069f..3f63290 100644 --- a/javascripts/mon-compte/ma-collection/details.js +++ b/javascripts/mon-compte/ma-collection/details.js @@ -133,6 +133,10 @@ if ( typeof item !== 'undefined' ) { .then( (res) => { showToastr("Mise à jour réalisée avec succès", true); this.item = res.data; + + this.setTrackList(); + this.setIdentifiers(); + this.showLessIdentifiers(); }) .catch((err) => { showToastr(err.response?.data?.message || "Impossible de mettre à jour cet album", false); -- 2.39.2 From e01f01337c615a448b192281abc26365fe21c05d Mon Sep 17 00:00:00 2001 From: dbroqua Date: Fri, 28 Oct 2022 22:56:04 +0200 Subject: [PATCH 06/16] Lint --- .eslintrc.js | 73 ++++--- javascripts/ajouter-un-album.js | 192 +++++++++--------- javascripts/collection.js | 96 +++++---- javascripts/conctact.js | 39 ++-- javascripts/main.js | 108 +++++----- javascripts/mon-compte/index.js | 19 +- .../mon-compte/ma-collection/details.js | 146 +++++++------ .../mon-compte/ma-collection/exporter.js | 16 +- javascripts/mon-compte/ma-collection/index.js | 129 +++++++----- .../mon-compte/ma-collection/details.ejs | 2 +- 10 files changed, 450 insertions(+), 370 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 143bf10..1f95ab5 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,36 +1,43 @@ module.exports = { - env: { - browser: true, - es2020: true, - node: true, - jquery: true, - }, - extends: ['airbnb-base', 'prettier'], - plugins: ['prettier'], - parserOptions: { - ecmaVersion: 11, - sourceType: 'module', - }, - rules: { - 'prettier/prettier': ['error'], - 'no-underscore-dangle': [ - 'error', - { - allow: ['_id', 'artists_sort', 'type_'], - }, - ], - 'camelcase': [ - 'error', - { - allow: ['artists_sort',] - }, - ], - }, - ignorePatterns: ['public/libs/**/*.js', 'public/js/main.js', 'dist/**'], - overrides: [ - { - files: ['**/*.js'], - excludedFiles: '*.ejs', + env: { + browser: true, + es2020: true, + node: true, + jquery: true, + }, + extends: ["airbnb-base", "prettier"], + plugins: ["prettier"], + parserOptions: { + ecmaVersion: 11, + sourceType: "module", + }, + rules: { + "prettier/prettier": ["error"], + "no-underscore-dangle": [ + "error", + { + allow: ["_id", "artists_sort", "type_"], + }, + ], + camelcase: [ + "error", + { + allow: ["artists_sort"], + }, + ], + }, + ignorePatterns: ["public/libs/**/*.js", "public/js/main.js", "dist/**"], + overrides: [ + { + files: ["**/*.js"], + excludedFiles: "*.ejs", + }, + ], + globals: { + Vue: true, + axios: true, + showToastr: true, + protocol: true, + host: true, }, - ], }; diff --git a/javascripts/ajouter-un-album.js b/javascripts/ajouter-un-album.js index d46d5d4..eb55697 100644 --- a/javascripts/ajouter-un-album.js +++ b/javascripts/ajouter-un-album.js @@ -1,109 +1,108 @@ Vue.createApp({ data() { return { - q: '', - year: '', - country: '', - format: '', + q: "", + year: "", + country: "", + format: "", loading: false, items: [], details: {}, modalIsVisible: false, formats: [ - 'Vinyl', - 'Acetate', - 'Flexi-disc', - 'Lathe Cut', - 'Mighty Tiny', - 'Shellac', - 'Sopic', - 'Pathé Disc', - 'Edison Disc', - 'Cylinder', - 'CD', - 'CDr', - 'CDV', - 'DVD', - 'DVDr', - 'HD DVD', - 'HD DVD-R', - 'Blu-ray', - 'Blu-ray-R', - 'Ultra HD Blu-ray', - 'SACD', - '4-Track Cartridge', - '8-Track Cartridge', - 'Cassette', - 'DC-International', - 'Elcaset', - 'PlayTape', - 'RCA Tape Cartridge', - 'DAT', - 'DCC', - 'Microcassette', - 'NT Cassette', - 'Pocket Rocker', - 'Revere Magnetic Stereo Tape Ca', - 'Tefifon', - 'Reel-To-Reel', - 'Sabamobil', - 'Betacam', - 'Betacam SP', - 'Betamax', - 'Cartrivision', - 'MiniDV', - 'Super VHS', - 'U-matic', - 'VHS', - 'Video 2000', - 'Video8', - 'Film Reel', - 'HitClips', - 'Laserdisc', - 'SelectaVision', - 'VHD', - 'Wire Recording', - 'Minidisc', - 'MVD', - 'UMD', - 'Floppy Disk', - 'File', - 'Memory Stick', - 'Hybrid', - 'All Media', - 'Box Set', - ] - } + "Vinyl", + "Acetate", + "Flexi-disc", + "Lathe Cut", + "Mighty Tiny", + "Shellac", + "Sopic", + "Pathé Disc", + "Edison Disc", + "Cylinder", + "CD", + "CDr", + "CDV", + "DVD", + "DVDr", + "HD DVD", + "HD DVD-R", + "Blu-ray", + "Blu-ray-R", + "Ultra HD Blu-ray", + "SACD", + "4-Track Cartridge", + "8-Track Cartridge", + "Cassette", + "DC-International", + "Elcaset", + "PlayTape", + "RCA Tape Cartridge", + "DAT", + "DCC", + "Microcassette", + "NT Cassette", + "Pocket Rocker", + "Revere Magnetic Stereo Tape Ca", + "Tefifon", + "Reel-To-Reel", + "Sabamobil", + "Betacam", + "Betacam SP", + "Betamax", + "Cartrivision", + "MiniDV", + "Super VHS", + "U-matic", + "VHS", + "Video 2000", + "Video8", + "Film Reel", + "HitClips", + "Laserdisc", + "SelectaVision", + "VHD", + "Wire Recording", + "Minidisc", + "MVD", + "UMD", + "Floppy Disk", + "File", + "Memory Stick", + "Hybrid", + "All Media", + "Box Set", + ], + }; }, methods: { search(event) { event.preventDefault(); - if ( this.loading ) { + if (this.loading) { return false; } this.loading = true; let url = `/api/v1/search?q=${this.q}`; - if ( this.year ) { + if (this.year) { url += `&year=${this.year}`; } - if ( this.country ) { + if (this.country) { url += `&country=${this.country}`; } - if ( this.format ) { + if (this.format) { url += `&format=${this.format}`; } - axios.get(url) - .then( response => { - const { - results, - } = response.data; - let items = []; + return axios + .get(url) + .then((response) => { + const { results } = response.data; + const items = []; - for (let i = 0 ; i < results.length ; i += 1 ) { + for (let i = 0; i < results.length; i += 1) { const { id, title, @@ -129,7 +128,10 @@ Vue.createApp({ this.items = items; }) .catch((err) => { - showToastr(err.response?.data?.message || "Aucun résultat trouvé :/"); + showToastr( + err.response?.data?.message || + "Aucun résultat trouvé :/" + ); }) .finally(() => { this.loading = false; @@ -139,33 +141,39 @@ Vue.createApp({ this.modalIsVisible = !this.modalIsVisible; }, loadDetails(discogsId) { - axios.get(`/api/v1/search/${discogsId}`) - .then( response => { - const { - data, - } = response; + axios + .get(`/api/v1/search/${discogsId}`) + .then((response) => { + const { data } = response; this.details = data; this.toggleModal(); }) .catch((err) => { - showToastr(err.response?.data?.message || "Impossible de charger les détails de cet album"); + showToastr( + err.response?.data?.message || + "Impossible de charger les détails de cet album" + ); }) .finally(() => { this.loading = false; }); }, add() { - axios.post('/api/v1/albums', this.details) + axios + .post("/api/v1/albums", this.details) .then(() => { - window.location.href = '/ma-collection'; + window.location.href = "/ma-collection"; }) .catch((err) => { - showToastr(err.response?.data?.message || "Impossible d'ajouter cet album pour le moment…"); + showToastr( + err.response?.data?.message || + "Impossible d'ajouter cet album pour le moment…" + ); }); }, orderedItems(items) { return items.sort(); - } - } -}).mount('#ajouter-album'); \ No newline at end of file + }, + }, +}).mount("#ajouter-album"); diff --git a/javascripts/collection.js b/javascripts/collection.js index c3b3561..beed2c6 100644 --- a/javascripts/collection.js +++ b/javascripts/collection.js @@ -1,4 +1,4 @@ -if ( typeof userId !== 'undefined' ) { +if (typeof userId !== "undefined") { Vue.createApp({ data() { return { @@ -9,16 +9,17 @@ if ( typeof userId !== 'undefined' ) { page: 1, totalPages: 1, limit: 16, - artist: '', - format: '', - year: '', - genre: '', - style: '', - sortOrder: 'artists_sort-asc', - sort: 'artists_sort', - order: 'asc', + artist: "", + format: "", + year: "", + genre: "", + style: "", + sortOrder: "artists_sort-asc", + sort: "artists_sort", + order: "asc", + // eslint-disable-next-line no-undef userId, - } + }; }, created() { this.fetch(); @@ -32,42 +33,49 @@ if ( typeof userId !== 'undefined' ) { const urlParams = new URLSearchParams(queryString); const entries = urlParams.entries(); - for(const entry of entries) { - switch(entry[0]) { - case 'artists_sort': - this.artist = entry[1]; + // eslint-disable-next-line no-restricted-syntax + for (const entry of entries) { + const [key, value] = entry; + switch (key) { + case "artists_sort": + this.artist = value; break; default: - this[entry[0]] = entry[1]; + this[key] = value; } } let url = `/api/v1/albums?userId=${this.userId}&page=${this.page}&limit=${this.limit}&sort=${this.sort}&order=${this.order}`; - if ( this.artist ) { - url += `&artists_sort=${this.artist.replace('&', '%26')}`; + if (this.artist) { + url += `&artists_sort=${this.artist.replace("&", "%26")}`; } - if ( this.format ) { - url += `&format=${this.format.replace('&', '%26')}`; + if (this.format) { + url += `&format=${this.format.replace("&", "%26")}`; } - if ( this.year ) { + if (this.year) { url += `&year=${this.year}`; } - if ( this.genre ) { - url += `&genre=${this.genre.replace('&', '%26')}`; + if (this.genre) { + url += `&genre=${this.genre.replace("&", "%26")}`; } - if ( this.style ) { - url += `&style=${this.style.replace('&', '%26')}`; + if (this.style) { + url += `&style=${this.style.replace("&", "%26")}`; } - axios.get(url) - .then( response => { + axios + .get(url) + .then((response) => { this.items = response.data.rows; this.total = response.data.count || 0; - this.totalPages = parseInt(response.data.count / this.limit) + (response.data.count % this.limit > 0 ? 1 : 0); - + this.totalPages = + parseInt(response.data.count / this.limit, 10) + + (response.data.count % this.limit > 0 ? 1 : 0); }) .catch((err) => { - showToastr(err.response?.data?.message || "Impossible de charger cette collection"); + showToastr( + err.response?.data?.message || + "Impossible de charger cette collection" + ); }) .finally(() => { this.loading = false; @@ -75,23 +83,23 @@ if ( typeof userId !== 'undefined' ) { }, changeUrl() { let url = `?page=${this.page}&limit=${this.limit}&sort=${this.sort}&order=${this.order}`; - if ( this.artist ) { - url += `&artists_sort=${this.artist.replace('&', '%26')}`; + if (this.artist) { + url += `&artists_sort=${this.artist.replace("&", "%26")}`; } - if ( this.format ) { - url += `&format=${this.format.replace('&', '%26')}`; + if (this.format) { + url += `&format=${this.format.replace("&", "%26")}`; } - if ( this.year ) { + if (this.year) { url += `&year=${this.year}`; } - if ( this.genre ) { - url += `&genre=${this.genre.replace('&', '%26')}`; + if (this.genre) { + url += `&genre=${this.genre.replace("&", "%26")}`; } - if ( this.style ) { - url += `&style=${this.style.replace('&', '%26')}`; + if (this.style) { + url += `&style=${this.style.replace("&", "%26")}`; } - location.href = url; + window.location.href = url; }, next(event) { event.preventDefault(); @@ -113,7 +121,7 @@ if ( typeof userId !== 'undefined' ) { this.changeUrl(); }, changeSort() { - const [sort,order] = this.sortOrder.split('-'); + const [sort, order] = this.sortOrder.split("-"); this.sort = sort; this.order = order; this.page = 1; @@ -127,7 +135,7 @@ if ( typeof userId !== 'undefined' ) { }, showMoreFilters() { this.moreFilters = !this.moreFilters; - } - } - }).mount('#collection-publique'); -} \ No newline at end of file + }, + }, + }).mount("#collection-publique"); +} diff --git a/javascripts/conctact.js b/javascripts/conctact.js index 51ed1cb..1fbde34 100644 --- a/javascripts/conctact.js +++ b/javascripts/conctact.js @@ -1,42 +1,43 @@ -if ( typeof contactMethod !== 'undefined' && contactMethod === 'smtp' ) { +// eslint-disable-next-line no-undef +if (typeof contactMethod !== "undefined" && contactMethod === "smtp") { Vue.createApp({ data() { return { - email: '', - name: '', - message: '', - captcha: '', + email: "", + name: "", + message: "", + captcha: "", loading: false, - } + }; }, methods: { send(event) { event.preventDefault(); - if ( this.loading ) { + if (this.loading) { return false; } this.loading = true; - const { - email, - message, - name, - captcha, - } = this; + const { email, message, name, captcha } = this; - axios.post('/api/v1/contact', {email, name, message, captcha}) - .then( () => { + return axios + .post("/api/v1/contact", { email, name, message, captcha }) + .then(() => { showToastr("Message correctement envoyé", true); }) .catch((err) => { - showToastr(err.response?.data?.message || "Impossible d'envoyer votre message", false); + showToastr( + err.response?.data?.message || + "Impossible d'envoyer votre message", + false + ); }) .finally(() => { this.loading = false; - }) + }); }, }, - }).mount('#contact'); -} \ No newline at end of file + }).mount("#contact"); +} diff --git a/javascripts/main.js b/javascripts/main.js index 0b0592e..388ab22 100644 --- a/javascripts/main.js +++ b/javascripts/main.js @@ -1,30 +1,30 @@ -const { - protocol, - host -} = window.location; +/* eslint-disable no-unused-vars */ +const { protocol, host } = window.location; - /** +/** * Fonction permettant d'afficher un message dans un toastr * @param {String} message */ function showToastr(message, success = false) { - let x = document.getElementById("toastr"); - if ( message ) { + const x = document.getElementById("toastr"); + if (message) { x.getElementsByTagName("SPAN")[0].innerHTML = message; } x.className = `${x.className} show`.replace("sucess", ""); - if ( success ) { + if (success) { x.className = `${x.className} success`; } - setTimeout(function(){ x.className = x.className.replace("show", ""); }, 3000); -}; + setTimeout(() => { + x.className = x.className.replace("show", ""); + }, 3000); +} /** * Fonction permettant de masquer le toastr */ function hideToastr() { - let x = document.getElementById("toastr"); + const x = document.getElementById("toastr"); x.className = x.className.replace("show", ""); x.getElementsByTagName("SPAN")[0].innerHTML = ""; @@ -37,17 +37,17 @@ function hideToastr() { * * @return {String} */ -function getCookie(cname, defaultValue = 'false') { - let name = cname + "="; - let decodedCookie = decodeURIComponent(document.cookie); - let ca = decodedCookie.split(';'); - for(let i = 0; i < ca.length; i+=1) { +function getCookie(cname, defaultValue = "false") { + const name = `${cname}=`; + const decodedCookie = decodeURIComponent(document.cookie); + const ca = decodedCookie.split(";"); + for (let i = 0; i < ca.length; i += 1) { let c = ca[i]; - while (c.charAt(0) == ' ') { - c = c.substring(1); + while (c.charAt(0) === " ") { + c = c.substring(1); } - if (c.indexOf(name) == 0) { - return c.substring(name.length, c.length); + if (c.indexOf(name) === 0) { + return c.substring(name.length, c.length); } } return defaultValue; @@ -61,9 +61,9 @@ function getCookie(cname, defaultValue = 'false') { */ function setCookie(cname, cvalue, exdays = 30) { const d = new Date(); - d.setTime(d.getTime() + (exdays*24*60*60*1000)); - let expires = "expires="+ d.toUTCString(); - document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; + d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000); + const expires = `expires=${d.toUTCString()}`; + document.cookie = `${cname}=${cvalue};${expires};path=/`; } /** @@ -71,9 +71,9 @@ function setCookie(cname, cvalue, exdays = 30) { * @param {String} value */ function setAriaTheme(value) { - let body = document.body; - if ( value === 'true' ) { - let classesString = body.className || ""; + const { body } = document; + if (value === "true") { + const classesString = body.className || ""; if (classesString.indexOf("is-accessible") === -1) { body.classList.add("is-accessible"); } @@ -86,11 +86,11 @@ function setAriaTheme(value) { * Fonction de (dé)charger le thème accessible */ function switchAriaTheme() { - let body = document.body; + const { body } = document; body.classList.toggle("is-accessible"); - setCookie('ariatheme', body.classList.contains("is-accessible")); + setCookie("ariatheme", body.classList.contains("is-accessible")); } /** @@ -98,46 +98,54 @@ function switchAriaTheme() { * @param {Object} e */ function switchTheme(e) { - const theme = e.target.checked ? 'dark' : 'light'; + const theme = e.target.checked ? "dark" : "light"; - document.documentElement.setAttribute('data-theme', theme); - setCookie('theme', theme); + document.documentElement.setAttribute("data-theme", theme); + setCookie("theme", theme); } /** * Ensemble d'actions effectuées au chargement de la page */ -document.addEventListener('DOMContentLoaded', () => { - const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0); +document.addEventListener("DOMContentLoaded", () => { + const $navbarBurgers = Array.prototype.slice.call( + document.querySelectorAll(".navbar-burger"), + 0 + ); if ($navbarBurgers.length > 0) { - $navbarBurgers.forEach( el => { - el.addEventListener('click', () => { - const target = el.dataset.target; + $navbarBurgers.forEach((el) => { + el.addEventListener("click", () => { + const { target } = el.dataset; const $target = document.getElementById(target); - el.classList.toggle('is-active'); - $target.classList.toggle('is-active'); + el.classList.toggle("is-active"); + $target.classList.toggle("is-active"); }); }); } const switchAriaThemeBtn = document.querySelector("#switchAriaTheme"); - if ( switchAriaThemeBtn ) { + if (switchAriaThemeBtn) { switchAriaThemeBtn.addEventListener("click", switchAriaTheme); } - setAriaTheme(getCookie('ariatheme')); + setAriaTheme(getCookie("ariatheme")); - const toggleSwitch = document.querySelector('.theme-switch input[type="checkbox"]'); - if ( toggleSwitch ) { - toggleSwitch.addEventListener('change', switchTheme, false); + const toggleSwitch = document.querySelector( + '.theme-switch input[type="checkbox"]' + ); + if (toggleSwitch) { + toggleSwitch.addEventListener("change", switchTheme, false); } - let currentThemeIsDark = getCookie('theme'); - if ( currentThemeIsDark === 'false' && window.matchMedia ) { - currentThemeIsDark = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; + let currentThemeIsDark = getCookie("theme"); + if (currentThemeIsDark === "false" && window.matchMedia) { + currentThemeIsDark = window.matchMedia("(prefers-color-scheme: dark)") + .matches + ? "dark" + : "light"; } - switchTheme({target: {checked: currentThemeIsDark === 'dark'}}); - if ( toggleSwitch) { - toggleSwitch.checked = currentThemeIsDark === 'dark'; + switchTheme({ target: { checked: currentThemeIsDark === "dark" } }); + if (toggleSwitch) { + toggleSwitch.checked = currentThemeIsDark === "dark"; } -}); \ No newline at end of file +}); diff --git a/javascripts/mon-compte/index.js b/javascripts/mon-compte/index.js index ccc1d02..ed40f03 100644 --- a/javascripts/mon-compte/index.js +++ b/javascripts/mon-compte/index.js @@ -1,16 +1,19 @@ -if ( typeof email !== 'undefined' && typeof username !== 'undefined' ) { +if (typeof email !== "undefined" && typeof username !== "undefined") { Vue.createApp({ data() { return { + // eslint-disable-next-line no-undef email, + // eslint-disable-next-line no-undef username, - oldPassword: '', - password: '', - passwordConfirm: '', + oldPassword: "", + password: "", + passwordConfirm: "", loading: false, - } + }; }, methods: { + // eslint-disable-next-line no-unused-vars async updateProfil(event) { // try { // if ( this.password !== this.passwordConfirm ) { @@ -21,6 +24,6 @@ if ( typeof email !== 'undefined' && typeof username !== 'undefined' ) { // showToastr(err); // } }, - } - }).mount('#mon-compte'); -} \ No newline at end of file + }, + }).mount("#mon-compte"); +} diff --git a/javascripts/mon-compte/ma-collection/details.js b/javascripts/mon-compte/ma-collection/details.js index 3f63290..fe8d079 100644 --- a/javascripts/mon-compte/ma-collection/details.js +++ b/javascripts/mon-compte/ma-collection/details.js @@ -1,17 +1,18 @@ -if ( typeof item !== 'undefined' ) { +if (typeof item !== "undefined") { Vue.createApp({ data() { return { + // eslint-disable-next-line no-undef item, tracklist: [], identifiers: [], modalIsVisible: false, - identifiersMode: 'preview', + identifiersMode: "preview", identifiersPreviewLength: 16, preview: null, index: null, showModalDelete: false, - } + }; }, created() { this.setTrackList(); @@ -20,65 +21,65 @@ if ( typeof item !== 'undefined' ) { window.addEventListener("keydown", this.changeImage); }, destroyed() { - window.removeEventListener('keydown', this.changeImage); + window.removeEventListener("keydown", this.changeImage); }, methods: { setIdentifiers() { this.identifiers = []; - let max = this.identifiersMode == 'preview' && this.item.identifiers.length > this.identifiersPreviewLength ? this.identifiersPreviewLength : this.item.identifiers.length; + const max = + this.identifiersMode === "preview" && + this.item.identifiers.length > this.identifiersPreviewLength + ? this.identifiersPreviewLength + : this.item.identifiers.length; - for ( let i = 0 ; i < max ; i += 1 ) { + for (let i = 0; i < max; i += 1) { this.identifiers.push(this.item.identifiers[i]); } }, setTrackList() { let subTrack = { - type: null, - title: null, - tracks: [], - }; - for (let i = 0 ; i < this.item.tracklist.length ; i += 1 ) { - const { - type_, - title, - position, - duration, - extraartists, - } = this.item.tracklist[i]; + type: null, + title: null, + tracks: [], + }; + for (let i = 0; i < this.item.tracklist.length; i += 1) { + const { type_, title, position, duration, extraartists } = + this.item.tracklist[i]; - if ( type_ === 'heading' ) { - if ( subTrack.type ) { - this.tracklist.push(subTrack); - subTrack = { - type: null, - title: null, - tracks: [], - }; + if (type_ === "heading") { + if (subTrack.type) { + this.tracklist.push(subTrack); + subTrack = { + type: null, + title: null, + tracks: [], + }; + } + + subTrack.type = type_; + subTrack.title = title; + } else { + subTrack.tracks.push({ + title, + position, + duration, + extraartists, + }); } - - subTrack.type = type_; - subTrack.title = title; - } else { - subTrack.tracks.push({ - title, - position, - duration, - extraartists - }); } - } - this.tracklist.push(subTrack); + this.tracklist.push(subTrack); }, setImage() { this.preview = this.item.images[this.index].uri; }, showGallery(event) { - const item = event.target.tagName === 'IMG' ? event.target.parentElement : event.target; + const item = + event.target.tagName === "IMG" + ? event.target.parentElement + : event.target; - const { - index, - } = item.dataset; + const { index } = item.dataset; this.index = Number(index); this.modalIsVisible = true; @@ -89,48 +90,63 @@ if ( typeof item !== 'undefined' ) { this.modalIsVisible = !this.modalIsVisible; }, previous() { - this.index = this.index > 0 ? this.index - 1 : this.item.images.length -1; + this.index = + this.index > 0 + ? this.index - 1 + : this.item.images.length - 1; this.setImage(); }, next() { - this.index = (this.index +1) === this.item.images.length ? 0 : this.index + 1; + this.index = + this.index + 1 === this.item.images.length + ? 0 + : this.index + 1; this.setImage(); }, changeImage(event) { const direction = event.code; - if ( this.modalIsVisible && ['ArrowRight', 'ArrowLeft', 'Escape'].indexOf(direction) !== -1 ) { + if ( + this.modalIsVisible && + ["ArrowRight", "ArrowLeft", "Escape"].indexOf(direction) !== + -1 + ) { switch (direction) { - case 'ArrowRight': + case "ArrowRight": return this.next(); - case 'ArrowLeft': + case "ArrowLeft": return this.previous(); default: this.modalIsVisible = false; return true; } } + + return true; }, showAllIdentifiers() { - this.identifiersMode = 'all'; + this.identifiersMode = "all"; this.setIdentifiers(); }, showLessIdentifiers() { - this.identifiersMode = 'preview'; + this.identifiersMode = "preview"; this.setIdentifiers(); - document.querySelector('#identifiers').scrollIntoView({ behavior: 'smooth' }); + document + .querySelector("#identifiers") + .scrollIntoView({ behavior: "smooth" }); }, showConfirmDelete() { - this.toggleModal(); + this.toggleModalDelete(); }, - toggleModal() { + toggleModalDelete() { this.showModalDelete = !this.showModalDelete; }, updateItem() { showToastr("Mise à jour en cours…", true); - axios.patch(`/api/v1/albums/${this.item._id}`) - .then( (res) => { + axios + .patch(`/api/v1/albums/${this.item._id}`) + .then((res) => { showToastr("Mise à jour réalisée avec succès", true); this.item = res.data; @@ -139,24 +155,32 @@ if ( typeof item !== 'undefined' ) { this.showLessIdentifiers(); }) .catch((err) => { - showToastr(err.response?.data?.message || "Impossible de mettre à jour cet album", false); + showToastr( + err.response?.data?.message || + "Impossible de mettre à jour cet album", + false + ); }); }, deleteItem() { - axios.delete(`/api/v1/albums/${this.item._id}`) - .then( () => { + axios + .delete(`/api/v1/albums/${this.item._id}`) + .then(() => { window.location.href = "/ma-collection"; }) .catch((err) => { - showToastr(err.response?.data?.message || "Impossible de supprimer cet album"); + showToastr( + err.response?.data?.message || + "Impossible de supprimer cet album" + ); }) .finally(() => { - this.toggleModal(); + this.toggleModalDelete(); }); }, goToArtist() { return ""; }, }, - }).mount('#ma-collection-details'); -} \ No newline at end of file + }).mount("#ma-collection-details"); +} diff --git a/javascripts/mon-compte/ma-collection/exporter.js b/javascripts/mon-compte/ma-collection/exporter.js index f5dcbcb..b391436 100644 --- a/javascripts/mon-compte/ma-collection/exporter.js +++ b/javascripts/mon-compte/ma-collection/exporter.js @@ -1,18 +1,16 @@ Vue.createApp({ data() { return { - format: 'xml', - } - }, - created() { - }, - destroyed() { + format: "xml", + }; }, + created() {}, + destroyed() {}, methods: { exportCollection(event) { event.preventDefault(); - window.open(`/api/v1/albums?exportFormat=${this.format}`, '_blank'); - } + window.open(`/api/v1/albums?exportFormat=${this.format}`, "_blank"); + }, }, -}).mount('#exporter'); \ No newline at end of file +}).mount("#exporter"); diff --git a/javascripts/mon-compte/ma-collection/index.js b/javascripts/mon-compte/ma-collection/index.js index 7e2bdf5..967e3f2 100644 --- a/javascripts/mon-compte/ma-collection/index.js +++ b/javascripts/mon-compte/ma-collection/index.js @@ -1,4 +1,4 @@ -if ( typeof isPublicCollection !== 'undefined' ) { +if (typeof isPublicCollection !== "undefined") { Vue.createApp({ data() { return { @@ -9,20 +9,21 @@ if ( typeof isPublicCollection !== 'undefined' ) { page: 1, totalPages: 1, limit: 16, - artist: '', - format: '', - year: '', - genre: '', - style: '', - sortOrder: 'artists_sort-asc', - sort: 'artists_sort', - order: 'asc', + artist: "", + format: "", + year: "", + genre: "", + style: "", + sortOrder: "artists_sort-asc", + sort: "artists_sort", + order: "asc", itemId: null, showModalDelete: false, showModalShare: false, shareLink: `${protocol}//${host}/collection/<%= user._id %>`, + // eslint-disable-next-line no-undef isPublicCollection, - } + }; }, created() { this.fetch(); @@ -36,41 +37,49 @@ if ( typeof isPublicCollection !== 'undefined' ) { const urlParams = new URLSearchParams(queryString); const entries = urlParams.entries(); - for(const entry of entries) { - switch(entry[0]) { - case 'artists_sort': - this.artist = entry[1]; + // eslint-disable-next-line no-restricted-syntax + for (const entry of entries) { + const [key, value] = entry; + switch (key) { + case "artists_sort": + this.artist = value; break; default: - this[entry[0]] = entry[1]; + this[key] = value; } } let url = `/api/v1/albums?page=${this.page}&limit=${this.limit}&sort=${this.sort}&order=${this.order}`; - if ( this.artist ) { - url += `&artists_sort=${this.artist.replace('&', '%26')}`; + if (this.artist) { + url += `&artists_sort=${this.artist.replace("&", "%26")}`; } - if ( this.format ) { - url += `&format=${this.format.replace('&', '%26')}`; + if (this.format) { + url += `&format=${this.format.replace("&", "%26")}`; } - if ( this.year ) { + if (this.year) { url += `&year=${this.year}`; } - if ( this.genre ) { - url += `&genre=${this.genre.replace('&', '%26')}`; + if (this.genre) { + url += `&genre=${this.genre.replace("&", "%26")}`; } - if ( this.style ) { - url += `&style=${this.style.replace('&', '%26')}`; + if (this.style) { + url += `&style=${this.style.replace("&", "%26")}`; } - axios.get(url) - .then( response => { + axios + .get(url) + .then((response) => { this.items = response.data.rows; this.total = response.data.count || 0; - this.totalPages = parseInt(response.data.count / this.limit) + (response.data.count % this.limit > 0 ? 1 : 0); + this.totalPages = + parseInt(response.data.count / this.limit, 10) + + (response.data.count % this.limit > 0 ? 1 : 0); }) .catch((err) => { - showToastr(err.response?.data?.message || "Impossible de charger votre collection"); + showToastr( + err.response?.data?.message || + "Impossible de charger votre collection" + ); }) .finally(() => { this.loading = false; @@ -78,23 +87,23 @@ if ( typeof isPublicCollection !== 'undefined' ) { }, changeUrl() { let url = `?page=${this.page}&limit=${this.limit}&sort=${this.sort}&order=${this.order}`; - if ( this.artist ) { - url += `&artists_sort=${this.artist.replace('&', '%26')}`; + if (this.artist) { + url += `&artists_sort=${this.artist.replace("&", "%26")}`; } - if ( this.format ) { - url += `&format=${this.format.replace('&', '%26')}`; + if (this.format) { + url += `&format=${this.format.replace("&", "%26")}`; } - if ( this.year ) { + if (this.year) { url += `&year=${this.year}`; } - if ( this.genre ) { - url += `&genre=${this.genre.replace('&', '%26')}`; + if (this.genre) { + url += `&genre=${this.genre.replace("&", "%26")}`; } - if ( this.style ) { - url += `&style=${this.style.replace('&', '%26')}`; + if (this.style) { + url += `&style=${this.style.replace("&", "%26")}`; } - location.href = url; + window.location.href = url; }, next(event) { event.preventDefault(); @@ -116,7 +125,7 @@ if ( typeof isPublicCollection !== 'undefined' ) { this.changeUrl(); }, changeSort() { - const [sort,order] = this.sortOrder.split('-'); + const [sort, order] = this.sortOrder.split("-"); this.sort = sort; this.order = order; this.page = 1; @@ -142,37 +151,51 @@ if ( typeof isPublicCollection !== 'undefined' ) { this.toggleModal(); }, deleteItem() { - axios.delete(`/api/v1/albums/${this.itemId}`) - .then( () => { + axios + .delete(`/api/v1/albums/${this.itemId}`) + .then(() => { this.fetch(); }) .catch((err) => { - showToastr(err.response?.data?.message || "Impossible de supprimer cet album"); + showToastr( + err.response?.data?.message || + "Impossible de supprimer cet album" + ); }) .finally(() => { this.toggleModal(); }); }, shareCollection() { - axios.patch(`/api/v1/me`, { - isPublicCollection: !this.isPublicCollection, - }) - .then( (res) => { + axios + .patch(`/api/v1/me`, { + isPublicCollection: !this.isPublicCollection, + }) + .then((res) => { this.isPublicCollection = res.data.isPublicCollection; - if ( this.isPublicCollection ) { - showToastr("Votre collection est désormais publique", true); + if (this.isPublicCollection) { + showToastr( + "Votre collection est désormais publique", + true + ); } else { - showToastr("Votre collection n'est plus partagée", true); + showToastr( + "Votre collection n'est plus partagée", + true + ); } }) .catch((err) => { - showToastr(err.response?.data?.message || "Impossible de supprimer cet album"); + showToastr( + err.response?.data?.message || + "Impossible de supprimer cet album" + ); }) .finally(() => { this.toggleModalShare(); }); }, - } - }).mount('#ma-collection'); -} \ No newline at end of file + }, + }).mount("#ma-collection"); +} diff --git a/views/pages/mon-compte/ma-collection/details.ejs b/views/pages/mon-compte/ma-collection/details.ejs index e8615b4..475ee79 100644 --- a/views/pages/mon-compte/ma-collection/details.ejs +++ b/views/pages/mon-compte/ma-collection/details.ejs @@ -169,7 +169,7 @@
- +
-- 2.39.2 From a56db99a8160cc52ec46e548df34699dd3647eb9 Mon Sep 17 00:00:00 2001 From: dbroqua Date: Wed, 2 Nov 2022 09:48:05 +0100 Subject: [PATCH 07/16] #69 - Partager ma collection --- javascripts/mon-compte/ma-collection/index.js | 2 +- views/pages/mon-compte/ma-collection/index.ejs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/javascripts/mon-compte/ma-collection/index.js b/javascripts/mon-compte/ma-collection/index.js index 967e3f2..1cfb05e 100644 --- a/javascripts/mon-compte/ma-collection/index.js +++ b/javascripts/mon-compte/ma-collection/index.js @@ -20,7 +20,7 @@ if (typeof isPublicCollection !== "undefined") { itemId: null, showModalDelete: false, showModalShare: false, - shareLink: `${protocol}//${host}/collection/<%= user._id %>`, + shareLink: `${protocol}//${host}/collection/${userId}`, // eslint-disable-next-line no-undef isPublicCollection, }; diff --git a/views/pages/mon-compte/ma-collection/index.ejs b/views/pages/mon-compte/ma-collection/index.ejs index 38993c8..5dffd9f 100644 --- a/views/pages/mon-compte/ma-collection/index.ejs +++ b/views/pages/mon-compte/ma-collection/index.ejs @@ -197,4 +197,5 @@ \ No newline at end of file -- 2.39.2 From d446735450e3f15cb9b175cfdfa1c65a904e1779 Mon Sep 17 00:00:00 2001 From: dbroqua Date: Tue, 17 Jan 2023 16:24:54 +0100 Subject: [PATCH 08/16] Utilisation de NPX --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b3dffed..b5607af 100644 --- a/package.json +++ b/package.json @@ -5,13 +5,13 @@ "scripts": { "start": "node ./dist/bin/www", "run:all": "npm-run-all build sass uglify start", - "watch": "nodemon -e js,scss", + "watch": "npx nodemon -e js,scss", "sass": "npx sass sass/index.scss public/css/main.css -s compressed --color", "uglify": "npx gulp", "prebuild": "rimraf dist", - "build": "babel ./src --out-dir dist --copy-files", + "build": "npx babel ./src --out-dir dist --copy-files", "test": "jest", - "prepare": "husky install" + "prepare": "npx husky install" }, "engines": { "node": "16.x", @@ -78,7 +78,7 @@ "vue": "^3.2.31" }, "nodemonConfig": { - "exec": "yarn run:all", + "exec": "npm run run:all", "watch": [ "src/*", "sass/*", -- 2.39.2 From dff1d2baf0d057e5542da66014b614052c268908 Mon Sep 17 00:00:00 2001 From: dbroqua Date: Tue, 17 Jan 2023 16:37:13 +0100 Subject: [PATCH 09/16] =?UTF-8?q?#75=20-=20Num=C3=A9rotation=20de=20la=20t?= =?UTF-8?q?racklist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- views/pages/mon-compte/ma-collection/details.ejs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/views/pages/mon-compte/ma-collection/details.ejs b/views/pages/mon-compte/ma-collection/details.ejs index 475ee79..c868db0 100644 --- a/views/pages/mon-compte/ma-collection/details.ejs +++ b/views/pages/mon-compte/ma-collection/details.ejs @@ -20,16 +20,16 @@
-- 2.39.2 From 8822056c1f40f6d3e96b4c2f7a37aa996a3e2890 Mon Sep 17 00:00:00 2001 From: dbroqua Date: Tue, 17 Jan 2023 16:54:58 +0100 Subject: [PATCH 10/16] =?UTF-8?q?#76=20-=20Avoir=20plus=20de=20d=C3=A9tail?= =?UTF-8?q?s=20sur=20le=20support=20physique=20sur=20la=20modale=20d'ajout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mon-compte/ma-collection/details.js | 12 ++++++-- views/pages/ajouter-un-album.ejs | 28 +++++++++++++++---- .../mon-compte/ma-collection/details.ejs | 5 ++++ 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/javascripts/mon-compte/ma-collection/details.js b/javascripts/mon-compte/ma-collection/details.js index fe8d079..5486244 100644 --- a/javascripts/mon-compte/ma-collection/details.js +++ b/javascripts/mon-compte/ma-collection/details.js @@ -38,14 +38,21 @@ if (typeof item !== "undefined") { } }, setTrackList() { + this.tracklist = []; let subTrack = { type: null, title: null, tracks: [], }; for (let i = 0; i < this.item.tracklist.length; i += 1) { - const { type_, title, position, duration, extraartists } = - this.item.tracklist[i]; + const { + type_, + title, + position, + duration, + artists, + extraartists, + } = this.item.tracklist[i]; if (type_ === "heading") { if (subTrack.type) { @@ -65,6 +72,7 @@ if (typeof item !== "undefined") { position, duration, extraartists, + artists, }); } } diff --git a/views/pages/ajouter-un-album.ejs b/views/pages/ajouter-un-album.ejs index f32ea67..2141963 100644 --- a/views/pages/ajouter-un-album.ejs +++ b/views/pages/ajouter-un-album.ejs @@ -1,7 +1,7 @@

Ajouter un album

-
+
@@ -87,7 +87,14 @@
    -
  1. {{ track.title }} ({{track.duration}})
  2. +
  3. + {{ track.title }} ({{track.duration}}) +
      +
    • + {{extra.role}} : {{extra.name}} +
    • +
    +
@@ -129,10 +136,19 @@
Format -
- - {{format.name}} - +
    +
  • + {{format.name}} + + +
  • +

diff --git a/views/pages/mon-compte/ma-collection/details.ejs b/views/pages/mon-compte/ma-collection/details.ejs index c868db0..dc56b3a 100644 --- a/views/pages/mon-compte/ma-collection/details.ejs +++ b/views/pages/mon-compte/ma-collection/details.ejs @@ -23,6 +23,11 @@
  • {{track.position || (index+1)}} - {{ track.title }} +
      +
    • + {{extra.name}} +
    • +
    • {{extra.role}} : {{extra.name}} -- 2.39.2 From fe3ed3e91f68d9de7be1c57b44ff0a93ec6fd58f Mon Sep 17 00:00:00 2001 From: dbroqua Date: Tue, 17 Jan 2023 17:08:41 +0100 Subject: [PATCH 11/16] #73 - Savoir sur quelle page on est --- javascripts/mon-compte/ma-collection/index.js | 6 +++++- views/pages/mon-compte/ma-collection/index.ejs | 7 ++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/javascripts/mon-compte/ma-collection/index.js b/javascripts/mon-compte/ma-collection/index.js index 1cfb05e..a2d93c5 100644 --- a/javascripts/mon-compte/ma-collection/index.js +++ b/javascripts/mon-compte/ma-collection/index.js @@ -6,7 +6,8 @@ if (typeof isPublicCollection !== "undefined") { moreFilters: false, items: [], total: 0, - page: 1, + // eslint-disable-next-line no-undef + page: query.page || 1, totalPages: 1, limit: 16, artist: "", @@ -20,9 +21,12 @@ if (typeof isPublicCollection !== "undefined") { itemId: null, showModalDelete: false, showModalShare: false, + // eslint-disable-next-line no-undef shareLink: `${protocol}//${host}/collection/${userId}`, // eslint-disable-next-line no-undef isPublicCollection, + // eslint-disable-next-line no-undef + query, }; }, created() { diff --git a/views/pages/mon-compte/ma-collection/index.ejs b/views/pages/mon-compte/ma-collection/index.ejs index 5dffd9f..c061d9a 100644 --- a/views/pages/mon-compte/ma-collection/index.ejs +++ b/views/pages/mon-compte/ma-collection/index.ejs @@ -135,12 +135,12 @@