Compare commits
132 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e3f47a7bf7 | ||
|
948ccf9419 | ||
|
47a8935ec5 | ||
|
ad8b8f4767 | ||
|
6ee117b583 | ||
|
4f707ece88 | ||
|
a4a3933c6d | ||
|
bed5139a27 | ||
|
5b2758afca | ||
|
68414e3e71 | ||
|
d692090022 | ||
|
061e72c459 | ||
|
bf2e9be3b7 | ||
|
d4e6d23459 | ||
|
0ea6a21b90 | ||
|
6b2f7b61cb | ||
|
f1220fc05a | ||
|
8d22435b90 | ||
|
30bd3ebdf9 | ||
|
5a7d9d707f | ||
|
041e24e26f | ||
|
71c120564a | ||
|
1a9728fce6 | ||
|
2eb22bb3d6 | ||
|
abcbd0f8f7 | ||
|
f73d4a3093 | ||
|
0a2d5029b5 | ||
|
fcb527aa5e | ||
|
c79f1c5a74 | ||
|
960f53ab54 | ||
|
6994170a04 | ||
|
8e0947ed4b | ||
|
736a0afa44 | ||
|
209ba0f5f0 | ||
77de7d54ca | |||
00bb8647e1 | |||
c32b182151 | |||
85752c537d | |||
3b3a4cf779 | |||
1931bd9eda | |||
7b525d3e43 | |||
81c61a0529 | |||
e01dbd5c31 | |||
205474a701 | |||
e28f382c6c | |||
3626b074bd | |||
4ea7b42d52 | |||
fd0a9df724 | |||
97b8bab2f4 | |||
2f988798df | |||
15eb2c2dad | |||
6862afda5c | |||
4109186a47 | |||
ec5e43889f | |||
c2ff54ecf2 | |||
bfdb19eec1 | |||
1df39410c3 | |||
e0f227af08 | |||
13209a9b1d | |||
b630e73c79 | |||
fbeb1a67c5 | |||
c743f0d3a4 | |||
68004646f1 | |||
55a9656c42 | |||
2389d7d731 | |||
4c442edf21 | |||
50f01805d4 | |||
663eb586cf | |||
c1b01ea4c0 | |||
fe3ed3e91f | |||
8822056c1f | |||
dff1d2baf0 | |||
d446735450 | |||
9fe49eca27 | |||
a7e41949dc | |||
a56db99a81 | |||
1d59ee3b71 | |||
e01f01337c | |||
980586d8eb | |||
8f9e902587 | |||
a74c67e241 | |||
eac7c1aa84 | |||
748edc9cc4 | |||
d03394bee7 | |||
4da4dd9423 | |||
6454f5f8d6 | |||
bc3bb3b554 | |||
da08aa0222 | |||
2da6afa06d | |||
b8b3df2932 | |||
adea857666 | |||
6320764743 | |||
d473899b20 | |||
827dcb9ccc | |||
1377b4c0c1 | |||
080471eb37 | |||
befdfa35a6 | |||
cc25b83b2e | |||
fe3bdafb63 | |||
a3c03a1569 | |||
06752ebcec | |||
12ca71e643 | |||
9dd7a35f22 | |||
f5196edfb8 | |||
e8f91288fc | |||
48c997ae10 | |||
6d0405d129 | |||
226a9ef1d1 | |||
36b33124bc | |||
0d90e0da20 | |||
62a3bcd8ee | |||
ae4b7b6de0 | |||
182aa7a6a6 | |||
7d7ee080ed | |||
5b9d6c94b8 | |||
7578d9b63f | |||
9e7743e16d | |||
e0a8fa42c2 | |||
b0e6964205 | |||
b27cbd467b | |||
b05bed9a00 | |||
3aeb172dbf | |||
4068df3cba | |||
9a088b9b5f | |||
4886e9cc48 | |||
73716335e2 | |||
aeb5df067c | |||
ac72c1c13c | |||
95ab6f5f42 | |||
0b8b4b21bd | |||
30d0713f79 | |||
1251ca1e02 |
79
.eslintrc.js
79
.eslintrc.js
@ -1,36 +1,49 @@
|
||||
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",
|
||||
"access_token",
|
||||
"api_url",
|
||||
"media_ids",
|
||||
"release_id",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
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,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -121,6 +121,6 @@ dist
|
||||
dist
|
||||
yarn.lock
|
||||
public/css
|
||||
public/css
|
||||
public/js
|
||||
docker-compose.yml
|
||||
dump
|
||||
|
53
README.md
53
README.md
@ -18,7 +18,9 @@ Vous pouvez, si vous le souhaitez héberger l'application sur votre propre serve
|
||||
|
||||
### Prérequis
|
||||
|
||||
Il existe 2 méthodes d'installation, soit via docker soit en mode standalone. Peu importe la méthode il vous faudra un compte sur [https://formspree.io/](https://formspree.io/) afin d'avoir une page nous-contacter fonctionnelle.
|
||||
Il existe 2 méthodes d'installation, soit via docker soit en mode standalone.
|
||||
|
||||
Peu importe la méthode il vous faudra un compte sur [https://formspree.io/](https://formspree.io/) afin d'avoir une page nous-contacter fonctionnelle ou configurer le SMTP tel que défini dans la section [variables d'environnements](#env-file).
|
||||
|
||||
Pour la méthode docker il ne vous faudra rien de plus que `docker` et `docker-compose`.
|
||||
|
||||
@ -62,7 +64,7 @@ Le site est accessible sur [http://localhost:PORT](http://localhost:PORT).
|
||||
|
||||
#### Standalone
|
||||
|
||||
Pour la version standalone je vous conseille de faire un script embarquant les variables d'environnement que vous souhaitez modifier :
|
||||
Pour la version standalone je vous conseille de faire un script embarquant les variables d'environnement que vous souhaitez modifier ([voir à la fin pour la liste des variables](#env-file)) :
|
||||
|
||||
```bash
|
||||
#! /bin/bash
|
||||
@ -90,7 +92,7 @@ C'est terminé !
|
||||
|
||||
Le site est accessible sur [http://localhost:3001](http://localhost:3001).
|
||||
|
||||
:information_source: Information : Vous pouvez, et vous dreviez, également regarder du côté de `systemd`, `pm2` ou encore `supervisor` pour que le service démarre en même temps que votre serveur.
|
||||
:information_source: Information : Vous pouvez, et vous devriez, également regarder du côté de `systemd`, `pm2` ou encore `supervisor` pour que le service démarre en même temps que votre serveur.
|
||||
|
||||
### Aller plus loin
|
||||
|
||||
@ -184,24 +186,59 @@ server {
|
||||
|
||||
Une fois le vhost activé (lien symbolique dans le dossier site-enable) et nginx rechargé votre site sera alors accessible en https.
|
||||
|
||||
### Jobs
|
||||
|
||||
Par défaut toute les images des albums sont affichées depuis Discogs. Cependant avec les temps les urls deviennent invalides. Pour éviter cela lors de l'ajout d'un album à votre collection un job est créé. Ce job a pour rôle de stocker les images sur un bucket s3.
|
||||
|
||||
Pour lancer les jobs il faut mettre en place une tâche cron qui sera éxécutée toute les heures (par exemple).
|
||||
|
||||
Exemple de crontab :
|
||||
```crontab
|
||||
0 * * * * curl 'http://localhost:3001/jobs' \
|
||||
-H 'JOBS_HEADER_KEY: JOBS_HEADER_VALUE' \
|
||||
-H 'Accept: application/json'
|
||||
30 * * * * curl 'http://localhost:3001/jobs?state=ERROR' \
|
||||
-H 'JOBS_HEADER_KEY: JOBS_HEADER_VALUE' \
|
||||
-H 'Accept: application/json'
|
||||
```
|
||||
|
||||
N'oubliez pas de remplacer `localhost:30001`, `JOBS_HEADER_KEY` et `JOBS_HEADER_VALUE` par les bonnes valeurs.
|
||||
|
||||
La première ligne permet de parcourir tous les nouveaux jobs alors que la seconde permet de relancer les jobs en erreurs (après 5 tentatives le job est marqué comme définitivement perdu).
|
||||
|
||||
### Fichier .env {#env-file}
|
||||
|
||||
Voici la liste des variables configurables :
|
||||
|
||||
```
|
||||
NODE_ENV # Environnement dans lequel exécuter le projet (development ou production)
|
||||
PORT # Port sur lequel éxécuter le serveur (par défaut 3001)
|
||||
MONGODB_URI # Url du serveur mongo (par défaut mongodb://musictopus-db/musictopus)
|
||||
SECRET # Hash utilisé pour pour sauvegardé les dessions (par défaut waemaeMe5ahc6ce1chaeKohKa6Io8Eik)
|
||||
PORT # Port sur lequel éxécuter le serveur (3001 par défaut)
|
||||
MONGODB_URI # Url du serveur mongo (mongodb://musictopus-db/musictopus par défaut)
|
||||
SECRET # Hash utilisé pour pour sauvegardé les dessions (waemaeMe5ahc6ce1chaeKohKa6Io8Eik par défault)
|
||||
DISCOGS_TOKEN # Token Discogs (vous devez créer un compte sur discogs afin d'en obtenir un gratuitement)
|
||||
FORMSPREE_ID # Id du formulaire formspree pour la page "nous-contacter"
|
||||
MATOMO_URL # Url vers l'instance matomo (exemple: https://analytics.darkou.fr/)
|
||||
MATOMO_ID # Id du site sur votre instance matomo (exemple: 1)
|
||||
SITE_NAME # Nom du site (utilisé dans le titre des pages)
|
||||
SITE_NAME # Nom du site utilisé dans le titre des pages (MusicTopus par défaut)
|
||||
AWS_ACCESS_KEY_ID # Clé d'accès AWS
|
||||
AWS_SECRET_ACCESS_KEY # Clé secrète AWS
|
||||
S3_ENDPOINT # Url de l'instance aws (s3.fr-par.scw.cloud par défaut)
|
||||
S3_SIGNATURE # Version de la signature AWS (s3v4 par défaut)
|
||||
S3_BASEFOLDER # Nom du sous dossier dans lequel seront mis les pochettes des albums (dev par défaut)
|
||||
S3_BUCKET # Nom du bucket (musictopus par défaut, à changer impérativement si vous voulez que cela fonctionne)
|
||||
JOBS_HEADER_KEY # Nom du header utilisé pour l'identification des tâches cron (musictopus par défaut)
|
||||
JOBS_HEADER_VALUE # Valeur de la clé (ooYee9xok7eigo2shiePohyoGh1eepew par défaut)
|
||||
REGISTRATION_OPEN # true/false en fonction de si vous souhaitez activer ou non l'inscription à votre instance (true par défaut)
|
||||
MAIL_METHOD # permet de définir la façon dont les mails de la page contact sont envoyés (formspree ou smtp)
|
||||
MAIL_HOST # Adresse du server mail (dams le cas ou MAIL_METHOD est défini sur smtp)
|
||||
MAIL_PORT # Port d'écoute du serveur smtp (dams le cas ou MAIL_METHOD est défini sur smtp)
|
||||
MAIL_USER # Adresse mail du compte permettant d'envoyer les mails (dams le cas ou MAIL_METHOD est défini sur smtp)
|
||||
MAIL_PASSWORD # Mot de passe du compte email (dams le cas ou MAIL_METHOD est défini sur smtp)
|
||||
MAIL_TO # Adresse mail du contact qui recevra les messages de la page "nous contacter" (dams le cas ou MAIL_METHOD est défini sur smtp)
|
||||
|
||||
```
|
||||
|
||||
## Contributeurs
|
||||
|
||||
- Damien Broqua (développeur principal du projet)
|
||||
- Brunus (Logo et fournisseur d'idées :wink: )
|
||||
|
||||
|
@ -3,7 +3,7 @@ version: "2.4"
|
||||
services:
|
||||
musictopus-www:
|
||||
container_name: musictopus-www
|
||||
image: "node:16"
|
||||
image: "node:18"
|
||||
restart: always
|
||||
user: "node"
|
||||
working_dir: /home/node/app
|
||||
@ -28,6 +28,21 @@ services:
|
||||
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:
|
||||
|
@ -3,7 +3,7 @@ version: "2.4"
|
||||
services:
|
||||
musictopus-www:
|
||||
container_name: musictopus-www
|
||||
image: "node:16"
|
||||
image: "node:18"
|
||||
restart: always
|
||||
user: "node"
|
||||
working_dir: /home/node/app
|
||||
@ -28,6 +28,15 @@ services:
|
||||
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}
|
||||
networks:
|
||||
- musictopus
|
||||
musictopus-db:
|
||||
|
124
fontello.json
Normal file
124
fontello.json
Normal file
@ -0,0 +1,124 @@
|
||||
{
|
||||
"name": "icon",
|
||||
"css_prefix_text": "icon-",
|
||||
"css_use_suffix": false,
|
||||
"hinting": true,
|
||||
"units_per_em": 1000,
|
||||
"ascent": 850,
|
||||
"glyphs": [
|
||||
{
|
||||
"uid": "ca90da02d2c6a3183f2458e4dc416285",
|
||||
"css": "adjust",
|
||||
"code": 59408,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "44e04715aecbca7f266a17d5a7863c68",
|
||||
"css": "plus",
|
||||
"code": 59392,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "8b80d36d4ef43889db10bc1f0dc9a862",
|
||||
"css": "user",
|
||||
"code": 59393,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "9dd9e835aebe1060ba7190ad2b2ed951",
|
||||
"css": "search",
|
||||
"code": 59394,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "bf882b30900da12fca090d9796bc3030",
|
||||
"css": "mail",
|
||||
"code": 59395,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "0ddd3e8201ccc7d41f7b7c9d27eca6c1",
|
||||
"css": "link",
|
||||
"code": 59396,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "e15f0d620a7897e2035c18c80142f6d9",
|
||||
"css": "link-ext",
|
||||
"code": 61582,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "9bc2902722abb366a213a052ade360bc",
|
||||
"css": "spin",
|
||||
"code": 59449,
|
||||
"src": "fontelico"
|
||||
},
|
||||
{
|
||||
"uid": "bbfb51903f40597f0b70fd75bc7b5cac",
|
||||
"css": "trash",
|
||||
"code": 61944,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "d73eceadda1f594cec0536087539afbf",
|
||||
"css": "heart",
|
||||
"code": 59397,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "cce5e05853d0798a4d10077ef613387c",
|
||||
"css": "blind",
|
||||
"code": 62109,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "567e3e257f2cc8fba2c12bf691c9f2d8",
|
||||
"css": "moon",
|
||||
"code": 61830,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "aa035df0908c4665c269b7b09a5596f3",
|
||||
"css": "sun",
|
||||
"code": 61829,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "c5fd349cbd3d23e4ade333789c29c729",
|
||||
"css": "eye",
|
||||
"code": 59398,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "d870630ff8f81e6de3958ecaeac532f2",
|
||||
"css": "left-open",
|
||||
"code": 59399,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "399ef63b1e23ab1b761dfbb5591fa4da",
|
||||
"css": "right-open",
|
||||
"code": 59400,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "895405dfac8a3b7b2f23b183c6608ee6",
|
||||
"css": "export",
|
||||
"code": 59401,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "4aad6bb50b02c18508aae9cbe14e784e",
|
||||
"css": "share",
|
||||
"code": 61920,
|
||||
"src": "fontawesome"
|
||||
},
|
||||
{
|
||||
"uid": "a73c5deb486c8d66249811642e5d719a",
|
||||
"css": "refresh",
|
||||
"code": 59402,
|
||||
"src": "fontawesome"
|
||||
}
|
||||
]
|
||||
}
|
47
gulpfile.js
Normal file
47
gulpfile.js
Normal file
@ -0,0 +1,47 @@
|
||||
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/chart.js/dist/chart.umd.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);
|
||||
// ----------------------------------------------------------------------------
|
211
javascripts/ajouter-un-album.js
Normal file
211
javascripts/ajouter-un-album.js
Normal file
@ -0,0 +1,211 @@
|
||||
/* eslint-disable no-undef */
|
||||
Vue.createApp({
|
||||
data() {
|
||||
return {
|
||||
// eslint-disable-next-line no-undef
|
||||
share: canPublish,
|
||||
q: "",
|
||||
year: "",
|
||||
country: "",
|
||||
format: "",
|
||||
loading: false,
|
||||
items: [],
|
||||
details: {},
|
||||
modalIsVisible: false,
|
||||
submitting: 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",
|
||||
],
|
||||
};
|
||||
},
|
||||
created() {
|
||||
window.addEventListener("keydown", this.keyDown);
|
||||
},
|
||||
destroyed() {
|
||||
window.removeEventListener("keydown", this.keyDown);
|
||||
},
|
||||
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}`;
|
||||
}
|
||||
|
||||
return axios
|
||||
.get(url)
|
||||
.then((response) => {
|
||||
const { results } = response.data;
|
||||
const items = [];
|
||||
|
||||
for (let i = 0; i < results.length; i += 1) {
|
||||
const {
|
||||
id,
|
||||
title,
|
||||
thumb,
|
||||
year,
|
||||
country,
|
||||
format,
|
||||
genre,
|
||||
style,
|
||||
inCollection,
|
||||
} = results[i];
|
||||
items.push({
|
||||
id,
|
||||
title,
|
||||
thumb,
|
||||
year,
|
||||
country,
|
||||
format,
|
||||
genre,
|
||||
style,
|
||||
inCollection,
|
||||
});
|
||||
}
|
||||
|
||||
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() {
|
||||
if (this.submitting) {
|
||||
return true;
|
||||
}
|
||||
this.submitting = true;
|
||||
|
||||
return axios
|
||||
.post(`/api/v1/${action}`, {
|
||||
album: this.details,
|
||||
share: this.share,
|
||||
})
|
||||
.then(() => {
|
||||
window.location.href =
|
||||
action === "albums"
|
||||
? "/ma-collection"
|
||||
: "/ma-liste-de-souhaits";
|
||||
})
|
||||
.catch((err) => {
|
||||
this.submitting = false;
|
||||
showToastr(
|
||||
err.response?.data?.message ||
|
||||
"Impossible d'ajouter cet album pour le moment…"
|
||||
);
|
||||
});
|
||||
},
|
||||
orderedItems(items) {
|
||||
return items.sort();
|
||||
},
|
||||
keyDown(event) {
|
||||
const keycode = event.code;
|
||||
|
||||
if (this.modalIsVisible && keycode === "Escape") {
|
||||
event.preventDefault();
|
||||
this.modalIsVisible = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
}).mount("#ajouter-album");
|
262
javascripts/collection.js
Normal file
262
javascripts/collection.js
Normal file
@ -0,0 +1,262 @@
|
||||
/* eslint-disable no-undef */
|
||||
Vue.createApp({
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
moreFilters: false,
|
||||
items: [],
|
||||
total: 0,
|
||||
// eslint-disable-next-line no-undef
|
||||
page: query.page || 1,
|
||||
limit: 16,
|
||||
totalPages: 1,
|
||||
artist: "",
|
||||
format: "",
|
||||
year: "",
|
||||
genre: "",
|
||||
style: "",
|
||||
sortOrder: "artists_sort-asc",
|
||||
sort: "artists_sort",
|
||||
order: "asc",
|
||||
itemId: null,
|
||||
showModalDelete: false,
|
||||
showModalShare: false,
|
||||
// eslint-disable-next-line no-undef
|
||||
shareLink: `/collection/${userId}`,
|
||||
// eslint-disable-next-line no-undef
|
||||
isPublicCollection,
|
||||
// eslint-disable-next-line no-undef
|
||||
userId,
|
||||
// eslint-disable-next-line no-undef
|
||||
vueType,
|
||||
// eslint-disable-next-line no-undef
|
||||
query,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.fetch();
|
||||
|
||||
window.addEventListener("keydown", this.keyDown);
|
||||
},
|
||||
destroyed() {
|
||||
window.removeEventListener("keydown", this.keyDown);
|
||||
},
|
||||
methods: {
|
||||
formatParams(param) {
|
||||
return param.replace("&", "%26").replace("+", "%2B");
|
||||
},
|
||||
fetch() {
|
||||
this.loading = true;
|
||||
this.total = 0;
|
||||
|
||||
const queryString = window.location.search;
|
||||
const urlParams = new URLSearchParams(queryString);
|
||||
const entries = urlParams.entries();
|
||||
|
||||
const sortOrder = {
|
||||
sort: "artists_sort",
|
||||
order: "asc",
|
||||
};
|
||||
|
||||
// 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:
|
||||
if (["order", "sort"].indexOf(key) !== -1) {
|
||||
sortOrder[key] = value;
|
||||
}
|
||||
this[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
this.sortOrder = `${sortOrder.sort}-${sortOrder.order}`;
|
||||
|
||||
let url = `/api/v1/${action}?page=${this.page}&sort=${this.sort}&order=${this.order}`;
|
||||
if (this.artist) {
|
||||
url += `&artist=${this.formatParams(this.artist)}`;
|
||||
}
|
||||
if (this.format) {
|
||||
url += `&format=${this.formatParams(this.format)}`;
|
||||
}
|
||||
if (this.year) {
|
||||
url += `&year=${this.year}`;
|
||||
}
|
||||
if (this.genre) {
|
||||
url += `&genre=${this.formatParams(this.genre)}`;
|
||||
}
|
||||
if (this.style) {
|
||||
url += `&style=${this.formatParams(this.style)}`;
|
||||
}
|
||||
// INFO: Cas d'une collection partagée
|
||||
if (this.vueType === "public" && this.userId) {
|
||||
url += `&userId=${this.userId}`;
|
||||
}
|
||||
|
||||
axios
|
||||
.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) +
|
||||
(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.formatParams(this.artist)}`;
|
||||
}
|
||||
if (this.format) {
|
||||
url += `&format=${this.formatParams(this.format)}`;
|
||||
}
|
||||
if (this.year) {
|
||||
url += `&year=${this.year}`;
|
||||
}
|
||||
if (this.genre) {
|
||||
url += `&genre=${this.formatParams(this.genre)}`;
|
||||
}
|
||||
if (this.style) {
|
||||
url += `&style=${this.formatParams(this.style)}`;
|
||||
}
|
||||
|
||||
window.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() {
|
||||
// eslint-disable-next-line no-undef
|
||||
if (vueType !== "private") {
|
||||
return false;
|
||||
}
|
||||
return axios
|
||||
.delete(`/api/v1/${action}/${this.itemId}`)
|
||||
.then(() => {
|
||||
this.fetch();
|
||||
})
|
||||
.catch((err) => {
|
||||
showToastr(
|
||||
err.response?.data?.message ||
|
||||
"Impossible de supprimer cet album"
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
this.toggleModal();
|
||||
});
|
||||
},
|
||||
shareCollection() {
|
||||
// eslint-disable-next-line no-undef
|
||||
if (vueType !== "private") {
|
||||
return false;
|
||||
}
|
||||
return 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();
|
||||
});
|
||||
},
|
||||
renderAlbumTitle(item) {
|
||||
let render = "";
|
||||
|
||||
for (let i = 0; i < item.artists.length; i += 1) {
|
||||
const { name, join } = item.artists[i];
|
||||
render += `${name} ${join ? `${join} ` : ""}`;
|
||||
}
|
||||
|
||||
render += `- ${item.title}`;
|
||||
|
||||
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");
|