Initial commit - Projet Managerr
This commit is contained in:
commit
848a79a04e
36 changed files with 3850 additions and 0 deletions
455
frontend/src/views/Settings.vue
Normal file
455
frontend/src/views/Settings.vue
Normal file
|
|
@ -0,0 +1,455 @@
|
|||
<template>
|
||||
<div class="settings-page">
|
||||
<h1>Configuration</h1>
|
||||
|
||||
<div v-if="successMessage" class="alert alert-success">
|
||||
{{ successMessage }}
|
||||
</div>
|
||||
|
||||
<div v-if="errorMessage" class="alert alert-danger">
|
||||
{{ errorMessage }}
|
||||
</div>
|
||||
|
||||
<div class="settings-card">
|
||||
<h2>Configuration API</h2>
|
||||
<p>Configurez les URLs et les clés API pour Sonarr et Radarr</p>
|
||||
|
||||
<form @submit.prevent="saveSettings" class="settings-form">
|
||||
<div class="settings-section">
|
||||
<h3>Sonarr</h3>
|
||||
<div class="form-group">
|
||||
<label for="sonarr-url">URL de l'API Sonarr</label>
|
||||
<input
|
||||
type="url"
|
||||
id="sonarr-url"
|
||||
v-model="settings.sonarr.url"
|
||||
placeholder="http://localhost:8989/api/v3"
|
||||
required
|
||||
>
|
||||
<small class="form-text">L'URL de base de l'API Sonarr (exemple: http://localhost:8989/api/v3)</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sonarr-key">Clé API Sonarr</label>
|
||||
<div class="api-key-input">
|
||||
<input
|
||||
:type="showSonarrKey ? 'text' : 'password'"
|
||||
id="sonarr-key"
|
||||
v-model="settings.sonarr.apiKey"
|
||||
placeholder="Votre clé API Sonarr"
|
||||
required
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="toggle-visibility"
|
||||
@click="showSonarrKey = !showSonarrKey"
|
||||
>
|
||||
{{ showSonarrKey ? '🔒' : '👁️' }}
|
||||
</button>
|
||||
</div>
|
||||
<small class="form-text">Disponible dans les paramètres de Sonarr sous "Général"</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="button" class="test-button" @click="testConnection('sonarr')">
|
||||
Tester la connexion
|
||||
</button>
|
||||
<span v-if="sonarrStatus === 'success'" class="status-text success">Connexion réussie ✓</span>
|
||||
<span v-if="sonarrStatus === 'error'" class="status-text error">Échec de connexion ✗</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-section">
|
||||
<h3>Radarr</h3>
|
||||
<div class="form-group">
|
||||
<label for="radarr-url">URL de l'API Radarr</label>
|
||||
<input
|
||||
type="url"
|
||||
id="radarr-url"
|
||||
v-model="settings.radarr.url"
|
||||
placeholder="http://localhost:7878/api/v3"
|
||||
required
|
||||
>
|
||||
<small class="form-text">L'URL de base de l'API Radarr (exemple: http://localhost:7878/api/v3)</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="radarr-key">Clé API Radarr</label>
|
||||
<div class="api-key-input">
|
||||
<input
|
||||
:type="showRadarrKey ? 'text' : 'password'"
|
||||
id="radarr-key"
|
||||
v-model="settings.radarr.apiKey"
|
||||
placeholder="Votre clé API Radarr"
|
||||
required
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="toggle-visibility"
|
||||
@click="showRadarrKey = !showRadarrKey"
|
||||
>
|
||||
{{ showRadarrKey ? '🔒' : '👁️' }}
|
||||
</button>
|
||||
</div>
|
||||
<small class="form-text">Disponible dans les paramètres de Radarr sous "Général"</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="button" class="test-button" @click="testConnection('radarr')">
|
||||
Tester la connexion
|
||||
</button>
|
||||
<span v-if="radarrStatus === 'success'" class="status-text success">Connexion réussie ✓</span>
|
||||
<span v-if="radarrStatus === 'error'" class="status-text error">Échec de connexion ✗</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="save-button" :disabled="isSaving">
|
||||
{{ isSaving ? 'Enregistrement...' : 'Enregistrer les paramètres' }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
const API_URL = process.env.VUE_APP_API_URL || 'http://localhost:5000/api'
|
||||
|
||||
export default {
|
||||
name: 'SettingsPage',
|
||||
data() {
|
||||
return {
|
||||
settings: {
|
||||
sonarr: {
|
||||
url: '',
|
||||
apiKey: ''
|
||||
},
|
||||
radarr: {
|
||||
url: '',
|
||||
apiKey: ''
|
||||
}
|
||||
},
|
||||
showSonarrKey: false,
|
||||
showRadarrKey: false,
|
||||
sonarrStatus: null,
|
||||
radarrStatus: null,
|
||||
successMessage: '',
|
||||
errorMessage: '',
|
||||
isSaving: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loadSettings()
|
||||
},
|
||||
methods: {
|
||||
async loadSettings() {
|
||||
try {
|
||||
const token = localStorage.getItem('token')
|
||||
if (!token) {
|
||||
this.$router.push('/login')
|
||||
return
|
||||
}
|
||||
|
||||
const response = await axios.get(`${API_URL}/settings`, {
|
||||
headers: {
|
||||
'x-auth-token': token
|
||||
}
|
||||
})
|
||||
|
||||
if (response.data) {
|
||||
// Si des paramètres existent déjà, les charger
|
||||
if (response.data.sonarr) {
|
||||
this.settings.sonarr = response.data.sonarr
|
||||
}
|
||||
if (response.data.radarr) {
|
||||
this.settings.radarr = response.data.radarr
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur lors du chargement des paramètres:', error)
|
||||
// Si c'est la première fois que l'utilisateur configure l'app, il n'y aura pas de paramètres
|
||||
// Donc on ne montre pas d'erreur
|
||||
}
|
||||
},
|
||||
async testConnection(type) {
|
||||
try {
|
||||
const token = localStorage.getItem('token')
|
||||
if (!token) {
|
||||
this.$router.push('/login')
|
||||
return
|
||||
}
|
||||
|
||||
const apiSettings = this.settings[type]
|
||||
const response = await axios.post(
|
||||
`${API_URL}/settings/test-connection`,
|
||||
{
|
||||
type,
|
||||
url: apiSettings.url,
|
||||
apiKey: apiSettings.apiKey
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'x-auth-token': token
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
if (response.data.success) {
|
||||
this[`${type}Status`] = 'success'
|
||||
setTimeout(() => {
|
||||
this[`${type}Status`] = null
|
||||
}, 3000)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Erreur lors du test de connexion ${type}:`, error)
|
||||
this[`${type}Status`] = 'error'
|
||||
setTimeout(() => {
|
||||
this[`${type}Status`] = null
|
||||
}, 3000)
|
||||
}
|
||||
},
|
||||
async saveSettings() {
|
||||
try {
|
||||
this.isSaving = true
|
||||
this.successMessage = ''
|
||||
this.errorMessage = ''
|
||||
|
||||
const token = localStorage.getItem('token')
|
||||
if (!token) {
|
||||
this.$router.push('/login')
|
||||
return
|
||||
}
|
||||
|
||||
await axios.post(
|
||||
`${API_URL}/settings`,
|
||||
this.settings,
|
||||
{
|
||||
headers: {
|
||||
'x-auth-token': token
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
this.successMessage = 'Configuration enregistrée avec succès'
|
||||
setTimeout(() => {
|
||||
this.successMessage = ''
|
||||
}, 3000)
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de l\'enregistrement des paramètres:', error)
|
||||
this.errorMessage = 'Une erreur est survenue lors de l\'enregistrement des paramètres'
|
||||
setTimeout(() => {
|
||||
this.errorMessage = ''
|
||||
}, 3000)
|
||||
} finally {
|
||||
this.isSaving = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.settings-page {
|
||||
padding: 2rem;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 2rem;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: var(--text-color);
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: var(--text-color);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding-bottom: 0.5rem;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.settings-card {
|
||||
background-color: var(--card-bg);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px var(--shadow-color);
|
||||
padding: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.settings-section {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
background-color: var(--input-bg);
|
||||
color: var(--input-text);
|
||||
}
|
||||
|
||||
.api-key-input {
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.api-key-input input {
|
||||
padding-right: 3rem;
|
||||
}
|
||||
|
||||
.toggle-visibility {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 3rem;
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.form-text {
|
||||
display: block;
|
||||
margin-top: 0.5rem;
|
||||
font-size: 0.85rem;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
.test-button {
|
||||
background-color: var(--info-bg);
|
||||
color: var(--info-text);
|
||||
border: none;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.test-button:hover {
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
|
||||
.status-text {
|
||||
margin-left: 1rem;
|
||||
font-weight: 500;
|
||||
animation: fadeIn 0.3s;
|
||||
}
|
||||
|
||||
.status-text.success {
|
||||
color: var(--success-text);
|
||||
}
|
||||
|
||||
.status-text.error {
|
||||
color: var(--danger-text);
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.save-button {
|
||||
background-color: var(--button-primary-bg);
|
||||
color: var(--button-primary-text);
|
||||
border: none;
|
||||
padding: 0.75rem 1.5rem;
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.save-button:hover {
|
||||
filter: brightness(1.1);
|
||||
}
|
||||
|
||||
.save-button:disabled {
|
||||
opacity: 0.7;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
border-radius: 4px;
|
||||
animation: fadeIn 0.3s;
|
||||
}
|
||||
|
||||
.alert-success {
|
||||
background-color: var(--success-bg);
|
||||
color: var(--success-text);
|
||||
}
|
||||
|
||||
.alert-danger {
|
||||
background-color: var(--danger-bg);
|
||||
color: var(--danger-text);
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
/* Styles responsifs */
|
||||
@media (max-width: 768px) {
|
||||
.settings-page {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.settings-card {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.settings-page {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.settings-card {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.save-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
display: block;
|
||||
margin-left: 0;
|
||||
margin-top: 0.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Add table
Add a link
Reference in a new issue