Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81db5f9708 | ||
|
|
fee34c79dd | ||
|
|
5caf22e19a | ||
|
|
b6a01a7f5f | ||
|
|
eba0adc03e | ||
|
|
5220af5111 | ||
|
|
be1901d40d | ||
|
|
c53de3acfe | ||
|
|
ed6b188679 | ||
|
|
6b5f91d977 | ||
|
|
6642328f2a | ||
|
|
f544c621e4 | ||
|
|
940513dc32 | ||
|
|
24c50dda29 | ||
|
|
fb78736a83 | ||
|
|
3d7449d871 | ||
|
|
c71f962967 | ||
|
|
525dc5748f | ||
|
|
1606d4c28b | ||
|
|
c15ab30c7a | ||
|
|
f3a7aafe87 | ||
|
|
195e1ba946 | ||
|
|
e2041421f6 | ||
|
|
287c184fa9 | ||
|
|
11abac2e33 | ||
|
|
c347180aae | ||
|
|
cebeb61b94 | ||
|
|
7ac852426e | ||
|
|
7647ec058c | ||
|
|
bd8a061a17 | ||
|
|
9ce569aabe | ||
|
|
d9ee11af79 | ||
|
|
4b8cfe923c | ||
|
|
0a719c0b66 | ||
|
|
3860e7948c | ||
|
|
ed91c68de9 | ||
|
|
79d52b3a4d | ||
|
|
5f61940c92 | ||
|
|
a6694d81d8 | ||
|
|
f5454b07e8 | ||
|
|
a50c43cab0 |
@@ -1,2 +1,2 @@
|
||||
export const REPO_URL = 'ajnart/homarr';
|
||||
export const CURRENT_VERSION = 'v0.10.4';
|
||||
export const CURRENT_VERSION = 'v0.10.6';
|
||||
|
||||
20
package.json
20
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "homarr",
|
||||
"version": "0.10.4",
|
||||
"version": "0.10.6",
|
||||
"description": "Homarr - A homepage for your server.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -30,17 +30,17 @@
|
||||
"@dnd-kit/core": "^6.0.5",
|
||||
"@dnd-kit/sortable": "^7.0.1",
|
||||
"@dnd-kit/utilities": "^3.2.0",
|
||||
"@emotion/react": "^11.10.0",
|
||||
"@emotion/react": "^11.10.5",
|
||||
"@emotion/server": "^11.10.0",
|
||||
"@mantine/carousel": "^5.1.0",
|
||||
"@mantine/core": "^5.2.3",
|
||||
"@mantine/dates": "^5.2.3",
|
||||
"@mantine/dropzone": "^5.2.3",
|
||||
"@mantine/form": "^5.2.3",
|
||||
"@mantine/hooks": "^5.2.3",
|
||||
"@mantine/modals": "^5.2.3",
|
||||
"@mantine/core": "^5.7.2",
|
||||
"@mantine/dates": "^5.7.2",
|
||||
"@mantine/dropzone": "^5.7.2",
|
||||
"@mantine/form": "^5.7.2",
|
||||
"@mantine/hooks": "^5.7.2",
|
||||
"@mantine/modals": "^5.7.2",
|
||||
"@mantine/next": "^5.2.3",
|
||||
"@mantine/notifications": "^5.2.3",
|
||||
"@mantine/notifications": "^5.7.2",
|
||||
"@mantine/prism": "^5.0.0",
|
||||
"@nivo/core": "^0.79.0",
|
||||
"@nivo/line": "^0.79.1",
|
||||
@@ -50,7 +50,7 @@
|
||||
"axios": "^0.27.2",
|
||||
"consola": "^2.15.3",
|
||||
"cookies-next": "^2.1.1",
|
||||
"dayjs": "^1.11.5",
|
||||
"dayjs": "^1.11.6",
|
||||
"dockerode": "^3.3.2",
|
||||
"embla-carousel-react": "^7.0.0",
|
||||
"framer-motion": "^6.5.1",
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Søg på nettet..."
|
||||
}
|
||||
},
|
||||
"switched-to": "Skiftet til",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "Web",
|
||||
"description": "Søg ved hjælp af din søgemaskine (defineret i indstillinger)"
|
||||
},
|
||||
"youtube": {
|
||||
"name": "YouTube",
|
||||
"description": "Søg på YouTube"
|
||||
},
|
||||
"torrents": {
|
||||
"name": "Torrents",
|
||||
"description": "Søg efter torrents"
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": "Søg efter film og tv-serier ved hjælp af Overseerr (modul skal være aktiveret)"
|
||||
}
|
||||
},
|
||||
"tip": "Du kan vælge søgefeltet med genvejen ",
|
||||
"switchedSearchEngine": "Skiftede til søgning med {{searchEngine}}"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Usenet",
|
||||
"description": "Giver dig mulighed for at se din usenet (Sabnzbd eller NZBGet) kø og historik, pause og genoptage downloads"
|
||||
"description": "Tillader dig at se din usenet (Sabnzbd eller NZBGet) kø og historie, pause og genoptage downloads"
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Das Internet durchsuchen..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Usenet",
|
||||
"description": "Ermöglicht es Ihnen, Ihre Usenet-Warteschlange (Sabnzbd oder NZBGet) und den Verlauf anzuzeigen, Downloads anzuhalten und fortzusetzen"
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Search the web..."
|
||||
}
|
||||
},
|
||||
"switched-to": "Switched to",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "Web",
|
||||
"description": "Search using your search engine (defined in settings)"
|
||||
},
|
||||
"youtube": {
|
||||
"name": "Youtube",
|
||||
"description": "Search on Youtube"
|
||||
},
|
||||
"torrents": {
|
||||
"name": "Torrents",
|
||||
"description": "Search for Torrents"
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": "Search for Movies and TV Shows using Overseerr (module must be enabled)"
|
||||
}
|
||||
},
|
||||
"tip": "You can select the search bar with the shortcut ",
|
||||
"switchedSearchEngine": "Switched to searching with {{searchEngine}}"
|
||||
}
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Buscar en Internet..."
|
||||
}
|
||||
},
|
||||
"switched-to": "Cambiado a",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "Web",
|
||||
"description": "Buscar usando tu motor de búsqueda (definido en ajustes)"
|
||||
},
|
||||
"youtube": {
|
||||
"name": "Youtube",
|
||||
"description": "Buscar en Youtube"
|
||||
},
|
||||
"torrents": {
|
||||
"name": "Torrents",
|
||||
"description": "Buscar Torrents"
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": "Buscar Películas y Series TV usando Overseerr (el módulo debe esta activado)"
|
||||
}
|
||||
},
|
||||
"tip": "Puedes seleccionar la barra de búsqueda con el atajo ",
|
||||
"switchedSearchEngine": "Cambiado a buscando con {{searchEngine}}"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Usenet",
|
||||
"description": "Le permite ver la cola y el historial de usenet (Sabnzbd o NZBGet), pausar y reanudar las descargas"
|
||||
"description": "Te permite ver la cola e historial de tu usenet (Sabnzbd or NZBGet), pausar y reanudar descargas"
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"accordions": {
|
||||
"downloads": {
|
||||
"text": "Vos téléchargements",
|
||||
"torrents": "",
|
||||
"usenet": ""
|
||||
"torrents": "Vos téléchargements Torrents",
|
||||
"usenet": "Vos téléchargements Usenet"
|
||||
},
|
||||
"others": {
|
||||
"text": "Autres"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Docker",
|
||||
"description": ""
|
||||
"description": "Vous permet de gérer facilement vos conteneurs docker"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "Recherche par nom de conteneur ou d'image"
|
||||
@@ -49,20 +49,20 @@
|
||||
},
|
||||
"actions": {
|
||||
"start": {
|
||||
"start": "",
|
||||
"end": ""
|
||||
"start": "Démarrage en cours",
|
||||
"end": "Démarré"
|
||||
},
|
||||
"stop": {
|
||||
"start": "",
|
||||
"start": "Arrêt en cours",
|
||||
"end": "Arrêté"
|
||||
},
|
||||
"restart": {
|
||||
"start": "",
|
||||
"end": ""
|
||||
"start": "Redémarrage en cours",
|
||||
"end": "Redémarré"
|
||||
},
|
||||
"remove": {
|
||||
"start": "",
|
||||
"end": ""
|
||||
"start": "Suppression en cours",
|
||||
"end": "Supprimé"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Cherchez sur le web..."
|
||||
}
|
||||
},
|
||||
"switched-to": "Basculé vers",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "Web",
|
||||
"description": "Recherche à l'aide de votre moteur de recherche (défini dans les paramètres)"
|
||||
},
|
||||
"youtube": {
|
||||
"name": "YouTube",
|
||||
"description": "Cherchez sur YouTube"
|
||||
},
|
||||
"torrents": {
|
||||
"name": "Torrents",
|
||||
"description": "Chercher des torrents"
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": "Chercher des films et séries TV avec Overseerr (le module doit-être activé)"
|
||||
}
|
||||
},
|
||||
"tip": "Vous pouvez sélectionner la barre de recherche avec le raccourci ",
|
||||
"switchedSearchEngine": "Basculer vers la recherche avec {{searchEngine}}"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Usenet",
|
||||
"description": "Vous permet de voir votre file d'attente et votre historique Usenet (Sabnzbd ou NZBGet), de mettre en pause et de reprendre les téléchargements"
|
||||
"description": "Permet de voir la file d'attente et l'historique de vos téléchargements usenet (Sabnzbd ou NZBGet), de mettre en pause et de reprendre les téléchargements"
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
"placeholder": "URL de requête personnalisée"
|
||||
},
|
||||
"searchNewTab": {
|
||||
"label": ""
|
||||
"label": "Ouvrir les résultats de la recherche dans un nouvel onglet"
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,8 @@
|
||||
},
|
||||
"lineChart": {
|
||||
"title": "מהירות הורדה נוכחית",
|
||||
"download": "הורדה ממתינה",
|
||||
"upload": "העלאה ממתינה",
|
||||
"download": "הורדה",
|
||||
"upload": "העלאה",
|
||||
"timeSpan": "לפני שניות",
|
||||
"totalDownload": "הורדה ממתינה",
|
||||
"totalUpload": "העלאה ממתינה"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"table": {
|
||||
"header": {
|
||||
"name": "שם",
|
||||
"image": "תמונה",
|
||||
"image": "קובץ תמונה",
|
||||
"ports": "יציאות",
|
||||
"state": "מצב"
|
||||
},
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "זמן תגובה",
|
||||
"name": "פינג",
|
||||
"description": "מאפשר בדיקה אם השירות פעיל או מחזיר קוד ספציפי של HTTP"
|
||||
},
|
||||
"states": {
|
||||
"online": "מקון",
|
||||
"offline": "לא מקון",
|
||||
"online": "מקוון",
|
||||
"offline": "לא מקוון",
|
||||
"loading": "טוען..."
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "חפש באינטרנט..."
|
||||
}
|
||||
},
|
||||
"switched-to": "להחליף ל",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "אינטרנט",
|
||||
"description": "חיפוש באמצעות מנוע החיפוש שלך (מוגדר בהגדרות)"
|
||||
},
|
||||
"youtube": {
|
||||
"name": "יוטיוב",
|
||||
"description": "חפש ביוטיוב"
|
||||
},
|
||||
"torrents": {
|
||||
"name": "טורנטים",
|
||||
"description": "חיפוש אחר טורנטים"
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": "חיפוש סרטים ותוכניות טלוויזיה באמצעות Overseerr (המודול חייב להיות מאופשר)"
|
||||
}
|
||||
},
|
||||
"tip": "באפשרותך לבחור את סרגל החיפוש באמצעות קיצור הדרך",
|
||||
"switchedSearchEngine": "עבור לחיפוש עם"
|
||||
}
|
||||
@@ -24,8 +24,8 @@
|
||||
},
|
||||
"lineChart": {
|
||||
"title": "מהירות הורדה נוכחית",
|
||||
"download": "הורדה ממתינה",
|
||||
"upload": "העלאה ממתינה",
|
||||
"download": "הורדה",
|
||||
"upload": "העלאה",
|
||||
"timeSpan": "לפני שניות",
|
||||
"totalDownload": "הורדה ממתינה",
|
||||
"totalUpload": "העלאה ממתינה"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Sabnzbd",
|
||||
"description": "מאמאפשר לך לראות את התור וההיסטוריה של usenet (Sabnzbd או NZBGet), להשהות ולחדש הורדות"
|
||||
"name": "קבוצת דיון",
|
||||
"description": "מאפשר צפייה בהיסטוריה, תור ההורדות, עצירה וחידוש הורדות בקבוצות הדיון (Sabnzbd או NZBGet)"
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"title": "Bentornato!",
|
||||
"title": "Bentornati!",
|
||||
"text": "Inserisci la password",
|
||||
"form": {
|
||||
"fields": {
|
||||
@@ -21,7 +21,7 @@
|
||||
"title": "Password corretta, reindirizzamento..."
|
||||
},
|
||||
"wrong": {
|
||||
"title": "Password errata. Per favore, prova di nuovo."
|
||||
"title": "Password errata. Per favore riprova."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"actionIcon": {
|
||||
"tooltip": "Aggiungere un servizio"
|
||||
"tooltip": "Aggiungi un servizio"
|
||||
},
|
||||
"modal": {
|
||||
"title": "Aggiungi servizio",
|
||||
"form": {
|
||||
"validation": {
|
||||
"invalidUrl": "Inserire un URL valido",
|
||||
"noStatusCodeSelected": "Selezionare un codice di stato"
|
||||
"noStatusCodeSelected": "Scegliere uno status code"
|
||||
}
|
||||
},
|
||||
"tabs": {
|
||||
@@ -15,28 +15,28 @@
|
||||
"title": "Opzioni",
|
||||
"form": {
|
||||
"serviceName": {
|
||||
"label": "Nome del servizio",
|
||||
"label": "Nome servizio",
|
||||
"placeholder": "Plex"
|
||||
},
|
||||
"iconUrl": {
|
||||
"label": "Icona URL"
|
||||
"label": "URL dell'icona"
|
||||
},
|
||||
"serviceUrl": {
|
||||
"label": "URL del servizio"
|
||||
"label": "URL servizio"
|
||||
},
|
||||
"onClickUrl": {
|
||||
"label": "URL di destinatione"
|
||||
"label": "URL di destinazione"
|
||||
},
|
||||
"serviceType": {
|
||||
"label": "Tipo di servizio",
|
||||
"label": "Tipologia servizio",
|
||||
"defaultValue": "Altro",
|
||||
"placeholder": "Scegli Uno"
|
||||
"placeholder": "Sceglierne uno"
|
||||
},
|
||||
"category": {
|
||||
"label": "Categoria",
|
||||
"placeholder": "Selezionare una categoria o crearne una nuova",
|
||||
"nothingFound": "Non è stato trovato nulla",
|
||||
"createLabel": "+ Creare {{query}}"
|
||||
"placeholder": "Seleziona una categoria o creane una nuova",
|
||||
"nothingFound": "Nessun risultato",
|
||||
"createLabel": "+ Crea {{query}}"
|
||||
},
|
||||
"integrations": {
|
||||
"apiKey": {
|
||||
@@ -46,7 +46,7 @@
|
||||
"noKey": "Chiave non valida"
|
||||
},
|
||||
"tip": {
|
||||
"text": "Ottenere la chiave API",
|
||||
"text": "Ottieni la tua chiave API",
|
||||
"link": "qui."
|
||||
}
|
||||
},
|
||||
@@ -111,16 +111,16 @@
|
||||
}
|
||||
},
|
||||
"advancedOptions": {
|
||||
"title": "Opzioni avanzate",
|
||||
"title": "Impostazioni avanzate",
|
||||
"form": {
|
||||
"httpStatusCodes": {
|
||||
"label": "Codici di stato HTTP",
|
||||
"placeholder": "Selezionare i codici di stato validi",
|
||||
"clearButtonLabel": "Cancella la selezione",
|
||||
"nothingFound": "Non è stato trovato nulla"
|
||||
"label": "Status Codes HTTP",
|
||||
"placeholder": "Selezionare status codes validi",
|
||||
"clearButtonLabel": "Elimina selezione",
|
||||
"nothingFound": "Nessun risultato"
|
||||
},
|
||||
"openServiceInNewTab": {
|
||||
"label": "Aprire il servizio in una nuova scheda"
|
||||
"label": "Apri servizio in una nuova scheda"
|
||||
},
|
||||
"buttons": {
|
||||
"submit": {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"modal": {
|
||||
"title": "Modificare un servizio",
|
||||
"title": "Modifica un servizio",
|
||||
"buttons": {
|
||||
"save": "Salvataggio del servizio"
|
||||
"save": "Salva servizio"
|
||||
}
|
||||
},
|
||||
"menu": {
|
||||
"labels": {
|
||||
"settings": "Impostazioni",
|
||||
"dangerZone": "Zona di pericolo"
|
||||
"dangerZone": "Danger zone"
|
||||
},
|
||||
"actions": {
|
||||
"edit": "Modifica",
|
||||
"delete": "Cancella"
|
||||
"delete": "Elimina"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
"accordions": {
|
||||
"downloads": {
|
||||
"text": "I tuoi download",
|
||||
"torrents": "Scaricamenti di Torrent",
|
||||
"usenet": "I tuoi scaricamenti di Usenet"
|
||||
"torrents": "I tuoi torrent",
|
||||
"usenet": "I tuoi download di Usenet"
|
||||
},
|
||||
"others": {
|
||||
"text": "Altri"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Calendario",
|
||||
"description": "Un calendario per la visualizzazione dei prossimi rilasci. Interagisce con le API di Sonarr e Radarr.",
|
||||
"description": "Un calendario per la visualizzazione delle prossime uscite. Può comunicare con le API di Sonarr e Radarr.",
|
||||
"settings": {
|
||||
"sundayStart": {
|
||||
"label": "Inizio settimana di domenica"
|
||||
"label": "Inizia la settimana di domenica"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"buttons": {
|
||||
"play": "Avvia",
|
||||
"request": "Richiedi"
|
||||
"play": "Riproduci",
|
||||
"request": "Richiesta"
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Dash.",
|
||||
"description": "Un modulo per visualizzare i grafici dell'istanza di Dash in esecuzione.",
|
||||
"description": "Un modulo per visualizzare i grafici dell'istanza di Dash. in esecuzione.",
|
||||
"settings": {
|
||||
"cpuMultiView": {
|
||||
"label": "Vista CPU Multi-Core"
|
||||
},
|
||||
"storageMultiView": {
|
||||
"label": "Visualizzazione dell'unità multipla di archiviazione"
|
||||
"label": "Visualizzazione archiviazione Multi-Drive"
|
||||
},
|
||||
"useCompactView": {
|
||||
"label": "Visualizzazione compatta"
|
||||
@@ -23,8 +23,8 @@
|
||||
"card": {
|
||||
"title": "Dash.",
|
||||
"errors": {
|
||||
"noService": "Nessun servizio Dash. trovato. Aggiungerne uno alla dashboard di Homarr o impostare un Dash. nelle opzioni del modulo",
|
||||
"noInformation": "Impossibile acquisire informazioni da dash. - state eseguendo l'ultima versione?"
|
||||
"noService": "Nessun servizio Dash. trovato. Aggiungine uno alla dashboard di Homarr o imposta un URL nelle impostazioni del modulo",
|
||||
"noInformation": "Impossibile reperire informazioni da dash. - è in esecuzione l'ultima versione?"
|
||||
},
|
||||
"graphs": {
|
||||
"storage": {
|
||||
@@ -35,8 +35,8 @@
|
||||
"title": "Rete",
|
||||
"label": "Rete:",
|
||||
"metrics": {
|
||||
"download": "In basso",
|
||||
"upload": "Su"
|
||||
"download": "Down",
|
||||
"upload": "Up"
|
||||
}
|
||||
},
|
||||
"cpu": {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"description": "Mostra l'ora e la data corrente in una scheda",
|
||||
"settings": {
|
||||
"display24HourFormat": {
|
||||
"label": "Visualizzazione a tempo pieno (24 ore)"
|
||||
"label": "Visualizza formato 24 ore"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Velocità Di Download",
|
||||
"description": "Mostra la velocità di download attuale dei servizi supportati"
|
||||
"description": "Mostra la velocità di download corrente dei servizi supportati"
|
||||
},
|
||||
"card": {
|
||||
"table": {
|
||||
"header": {
|
||||
"name": "Nome",
|
||||
"size": "Dimensione",
|
||||
"download": "In basso",
|
||||
"upload": "Su",
|
||||
"download": "Down",
|
||||
"upload": "Up",
|
||||
"estimatedTimeOfArrival": "ETA",
|
||||
"progress": "Avanzamento"
|
||||
},
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
},
|
||||
"lineChart": {
|
||||
"title": "Velocità di download attuale",
|
||||
"title": "Velocità di download",
|
||||
"download": "Download: {{download}}",
|
||||
"upload": "Upload: {{upload}}",
|
||||
"timeSpan": "{{seconds}} secondi fa",
|
||||
@@ -28,7 +28,7 @@
|
||||
"errors": {
|
||||
"noDownloadClients": {
|
||||
"title": "Nessun client di download supportato trovato!",
|
||||
"text": "Aggiungere un servizio di download per visualizzare i download correnti"
|
||||
"text": "Aggiungi un servizio di download per visualizzare i tuoi download attuali"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Docker",
|
||||
"description": "Ti permette di gestire facilmente i tuoi container docker"
|
||||
"description": "Gestisci facilmente i tuoi container di docker"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "Ricerca per contenitore o nome dell'immagine"
|
||||
"placeholder": "Ricerca per container nome immagine"
|
||||
},
|
||||
"table": {
|
||||
"header": {
|
||||
@@ -14,7 +14,7 @@
|
||||
"state": "Stato"
|
||||
},
|
||||
"body": {
|
||||
"portCollapse": "{{ports}} di più"
|
||||
"portCollapse": "{{ports}} altro"
|
||||
},
|
||||
"states": {
|
||||
"running": "In esecuzione",
|
||||
@@ -38,13 +38,13 @@
|
||||
"title": "Avvia"
|
||||
},
|
||||
"refreshData": {
|
||||
"title": "Aggiornare i dati"
|
||||
"title": "Aggiorna dati"
|
||||
},
|
||||
"remove": {
|
||||
"title": "Rimuovi"
|
||||
},
|
||||
"addToHomarr": {
|
||||
"title": "Aggiungi a Homarr"
|
||||
"title": "Aggiungi ad Homarr"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
@@ -61,13 +61,13 @@
|
||||
"end": "Riavviato"
|
||||
},
|
||||
"remove": {
|
||||
"start": "Rimozione",
|
||||
"start": "Rimozione in corso",
|
||||
"end": "Rimosso"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"integrationFailed": {
|
||||
"title": "Integrazione di Docker fallita",
|
||||
"title": "Integrazione Docker fallita",
|
||||
"message": "Hai dimenticato di montare il socket di docker?"
|
||||
},
|
||||
"unknownError": {
|
||||
|
||||
@@ -8,17 +8,17 @@
|
||||
"buttons": {
|
||||
"askFor": "Richiedi {{title}}",
|
||||
"cancel": "Annulla",
|
||||
"request": "Richiedi"
|
||||
"request": "Richiesta"
|
||||
},
|
||||
"alerts": {
|
||||
"automaticApproval": {
|
||||
"title": "Utilizzo della chiave API",
|
||||
"title": "Chiave API in uso",
|
||||
"text": "Questa richiesta verrà approvata automaticamente"
|
||||
}
|
||||
}
|
||||
},
|
||||
"seasonSelector": {
|
||||
"caption": "Spuntare le stagioni che si desidera scaricare.",
|
||||
"caption": "Seleziona le stagioni che desideri scaricare",
|
||||
"table": {
|
||||
"header": {
|
||||
"season": "Stagione",
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Ping",
|
||||
"description": "Consente di verificare se il servizio è attivo o se restituisce un codice di stato HTTP specifico."
|
||||
"description": "Consente di controllare se il servizio è attivo o restituisce uno specifico status code HTTP."
|
||||
},
|
||||
"states": {
|
||||
"online": "Online {{response}}",
|
||||
"offline": "Offline {{response}}",
|
||||
"loading": "Caricamento..."
|
||||
"loading": "Caricamento in corso..."
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,30 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Barra di ricerca",
|
||||
"description": "Barra di ricerca per cercare sul web, su Youtube, su Torrents o su Overseerr"
|
||||
"description": "Barra di ricerca per cercare sul web, Youtube, Torrent o Overseerr"
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Cerca sul web..."
|
||||
}
|
||||
},
|
||||
"switched-to": "Impostato su",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "Web",
|
||||
"description": "Cerca usando il tuo motore di ricerca (definito nelle impostazioni)"
|
||||
},
|
||||
"youtube": {
|
||||
"name": "Youtube",
|
||||
"description": "Cerca su YouTube"
|
||||
},
|
||||
"torrents": {
|
||||
"name": "Torrents",
|
||||
"description": "Cerca Torrents"
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": "Cerca film e serie TV con Overseerr (il modulo deve essere abilitato)"
|
||||
}
|
||||
},
|
||||
"tip": "Puoi selezionare la barra di ricerca con la scorciatoia ",
|
||||
"switchedSearchEngine": "Ricerca cambiata con {{searchEngine}}"
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Torrent",
|
||||
"description": "Mostra la velocità di download attuale dei servizi supportati",
|
||||
"description": "Mostra la velocità di download corrente dei servizi supportati",
|
||||
"settings": {
|
||||
"hideComplete": {
|
||||
"label": "Nascondere i torrent completati"
|
||||
"label": "Nascondi torrent completati"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -13,8 +13,8 @@
|
||||
"header": {
|
||||
"name": "Nome",
|
||||
"size": "Dimensione",
|
||||
"download": "In basso",
|
||||
"upload": "Su",
|
||||
"download": "Down",
|
||||
"upload": "Up",
|
||||
"estimatedTimeOfArrival": "ETA",
|
||||
"progress": "Avanzamento"
|
||||
},
|
||||
@@ -23,7 +23,7 @@
|
||||
}
|
||||
},
|
||||
"lineChart": {
|
||||
"title": "Velocità di download attuale",
|
||||
"title": "Velocità di download",
|
||||
"download": "Download: {{download}}",
|
||||
"upload": "Upload: {{upload}}",
|
||||
"timeSpan": "{{seconds}} secondi fa",
|
||||
@@ -33,7 +33,7 @@
|
||||
"errors": {
|
||||
"noDownloadClients": {
|
||||
"title": "Nessun client di download supportato trovato!",
|
||||
"text": "Aggiungere un servizio di download per visualizzare i download correnti"
|
||||
"text": "Aggiungi un servizio di download per visualizzare i tuoi download attuali"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Usenet",
|
||||
"description": "Ti consente di vedere la coda e la cronologia di usenet (Sabnzbd o NZBGet), mettere in pausa e riprendere i download."
|
||||
"description": "Permette di vedere la coda e la cronologia di usenet (Sabnzbd o NZBGet), di mettere in pausa e riprendere i download"
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
"noDownloadClients": {
|
||||
"title": "Nessun client di download supportato trovato!",
|
||||
"text": "Aggiungere un servizio di download per visualizzare i download correnti"
|
||||
"text": "Aggiungi un servizio di download per visualizzare i tuoi download attuali"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,26 +4,26 @@
|
||||
"description": "Consulta il meteo attuale della propria località",
|
||||
"settings": {
|
||||
"displayInFahrenheit": {
|
||||
"label": "Visualizzazione in Fahrenheit"
|
||||
"label": "Mostra in Fahrenheit"
|
||||
},
|
||||
"location": {
|
||||
"label": "Posizione meteo"
|
||||
"label": "Località meteo"
|
||||
}
|
||||
}
|
||||
},
|
||||
"card": {
|
||||
"weatherDescriptions": {
|
||||
"clear": "Cancella",
|
||||
"mainlyClear": "Sereno",
|
||||
"clear": "Sereno",
|
||||
"mainlyClear": "Per lo più sereno",
|
||||
"fog": "Nebbia",
|
||||
"drizzle": "Pioggerella",
|
||||
"freezingDrizzle": "Pioggia gelata",
|
||||
"drizzle": "Pioggia leggera",
|
||||
"freezingDrizzle": "Pioggia leggera gelata",
|
||||
"rain": "Pioggia",
|
||||
"freezingRain": "Pioggia gelata",
|
||||
"snowFall": "Caduta della neve",
|
||||
"snowGrains": "Granelli di neve",
|
||||
"rainShowers": "Piogge a catinelle",
|
||||
"snowShowers": "Piogge di neve",
|
||||
"snowFall": "Neve",
|
||||
"snowGrains": "Neve tonda",
|
||||
"rainShowers": "Rovesci",
|
||||
"snowShowers": "Forti nevicate",
|
||||
"thunderstorm": "Temporale",
|
||||
"thunderstormWithHail": "Temporale con grandine",
|
||||
"unknown": "Sconosciuto"
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
"title": "Impostazioni",
|
||||
"tooltip": "Impostazioni",
|
||||
"tabs": {
|
||||
"common": "Comune",
|
||||
"customizations": "Personalizzazioni"
|
||||
"common": "Generale",
|
||||
"customizations": "Personalizza"
|
||||
},
|
||||
"tips": {
|
||||
"configTip": "Caricate il vostro file di configurazione trascinandolo sulla pagina!"
|
||||
"configTip": "Carica il file di configurazione trascinandolo e rilasciandolo sulla pagina!"
|
||||
},
|
||||
"credits": {
|
||||
"madeWithLove": "Realizzato con ❤️ da @"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"label": "Larghezza dell'applicazione"
|
||||
"label": "Larghezza App"
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"label": "Opacità dell'applicazione"
|
||||
"label": "Opacità App"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"pageTitle": {
|
||||
"label": "Titolo della pagina",
|
||||
"label": "Titolo pagina",
|
||||
"placeholder": "Homarr 🦞"
|
||||
},
|
||||
"logo": {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"label": "Ombreggiatura"
|
||||
"label": "Tonalità"
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"configSelect": {
|
||||
"label": "Caricatore di configurazione"
|
||||
"label": "Carica configurazione"
|
||||
},
|
||||
"modal": {
|
||||
"title": "Scegliere il nome della nuova configurazione",
|
||||
"title": "Scegli il nome della nuova configurazione",
|
||||
"form": {
|
||||
"configName": {
|
||||
"label": "Nome della configurazione",
|
||||
"placeholder": "Il nome della nuova configurazione"
|
||||
"label": "Nome configurazione",
|
||||
"placeholder": "Nuovo nome configurazione"
|
||||
},
|
||||
"submitButton": "Conferma"
|
||||
},
|
||||
@@ -19,21 +19,21 @@
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"download": "Scarica la configurazione",
|
||||
"download": "Download configurazione",
|
||||
"delete": {
|
||||
"text": "Cancellare la configurazione",
|
||||
"text": "Elimina configurazione",
|
||||
"notifications": {
|
||||
"deleted": {
|
||||
"title": "Configurazione cancellata",
|
||||
"message": "Configurazione cancellata"
|
||||
"title": "Configurazione eliminata",
|
||||
"message": "Configurazione eliminata"
|
||||
},
|
||||
"deleteFailed": {
|
||||
"title": "Cancellazione configurazione fallita",
|
||||
"message": "Cancellazione configurazione fallita"
|
||||
"title": "Eliminazione configurazione fallita",
|
||||
"message": "Eliminazione configurazione fallita"
|
||||
}
|
||||
}
|
||||
},
|
||||
"saveCopy": "Salvare una copia"
|
||||
"saveCopy": "Salva una copia"
|
||||
},
|
||||
"dropzone": {
|
||||
"notifications": {
|
||||
@@ -46,10 +46,10 @@
|
||||
}
|
||||
},
|
||||
"accept": {
|
||||
"text": "Trascinare i file qui per caricare una configurazione. Supporto solo per JSON."
|
||||
"text": "Trascina qui i file per caricare una configurazione. Solo file JSON supportati."
|
||||
},
|
||||
"reject": {
|
||||
"text": "Questo formato di file non è supportato. Caricare solo JSON."
|
||||
"text": "Formato file non supportato. Caricare solo file JSON."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"title": "Modulo abilitatore"
|
||||
"title": "Abilitatore moduli"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"title": "Motore di ricerca",
|
||||
"tips": {
|
||||
"generalTip": "Utilizzate i prefissi !yt e !t davanti alla vostra ricerca per cercare rispettivamente su YouTube o su un Torrent.",
|
||||
"generalTip": "Usa i prefissi !yt e !t di fronte alla tua ricerca per cercare rispettivamente su YouTube o un Torrent.",
|
||||
"placeholderTip": "%s può essere usato come segnaposto per la ricerca."
|
||||
},
|
||||
"customEngine": {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"label": "Posizionare i widget a sinistra"
|
||||
"label": "Posiziona widget a sinistra"
|
||||
}
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "ウェブで検索..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "オーバーホール",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "ユースネット",
|
||||
"description": "Usenet (Sabnzbd または NZBGet) のキューと履歴を表示し、ダウンロードを一時停止および再開できます。"
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"label": "ロゴマーク"
|
||||
},
|
||||
"favicon": {
|
||||
"label": "Favicon"
|
||||
"label": "ファビコン"
|
||||
},
|
||||
"background": {
|
||||
"label": "背景"
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "웹에서 검색..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "ユースネット",
|
||||
"description": "유즈넷(Sabnzbd 또는 NZBGet) 대기열 및 기록을 보고 다운로드를 일시 중지 및 재개할 수 있습니다."
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"label": "로고"
|
||||
},
|
||||
"favicon": {
|
||||
"label": "Favicon"
|
||||
"label": "파비콘"
|
||||
},
|
||||
"background": {
|
||||
"label": "배경"
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Search teh web..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Usenet",
|
||||
"description": "Allowz u 2 c ur usenet (Sabnzbd & NZBGet) queue an histowee, paues an resuem downloadz"
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Doorzoek het web..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Usenet",
|
||||
"description": "Hiermee kunt u uw usenet (Sabnzbd of NZBGet) wachtrij en geschiedenis bekijken, downloads pauzeren en hervatten."
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Szukaj w internecie..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Usenet",
|
||||
"description": "Pozwala zobaczyć kolejkę i historię usenetu (Sabnzbd lub NZBGet), wstrzymywać i wznawiać pobieranie."
|
||||
"description": ""
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Pesquisar na Internet..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Usenet",
|
||||
"description": "Permite que você veja sua fila e histórico de usenet (Sabnzbd ou NZBGet), pausar e retomar downloads."
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Искать в интернете..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Юнет",
|
||||
"description": "Позволяет просматривать очередь и историю Usenet (Sabnzbd или NZBGet), приостанавливать и возобновлять загрузки."
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Preišči splet..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Usenet",
|
||||
"description": "Omogoča ogled vaše čakalne vrste in zgodovine usenet (Sabnzbd ali NZBGet), zaustavitev in nadaljevanje prenosov."
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Sök på webben..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Usenet",
|
||||
"description": "Låter dig se din usenet (Sabnzbd eller NZBGet) kö och historik, pausa och återuppta nedladdningar."
|
||||
"description": "Låter dig se din usenet (Sabnzbd eller NZBGet) kö och historik, pausa och återuppta nedladdningar"
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Пошук в Інтернеті..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Sabnzbd",
|
||||
"description": "Дозволяє переглядати чергу та історію usenet (Sabnzbd або NZBGet), призупиняти та відновлювати завантаження."
|
||||
"name": "Usenet",
|
||||
"description": "Дозволяє вам бачити вашу чергу та історію в usenet (Sabnzbd або NZBGet), керувати завантаженнями"
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
},
|
||||
"favicon": {
|
||||
"label": "Іконка"
|
||||
},
|
||||
"background": {
|
||||
"label": "Фон"
|
||||
},
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "Tìm kiếm trên web..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -9,6 +9,6 @@
|
||||
"configTip": "Tải tệp cấu hình của bạn lên chỉ bằng cách kéo và thả tệp vào trong trang!"
|
||||
},
|
||||
"credits": {
|
||||
"madeWithLove": "Được tạo bằng ❤️ bởi @"
|
||||
"madeWithLove": "From @ with ❤️"
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"download": "Tải cấu hình xuống",
|
||||
"download": "Tải cấu hình",
|
||||
"delete": {
|
||||
"text": "Xóa cấu hình",
|
||||
"notifications": {
|
||||
|
||||
@@ -5,5 +5,26 @@
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "在网上搜索..."
|
||||
}
|
||||
},
|
||||
"switched-to": "",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"youtube": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"torrents": {
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"tip": "",
|
||||
"switchedSearchEngine": ""
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "用户网",
|
||||
"description": "允许您查看您的用户网(Sabnzbd 或 NZBGet)队列和历史记录,暂停和恢复下载。"
|
||||
"name": "",
|
||||
"description": ""
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
@@ -16,7 +16,7 @@
|
||||
"history": "历史"
|
||||
},
|
||||
"info": {
|
||||
"sizeLeft": "左侧大小",
|
||||
"sizeLeft": "左侧尺寸调整",
|
||||
"paused": "暂停使用"
|
||||
},
|
||||
"queue": {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Accordion, Grid, Paper, Stack, Text, useMantineColorScheme } from '@mantine/core';
|
||||
import { Accordion, Grid, Stack, Title, useMantineColorScheme } from '@mantine/core';
|
||||
import {
|
||||
closestCenter,
|
||||
DndContext,
|
||||
@@ -9,16 +9,16 @@ import {
|
||||
useSensor,
|
||||
useSensors,
|
||||
} from '@dnd-kit/core';
|
||||
|
||||
import { arrayMove, SortableContext } from '@dnd-kit/sortable';
|
||||
import { useLocalStorage } from '@mantine/hooks';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import * as Modules from '../../modules';
|
||||
import { useConfig } from '../../tools/state';
|
||||
|
||||
import { SortableAppShelfItem, AppShelfItem } from './AppShelfItem';
|
||||
import { ModuleMenu, ModuleWrapper } from '../../modules/moduleWrapper';
|
||||
import { AppShelfItem, SortableItem } from './AppShelfItem';
|
||||
import { ModuleWrapper } from '../../modules/moduleWrapper';
|
||||
import { UsenetModule, TorrentsModule } from '../../modules';
|
||||
import TorrentsComponent from '../../modules/torrents/TorrentsModule';
|
||||
import { UsenetComponent } from '../../modules/usenet/UsenetModule';
|
||||
|
||||
const AppShelf = (props: any) => {
|
||||
const { config, setConfig } = useConfig();
|
||||
@@ -79,13 +79,14 @@ const AppShelf = (props: any) => {
|
||||
const getItems = (filter?: string) => {
|
||||
// If filter is not set, return all the services without a category or a null category
|
||||
let filtered = config.services;
|
||||
const modules = Object.values(Modules).map((module) => module);
|
||||
|
||||
if (!filter) {
|
||||
filtered = config.services.filter((e) => !e.category || e.category === null);
|
||||
}
|
||||
if (filter) {
|
||||
filtered = config.services.filter((e) => e.category === filter);
|
||||
}
|
||||
|
||||
return (
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
@@ -94,17 +95,12 @@ const AppShelf = (props: any) => {
|
||||
onDragEnd={handleDragEnd}
|
||||
>
|
||||
<SortableContext items={config.services}>
|
||||
<Grid gutter="xl" align="center">
|
||||
<Grid gutter="lg" align="center">
|
||||
{filtered.map((service) => (
|
||||
<Grid.Col
|
||||
key={service.id}
|
||||
span={6}
|
||||
xl={config.settings.appCardWidth || 2}
|
||||
xs={4}
|
||||
sm={3}
|
||||
md={3}
|
||||
>
|
||||
<SortableAppShelfItem service={service} key={service.id} id={service.id} />
|
||||
<Grid.Col key={service.id} span="content">
|
||||
<SortableItem service={service} key={service.id} id={service.id}>
|
||||
<AppShelfItem service={service} />
|
||||
</SortableItem>
|
||||
</Grid.Col>
|
||||
))}
|
||||
</Grid>
|
||||
@@ -123,100 +119,36 @@ const AppShelf = (props: any) => {
|
||||
);
|
||||
};
|
||||
|
||||
if (categoryList.length > 0) {
|
||||
const noCategory = config.services.filter(
|
||||
(e) => e.category === undefined || e.category === null
|
||||
);
|
||||
|
||||
const torrentEnabled = config.modules?.[TorrentsModule.id]?.enabled ?? false;
|
||||
const usenetEnabled = config.modules?.[UsenetModule.id]?.enabled ?? false;
|
||||
|
||||
const downloadEnabled = usenetEnabled || torrentEnabled;
|
||||
// Create an item with 0: true, 1: true, 2: true... For each category
|
||||
return (
|
||||
// TODO: Style accordion so that the bar is transparent to the user settings
|
||||
<Stack>
|
||||
<Accordion
|
||||
variant="separated"
|
||||
radius="lg"
|
||||
order={2}
|
||||
multiple
|
||||
value={toggledCategories}
|
||||
onChange={(state) => {
|
||||
setToggledCategories([...state]);
|
||||
}}
|
||||
>
|
||||
{categoryList.map((category, idx) => (
|
||||
<Accordion.Item
|
||||
style={{
|
||||
background: `rgba(${colorScheme === 'dark' ? '32, 33, 35,' : '255, 255, 255,'} \
|
||||
${(config.settings.appOpacity || 100) / 100}`,
|
||||
borderColor: `rgba(${colorScheme === 'dark' ? '32, 33, 35,' : '233, 236, 239,'} \
|
||||
${(config.settings.appOpacity || 100) / 100}`,
|
||||
}}
|
||||
key={category}
|
||||
value={idx.toString()}
|
||||
>
|
||||
<Accordion.Control>{category}</Accordion.Control>
|
||||
<Accordion.Panel>{getItems(category)}</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
))}
|
||||
{/* Return the item for all services without category */}
|
||||
{noCategory && noCategory.length > 0 ? (
|
||||
<Accordion.Item
|
||||
style={{
|
||||
background: `rgba(${colorScheme === 'dark' ? '32, 33, 35,' : '255, 255, 255,'} \
|
||||
${(config.settings.appOpacity || 100) / 100}`,
|
||||
borderColor: `rgba(${colorScheme === 'dark' ? '32, 33, 35,' : '233, 236, 239,'} \
|
||||
${(config.settings.appOpacity || 100) / 100}`,
|
||||
}}
|
||||
key="Other"
|
||||
value="Other"
|
||||
>
|
||||
<Accordion.Control>{t('accordions.others.text')}</Accordion.Control>
|
||||
<Accordion.Panel>{getItems()}</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
) : null}
|
||||
{downloadEnabled ? (
|
||||
<Accordion.Item
|
||||
style={{
|
||||
color: `rgba(${colorScheme === 'dark' ? '32, 33, 35,' : '255, 255, 255,'} \
|
||||
${(config.settings.appOpacity || 100) / 100}`,
|
||||
background: `rgba(${colorScheme === 'dark' ? '32, 33, 35,' : '255, 255, 255,'} \
|
||||
${(config.settings.appOpacity || 100) / 100}`,
|
||||
borderColor: `rgba(${colorScheme === 'dark' ? '32, 33, 35,' : '233, 236, 239,'} \
|
||||
${(config.settings.appOpacity || 100) / 100}`,
|
||||
}}
|
||||
key="Downloads"
|
||||
value="Your downloads"
|
||||
>
|
||||
<Accordion.Control>{t('accordions.downloads.text')}</Accordion.Control>
|
||||
<Accordion.Panel>
|
||||
<Paper radius="lg" style={{ position: 'relative' }}>
|
||||
{torrentEnabled && (
|
||||
<>
|
||||
<Text>{t('accordions.downloads.torrents')}</Text>
|
||||
<ModuleMenu module={TorrentsModule} hovered />
|
||||
<TorrentsComponent />
|
||||
</>
|
||||
)}
|
||||
{usenetEnabled && (
|
||||
<>
|
||||
<Text mt="md">{t('accordions.downloads.usenet')}</Text>
|
||||
<ModuleMenu module={UsenetModule} hovered />
|
||||
<UsenetComponent />
|
||||
</>
|
||||
)}
|
||||
</Paper>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
) : null}
|
||||
</Accordion>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Stack>
|
||||
<Accordion
|
||||
variant="separated"
|
||||
radius="lg"
|
||||
order={2}
|
||||
multiple
|
||||
value={toggledCategories}
|
||||
onChange={(state) => {
|
||||
setToggledCategories([...state]);
|
||||
}}
|
||||
>
|
||||
{categoryList.map((category, idx) => (
|
||||
<Accordion.Item
|
||||
style={{
|
||||
background: `rgba(${colorScheme === 'dark' ? '32, 33, 35,' : '255, 255, 255,'} \
|
||||
${(config.settings.appOpacity || 100) / 100}`,
|
||||
borderColor: `rgba(${colorScheme === 'dark' ? '32, 33, 35,' : '233, 236, 239,'} \
|
||||
${(config.settings.appOpacity || 100) / 100}`,
|
||||
}}
|
||||
key={category}
|
||||
value={idx.toString()}
|
||||
>
|
||||
<Accordion.Control>
|
||||
<Title order={5}>{category}</Title>
|
||||
</Accordion.Control>
|
||||
<Accordion.Panel>{getItems(category)}</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
))}
|
||||
</Accordion>
|
||||
{getItems()}
|
||||
<ModuleWrapper mt="xl" module={TorrentsModule} />
|
||||
<ModuleWrapper mt="xl" module={UsenetModule} />
|
||||
|
||||
@@ -31,7 +31,7 @@ const useStyles = createStyles((theme) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
export function SortableAppShelfItem(props: any) {
|
||||
export function SortableItem(props: any) {
|
||||
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
|
||||
id: props.id,
|
||||
});
|
||||
@@ -43,7 +43,7 @@ export function SortableAppShelfItem(props: any) {
|
||||
|
||||
return (
|
||||
<div ref={setNodeRef} style={style} {...attributes} {...listeners}>
|
||||
<AppShelfItem service={props.service} />
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -75,6 +75,8 @@ export function AppShelfItem(props: any) {
|
||||
shadow="md"
|
||||
className={classes.item}
|
||||
style={{
|
||||
// Use the grab cursor when hovering over the card
|
||||
cursor: hovering ? 'grab' : 'auto',
|
||||
background: `rgba(${colorScheme === 'dark' ? '37, 38, 43,' : '255, 255, 255,'} \
|
||||
${(config.settings.appOpacity || 100) / 100}`,
|
||||
borderColor: `rgba(${colorScheme === 'dark' ? '37, 38, 43,' : '233, 236, 239,'} \
|
||||
@@ -105,14 +107,14 @@ export function AppShelfItem(props: any) {
|
||||
<AppShelfMenu service={service} />
|
||||
</motion.div>
|
||||
</Card.Section>
|
||||
<Center>
|
||||
<Card.Section>
|
||||
<Card.Section>
|
||||
<Center>
|
||||
<AspectRatio
|
||||
ratio={3 / 5}
|
||||
m="xl"
|
||||
m="lg"
|
||||
style={{
|
||||
width: 150,
|
||||
height: 90,
|
||||
height: 75 * ((config.settings.appCardWidth ?? 1) * 1.2),
|
||||
width: 75 * ((config.settings.appCardWidth ?? 1) * 2),
|
||||
}}
|
||||
>
|
||||
<motion.i
|
||||
@@ -126,8 +128,8 @@ export function AppShelfItem(props: any) {
|
||||
>
|
||||
<Image
|
||||
styles={{ root: { cursor: 'pointer' } }}
|
||||
width={80}
|
||||
height={80}
|
||||
width={75 * ((config.settings.appCardWidth ?? 1) * 1.2)}
|
||||
height={75 * ((config.settings.appCardWidth ?? 1) * 1.2)}
|
||||
src={service.icon}
|
||||
fit="contain"
|
||||
/>
|
||||
@@ -135,8 +137,8 @@ export function AppShelfItem(props: any) {
|
||||
</motion.i>
|
||||
</AspectRatio>
|
||||
{service.ping !== false && <PingComponent url={service.url} status={service.status} />}
|
||||
</Card.Section>
|
||||
</Center>
|
||||
</Center>
|
||||
</Card.Section>
|
||||
</Card>
|
||||
</motion.div>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import React from 'react';
|
||||
import { createStyles, Switch, Group, useMantineColorScheme, Kbd } from '@mantine/core';
|
||||
import { IconSun as Sun, IconMoonStars as MoonStars } from '@tabler/icons';
|
||||
import {
|
||||
createStyles,
|
||||
Switch,
|
||||
Group,
|
||||
useMantineColorScheme,
|
||||
Kbd,
|
||||
useMantineTheme,
|
||||
} from '@mantine/core';
|
||||
import { IconMoonStars, IconSun } from '@tabler/icons';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useConfig } from '../../tools/state';
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
root: {
|
||||
@@ -31,18 +37,18 @@ const useStyles = createStyles((theme) => ({
|
||||
}));
|
||||
|
||||
export function ColorSchemeSwitch() {
|
||||
const { config } = useConfig();
|
||||
const { colorScheme, toggleColorScheme } = useMantineColorScheme();
|
||||
const { classes, cx } = useStyles();
|
||||
const { t } = useTranslation('settings/general/theme-selector');
|
||||
|
||||
const theme = useMantineTheme();
|
||||
return (
|
||||
<Group>
|
||||
<div className={classes.root}>
|
||||
<Sun className={cx(classes.icon, classes.iconLight)} size={18} />
|
||||
<MoonStars className={cx(classes.icon, classes.iconDark)} size={18} />
|
||||
<Switch checked={colorScheme === 'dark'} onChange={() => toggleColorScheme()} size="md" />
|
||||
</div>
|
||||
<Switch
|
||||
checked={colorScheme === 'dark'}
|
||||
onChange={() => toggleColorScheme()}
|
||||
size="md"
|
||||
onLabel={<IconSun color={theme.white} size={20} stroke={1.5} />}
|
||||
offLabel={<IconMoonStars color={theme.colors.gray[6]} size={20} stroke={1.5} />}
|
||||
/>
|
||||
{t('label', {
|
||||
theme: colorScheme === 'dark' ? 'light' : 'dark',
|
||||
})}
|
||||
|
||||
@@ -21,11 +21,11 @@ export function AppCardWidthSelector() {
|
||||
<Stack spacing="xs">
|
||||
<Text>{t('label')}</Text>
|
||||
<Slider
|
||||
label={null}
|
||||
defaultValue={config.settings.appCardWidth}
|
||||
step={0.2}
|
||||
min={0.8}
|
||||
max={2}
|
||||
label={config.settings.appCardWidth?.toFixed(1)}
|
||||
defaultValue={config.settings.appCardWidth ?? 0.7}
|
||||
step={0.1}
|
||||
min={0.3}
|
||||
max={1.2}
|
||||
styles={{ markLabel: { fontSize: 'xx-small' } }}
|
||||
onChange={(value) => setappCardWidth(value)}
|
||||
/>
|
||||
|
||||
@@ -9,7 +9,7 @@ export function Logo({ style, withoutText }: any) {
|
||||
const { primaryColor, secondaryColor } = useColorTheme();
|
||||
|
||||
return (
|
||||
<Group spacing="xs">
|
||||
<Group spacing="xs" noWrap>
|
||||
<Image
|
||||
width={50}
|
||||
src={config.settings.logo || '/imgs/logo/logo.png'}
|
||||
@@ -18,26 +18,18 @@ export function Logo({ style, withoutText }: any) {
|
||||
}}
|
||||
/>
|
||||
{withoutText ? null : (
|
||||
<NextLink
|
||||
href="/"
|
||||
style={{
|
||||
textDecoration: 'none',
|
||||
position: 'relative',
|
||||
<Text
|
||||
sx={style}
|
||||
weight="bold"
|
||||
variant="gradient"
|
||||
gradient={{
|
||||
from: primaryColor,
|
||||
to: secondaryColor,
|
||||
deg: 145,
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
sx={style}
|
||||
weight="bold"
|
||||
variant="gradient"
|
||||
gradient={{
|
||||
from: primaryColor,
|
||||
to: secondaryColor,
|
||||
deg: 145,
|
||||
}}
|
||||
>
|
||||
{config.settings.title || 'Homarr'}
|
||||
</Text>
|
||||
</NextLink>
|
||||
{config.settings.title || 'Homarr'}
|
||||
</Text>
|
||||
)}
|
||||
</Group>
|
||||
);
|
||||
|
||||
@@ -1,27 +1,16 @@
|
||||
import { Box, createStyles, Group, Header as Head, useMantineColorScheme } from '@mantine/core';
|
||||
import { Group, Header as Head, useMantineColorScheme, useMantineTheme } from '@mantine/core';
|
||||
import { useViewportSize } from '@mantine/hooks';
|
||||
import { AddItemShelfButton } from '../../AppShelf/AddAppShelfItem';
|
||||
|
||||
import DockerMenuButton from '../../../modules/docker/DockerModule';
|
||||
import SearchBar from '../../../modules/search/SearchModule';
|
||||
import { SettingsMenuButton } from '../../Settings/SettingsMenu';
|
||||
import { Logo } from '../Logo';
|
||||
import { useConfig } from '../../../tools/state';
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
hide: {
|
||||
[theme.fn.smallerThan('xs')]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
burger: {
|
||||
[theme.fn.largerThan('sm')]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
}));
|
||||
import { SearchModuleComponent } from '../../../modules/search/SearchModule';
|
||||
|
||||
export function Header(props: any) {
|
||||
const { classes } = useStyles();
|
||||
const { width } = useViewportSize();
|
||||
const MIN_WIDTH_MOBILE = useMantineTheme().breakpoints.xs;
|
||||
const { config } = useConfig();
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
|
||||
@@ -35,12 +24,10 @@ export function Header(props: any) {
|
||||
${(config.settings.appOpacity || 100) / 100}`,
|
||||
}}
|
||||
>
|
||||
<Group p="xs" position="apart">
|
||||
<Box className={classes.hide}>
|
||||
<Logo style={{ fontSize: 22 }} />
|
||||
</Box>
|
||||
<Group noWrap>
|
||||
<SearchBar />
|
||||
<Group p="xs" noWrap grow>
|
||||
{width > MIN_WIDTH_MOBILE && <Logo style={{ fontSize: 22 }} />}
|
||||
<Group position="right" noWrap>
|
||||
<SearchModuleComponent />
|
||||
<DockerMenuButton />
|
||||
<SettingsMenuButton />
|
||||
<AddItemShelfButton />
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
ScrollArea,
|
||||
createStyles,
|
||||
useMantineTheme,
|
||||
Space,
|
||||
} from '@mantine/core';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Calendar } from '@mantine/dates';
|
||||
@@ -143,12 +144,6 @@ export default function CalendarComponent(props: any) {
|
||||
margin: 1,
|
||||
}
|
||||
}
|
||||
styles={{
|
||||
calendarHeader: {
|
||||
marginRight: 40,
|
||||
marginLeft: 40,
|
||||
},
|
||||
}}
|
||||
allowLevelChange={false}
|
||||
dayClassName={(date, modifiers) => cx({ [classes.weekend]: modifiers.weekend })}
|
||||
renderDay={(renderdate) => (
|
||||
@@ -278,10 +273,11 @@ function DayComponent(props: any) {
|
||||
scrollbarSize={5}
|
||||
style={{
|
||||
height:
|
||||
totalFiltered.slice(0, 2).length > 1 ? totalFiltered.slice(0, 2).length * 150 : 200,
|
||||
totalFiltered.slice(0, 2).length > 1 ? totalFiltered.slice(0, 2).length * 150 : 220,
|
||||
width: 400,
|
||||
}}
|
||||
>
|
||||
<Space mt={5} />
|
||||
{sonarrFiltered.map((media: any, index: number) => (
|
||||
<React.Fragment key={index}>
|
||||
<SonarrMediaDisplay media={media} />
|
||||
|
||||
@@ -163,7 +163,7 @@ export function MediaDisplay({ media }: { media: IMedia }) {
|
||||
const { t } = useTranslation('modules/common-media-cards');
|
||||
|
||||
return (
|
||||
<Group mr="xs" align="stretch" noWrap style={{ maxHeight: 200 }}>
|
||||
<Group mr="xs" align="stretch" noWrap style={{ maxHeight: 200 }} spacing="xs">
|
||||
<Image src={media.poster} height={200} width={150} radius="md" fit="cover" />
|
||||
<Stack justify="space-around">
|
||||
<Stack spacing="sm">
|
||||
|
||||
@@ -38,7 +38,7 @@ export const DashdotModule = asModule({
|
||||
id: 'dashdot',
|
||||
});
|
||||
|
||||
const useStyles = createStyles((theme, _params) => ({
|
||||
const useStyles = createStyles((theme, _params, getRef) => ({
|
||||
heading: {
|
||||
marginTop: 0,
|
||||
marginBottom: 10,
|
||||
@@ -70,6 +70,21 @@ const useStyles = createStyles((theme, _params) => ({
|
||||
maxWidth: '100%',
|
||||
height: '140px',
|
||||
borderRadius: theme.radius.lg,
|
||||
border: 'none',
|
||||
colorScheme: 'none',
|
||||
},
|
||||
graphTitle: {
|
||||
ref: getRef('graphTitle'),
|
||||
position: 'absolute',
|
||||
right: 0,
|
||||
opacity: 0,
|
||||
transition: 'opacity .1s ease-in-out',
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
graphStack: {
|
||||
[`&:hover .${getRef('graphTitle')}`]: {
|
||||
opacity: 0.5,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -221,6 +236,7 @@ export function DashdotComponent() {
|
||||
|
||||
{graphs.map((graph) => (
|
||||
<Stack
|
||||
className={classes.graphStack}
|
||||
style={
|
||||
isCompact
|
||||
? {
|
||||
@@ -230,7 +246,7 @@ export function DashdotComponent() {
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<Title style={{ position: 'absolute', right: 0 }} order={4} mt={10} mr={25}>
|
||||
<Title className={classes.graphTitle} order={4} mt={10} mr={25}>
|
||||
{graph.name}
|
||||
</Title>
|
||||
<iframe
|
||||
@@ -248,7 +264,7 @@ export function DashdotComponent() {
|
||||
.join('&')}`
|
||||
: ''
|
||||
}`}
|
||||
frameBorder="0"
|
||||
allowTransparency
|
||||
/>
|
||||
</Stack>
|
||||
))}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import { Button, Group, TextInput, Title } from '@mantine/core';
|
||||
import { closeAllModals, closeModal, openModal } from '@mantine/modals';
|
||||
import { Button, Group } from '@mantine/core';
|
||||
import { closeModal, openModal } from '@mantine/modals';
|
||||
import { showNotification, updateNotification } from '@mantine/notifications';
|
||||
import {
|
||||
IconCheck,
|
||||
@@ -72,7 +72,7 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
|
||||
const { config, setConfig } = useConfig();
|
||||
|
||||
return (
|
||||
<Group>
|
||||
<Group spacing="xs">
|
||||
<Button
|
||||
leftIcon={<IconRefresh />}
|
||||
onClick={() => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Table, Checkbox, Group, Badge, createStyles, ScrollArea, TextInput } from '@mantine/core';
|
||||
import { Table, Checkbox, Group, Badge, createStyles, ScrollArea, TextInput, useMantineTheme } from '@mantine/core';
|
||||
import { useElementSize } from '@mantine/hooks';
|
||||
import { IconSearch } from '@tabler/icons';
|
||||
import Dockerode from 'dockerode';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
@@ -23,9 +24,11 @@ export default function DockerTable({
|
||||
containers: Dockerode.ContainerInfo[];
|
||||
selection: Dockerode.ContainerInfo[];
|
||||
}) {
|
||||
const MIN_WIDTH_MOBILE = useMantineTheme().breakpoints.xs;
|
||||
const [usedContainers, setContainers] = useState<Dockerode.ContainerInfo[]>(containers);
|
||||
const { classes, cx } = useStyles();
|
||||
const [search, setSearch] = useState('');
|
||||
const { ref, width, height } = useElementSize();
|
||||
|
||||
const { t } = useTranslation('modules/docker');
|
||||
|
||||
@@ -67,28 +70,30 @@ export default function DockerTable({
|
||||
/>
|
||||
</td>
|
||||
<td>{element.Names[0].replace('/', '')}</td>
|
||||
<td>{element.Image}</td>
|
||||
<td>
|
||||
<Group>
|
||||
{element.Ports.sort((a, b) => a.PrivatePort - b.PrivatePort)
|
||||
// Remove duplicates with filter function
|
||||
.filter(
|
||||
(port, index, self) =>
|
||||
index === self.findIndex((t) => t.PrivatePort === port.PrivatePort)
|
||||
)
|
||||
.slice(-3)
|
||||
.map((port) => (
|
||||
<Badge key={port.PrivatePort} variant="outline">
|
||||
{port.PrivatePort}:{port.PublicPort}
|
||||
{width > MIN_WIDTH_MOBILE && <td>{element.Image}</td>}
|
||||
{width > MIN_WIDTH_MOBILE && (
|
||||
<td>
|
||||
<Group>
|
||||
{element.Ports.sort((a, b) => a.PrivatePort - b.PrivatePort)
|
||||
// Remove duplicates with filter function
|
||||
.filter(
|
||||
(port, index, self) =>
|
||||
index === self.findIndex((t) => t.PrivatePort === port.PrivatePort)
|
||||
)
|
||||
.slice(-3)
|
||||
.map((port) => (
|
||||
<Badge key={port.PrivatePort} variant="outline">
|
||||
{port.PrivatePort}:{port.PublicPort}
|
||||
</Badge>
|
||||
))}
|
||||
{element.Ports.length > 3 && (
|
||||
<Badge variant="filled">
|
||||
{t('table.body.portCollapse', { ports: element.Ports.length - 3 })}
|
||||
</Badge>
|
||||
))}
|
||||
{element.Ports.length > 3 && (
|
||||
<Badge variant="filled">
|
||||
{t('table.body.portCollapse', { ports: element.Ports.length - 3 })}
|
||||
</Badge>
|
||||
)}
|
||||
</Group>
|
||||
</td>
|
||||
)}
|
||||
</Group>
|
||||
</td>
|
||||
)}
|
||||
<td>
|
||||
<ContainerState state={element.State} />
|
||||
</td>
|
||||
@@ -106,7 +111,7 @@ export default function DockerTable({
|
||||
onChange={handleSearchChange}
|
||||
disabled={usedContainers.length === 0}
|
||||
/>
|
||||
<Table captionSide="bottom" highlightOnHover sx={{ minWidth: 800 }} verticalSpacing="sm">
|
||||
<Table ref={ref} captionSide="bottom" highlightOnHover verticalSpacing="sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{ width: 40 }}>
|
||||
@@ -119,8 +124,8 @@ export default function DockerTable({
|
||||
/>
|
||||
</th>
|
||||
<th>{t('table.header.name')}</th>
|
||||
<th>{t('table.header.image')}</th>
|
||||
<th>{t('table.header.ports')}</th>
|
||||
{width > MIN_WIDTH_MOBILE ? <th>{t('table.header.image')}</th> : null}
|
||||
{width > MIN_WIDTH_MOBILE ? <th>{t('table.header.ports')}</th> : null}
|
||||
<th>{t('table.header.state')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@@ -188,7 +188,7 @@ export function TvRequestModal({
|
||||
</thead>
|
||||
<tbody>{rows}</tbody>
|
||||
</Table>
|
||||
<Group>
|
||||
<Group position="center">
|
||||
<Button variant="outline" color="gray" onClick={() => setOpened(false)}>
|
||||
{t('popup.item.buttons.cancel')}
|
||||
</Button>
|
||||
|
||||
@@ -1,236 +1,162 @@
|
||||
import { Kbd, createStyles, Autocomplete, Popover, ScrollArea, Divider } from '@mantine/core';
|
||||
import { useClickOutside, useDebouncedValue, useHotkeys } from '@mantine/hooks';
|
||||
import { useForm } from '@mantine/form';
|
||||
import React, { forwardRef, useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
IconSearch as Search,
|
||||
IconBrandYoutube as BrandYoutube,
|
||||
IconDownload as Download,
|
||||
IconMovie,
|
||||
} from '@tabler/icons';
|
||||
ActionIcon,
|
||||
Box,
|
||||
createStyles,
|
||||
Divider,
|
||||
Kbd,
|
||||
Menu,
|
||||
Popover,
|
||||
ScrollArea,
|
||||
TextInput,
|
||||
Tooltip,
|
||||
} from '@mantine/core';
|
||||
import { IconSearch, IconBrandYoutube, IconDownload, IconMovie } from '@tabler/icons';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { useDebouncedValue, useHotkeys } from '@mantine/hooks';
|
||||
import { showNotification } from '@mantine/notifications';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import axios from 'axios';
|
||||
import { showNotification } from '@mantine/notifications';
|
||||
import { useConfig } from '../../tools/state';
|
||||
import { IModule } from '../ModuleTypes';
|
||||
import { useConfig } from '../../tools/state';
|
||||
import { OverseerrModule } from '../overseerr';
|
||||
import Tip from '../../components/layout/Tip';
|
||||
import { OverseerrMediaDisplay } from '../common';
|
||||
import SmallServiceItem from '../../components/AppShelf/SmallServiceItem';
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
hide: {
|
||||
[theme.fn.smallerThan('sm')]: {
|
||||
display: 'none',
|
||||
},
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
}));
|
||||
|
||||
export const SearchModule: IModule = {
|
||||
title: 'Search',
|
||||
icon: Search,
|
||||
component: SearchBar,
|
||||
icon: IconSearch,
|
||||
component: SearchModuleComponent,
|
||||
id: 'search',
|
||||
};
|
||||
|
||||
export default function SearchBar(props: any) {
|
||||
const { classes, cx } = useStyles();
|
||||
// Config
|
||||
interface ItemProps extends React.ComponentPropsWithoutRef<'div'> {
|
||||
label: string;
|
||||
disabled: boolean;
|
||||
value: string;
|
||||
description: string;
|
||||
icon: React.ReactNode;
|
||||
url: string;
|
||||
shortcut: string;
|
||||
}
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
item: {
|
||||
'&[data-hovered]': {
|
||||
backgroundColor: theme.colors[theme.primaryColor][theme.fn.primaryShade()],
|
||||
color: theme.white,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export function SearchModuleComponent() {
|
||||
const { config } = useConfig();
|
||||
const isModuleEnabled = config.modules?.[SearchModule.id]?.enabled ?? false;
|
||||
const { t } = useTranslation('modules/search');
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [debounced, cancel] = useDebouncedValue(searchQuery, 250);
|
||||
const isOverseerrEnabled = config.modules?.[OverseerrModule.id]?.enabled ?? false;
|
||||
const OverseerrService = config.services.find(
|
||||
(service) => service.type === 'Overseerr' || service.type === 'Jellyseerr'
|
||||
);
|
||||
const queryUrl = config.settings.searchUrl ?? 'https://www.google.com/search?q=';
|
||||
|
||||
const [OverseerrResults, setOverseerrResults] = useState<any[]>([]);
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [icon, setIcon] = useState(<Search />);
|
||||
const [results, setResults] = useState<any[]>([]);
|
||||
const [opened, setOpened] = useState(false);
|
||||
const ref = useClickOutside(() => setOpened(false));
|
||||
|
||||
const textInput = useRef<HTMLInputElement>();
|
||||
useHotkeys([['ctrl+K', () => textInput.current && textInput.current.focus()]]);
|
||||
|
||||
const form = useForm({
|
||||
initialValues: {
|
||||
query: '',
|
||||
const searchEnginesList: ItemProps[] = [
|
||||
{
|
||||
icon: <IconSearch />,
|
||||
disabled: false,
|
||||
label: t('searchEngines.search.name'),
|
||||
value: 'search',
|
||||
description: t('searchEngines.search.description'),
|
||||
url: config.settings.searchUrl,
|
||||
shortcut: 's',
|
||||
},
|
||||
});
|
||||
const [debounced, cancel] = useDebouncedValue(form.values.query, 250);
|
||||
const { t } = useTranslation('modules/search');
|
||||
{
|
||||
icon: <IconDownload />,
|
||||
disabled: false,
|
||||
label: t('searchEngines.torrents.name'),
|
||||
value: 'torrents',
|
||||
description: t('searchEngines.torrents.description'),
|
||||
url: 'https://www.torrentdownloads.me/search/?search=',
|
||||
shortcut: 't',
|
||||
},
|
||||
{
|
||||
icon: <IconBrandYoutube />,
|
||||
disabled: false,
|
||||
label: t('searchEngines.youtube.name'),
|
||||
value: 'youtube',
|
||||
description: t('searchEngines.youtube.description'),
|
||||
url: 'https://www.youtube.com/results?search_query=',
|
||||
shortcut: 'y',
|
||||
},
|
||||
{
|
||||
icon: <IconMovie />,
|
||||
disabled: !(isOverseerrEnabled === true && OverseerrService !== undefined),
|
||||
label: t('searchEngines.overseerr.name'),
|
||||
value: 'overseerr',
|
||||
description: t('searchEngines.overseerr.description'),
|
||||
url: `${OverseerrService?.url}search?query=`,
|
||||
shortcut: 'm',
|
||||
},
|
||||
];
|
||||
const [selectedSearchEngine, setSearchEngine] = useState<ItemProps>(searchEnginesList[0]);
|
||||
useEffect(() => {
|
||||
// Refresh the default search engine every time the config for it changes #521
|
||||
setSearchEngine(searchEnginesList[0]);
|
||||
}, [config.settings.searchUrl]);
|
||||
const textInput = useRef<HTMLInputElement>(null);
|
||||
useHotkeys([['mod+K', () => textInput.current && textInput.current.focus()]]);
|
||||
const { classes } = useStyles();
|
||||
const openInNewTab = config.settings.searchNewTab ? '_blank' : '_self';
|
||||
const [OverseerrResults, setOverseerrResults] = useState<any[]>([]);
|
||||
const [opened, setOpened] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (OverseerrService === undefined && isOverseerrEnabled) {
|
||||
showNotification({
|
||||
title: 'Overseerr integration',
|
||||
message:
|
||||
'Module enabled but no service is configured with the type "Overseerr" / "Jellyseerr"',
|
||||
color: 'red',
|
||||
if (debounced !== '' && selectedSearchEngine.value === 'overseerr' && searchQuery.length > 3) {
|
||||
axios.get(`/api/modules/overseerr?query=${searchQuery}`).then((res) => {
|
||||
setOverseerrResults(res.data.results ?? []);
|
||||
});
|
||||
}
|
||||
}, [OverseerrService, isOverseerrEnabled]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
form.values.query !== debounced ||
|
||||
form.values.query === '' ||
|
||||
(form.values.query.startsWith('!') && !form.values.query.startsWith('!os'))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (form.values.query.startsWith('!os')) {
|
||||
axios
|
||||
.get(`/api/modules/overseerr?query=${form.values.query.replace('!os', '').trim()}`)
|
||||
.then((res) => {
|
||||
setOverseerrResults(res.data.results ?? []);
|
||||
setLoading(false);
|
||||
});
|
||||
setLoading(true);
|
||||
} else {
|
||||
setOverseerrResults([]);
|
||||
axios
|
||||
.get(`/api/modules/search?q=${form.values.query}`)
|
||||
.then((res) => setResults(res.data ?? []));
|
||||
}
|
||||
}, [debounced]);
|
||||
|
||||
const isModuleEnabled = config.modules?.[SearchModule.id]?.enabled ?? false;
|
||||
if (!isModuleEnabled) {
|
||||
return null;
|
||||
}
|
||||
// Match all the services that contain the query in their name if the query is not empty
|
||||
const matchingServices = config.services.filter((service) => {
|
||||
if (form.values.query === '' || form.values.query === undefined) {
|
||||
return false;
|
||||
}
|
||||
return service.name.toLowerCase().includes(form.values.query.toLowerCase());
|
||||
});
|
||||
const autocompleteData = matchingServices.map((service) => ({
|
||||
label: service.name,
|
||||
value: service.name,
|
||||
icon: service.icon,
|
||||
url: service.openedUrl ?? service.url,
|
||||
}));
|
||||
// Append the matching results to the autocomplete data
|
||||
const autoCompleteResults = results.map((result) => ({
|
||||
label: result.phrase,
|
||||
value: result.phrase,
|
||||
icon: result.icon,
|
||||
url: result.url,
|
||||
}));
|
||||
autocompleteData.push(...autoCompleteResults);
|
||||
|
||||
const AutoCompleteItem = forwardRef<HTMLDivElement, any>(
|
||||
({ label, value, icon, url, ...others }: any, ref) => (
|
||||
<div ref={ref} {...others}>
|
||||
<SmallServiceItem service={{ label, value, icon, url }} />
|
||||
</div>
|
||||
)
|
||||
);
|
||||
|
||||
//TODO: Fix the bug where clicking anything inside the Modal to ask for a movie
|
||||
// will close it (Because it closes the underlying Popover)
|
||||
return (
|
||||
<form
|
||||
onChange={() => {
|
||||
// If query contains !yt or !t add "Searching on YouTube" or "Searching torrent"
|
||||
const query = form.values.query.trim();
|
||||
switch (query.substring(0, 3)) {
|
||||
case '!yt':
|
||||
setIcon(<BrandYoutube />);
|
||||
break;
|
||||
case '!t ':
|
||||
setIcon(<Download />);
|
||||
break;
|
||||
case '!os':
|
||||
setIcon(<IconMovie />);
|
||||
break;
|
||||
default:
|
||||
setIcon(<Search />);
|
||||
break;
|
||||
}
|
||||
}}
|
||||
onSubmit={form.onSubmit((values) => {
|
||||
const query = values.query.trim();
|
||||
const open_in = config.settings.searchNewTab ? '_blank' : '_self';
|
||||
setTimeout(() => {
|
||||
form.setValues({ query: '' });
|
||||
switch (query.substring(0, 3)) {
|
||||
case '!yt':
|
||||
window.open(
|
||||
`https://www.youtube.com/results?search_query=${query.substring(3)}`,
|
||||
open_in
|
||||
);
|
||||
break;
|
||||
case '!t ':
|
||||
window.open(
|
||||
`https://www.torrentdownloads.me/search/?search=${query.substring(3)}`,
|
||||
open_in
|
||||
);
|
||||
break;
|
||||
case '!os':
|
||||
break;
|
||||
default:
|
||||
window.open(
|
||||
`${
|
||||
queryUrl.includes('%s') ? queryUrl.replace('%s', query) : `${queryUrl}${query}`
|
||||
}`,
|
||||
open_in
|
||||
);
|
||||
break;
|
||||
}
|
||||
}, 500);
|
||||
})}
|
||||
>
|
||||
<Box style={{ width: '100%', maxWidth: 400, minWidth: 300 }}>
|
||||
<Popover
|
||||
opened={OverseerrResults.length > 0 && opened}
|
||||
opened={OverseerrResults.length > 0 && opened && searchQuery.length > 3}
|
||||
position="bottom"
|
||||
withArrow
|
||||
withinPortal
|
||||
shadow="md"
|
||||
radius="md"
|
||||
zIndex={100}
|
||||
trapFocus
|
||||
transition="pop-top-right"
|
||||
>
|
||||
<Popover.Target>
|
||||
<Autocomplete
|
||||
<TextInput
|
||||
ref={textInput}
|
||||
onFocusCapture={() => setOpened(true)}
|
||||
autoFocus
|
||||
variant="filled"
|
||||
itemComponent={AutoCompleteItem}
|
||||
onItemSubmit={(item) => {
|
||||
setOpened(false);
|
||||
if (item.url) {
|
||||
results.splice(0, autocompleteData.length);
|
||||
form.reset();
|
||||
window.open(item.url);
|
||||
rightSection={<SearchModuleMenu />}
|
||||
placeholder={t(`searchEngines.${selectedSearchEngine.value}.description`)}
|
||||
value={searchQuery}
|
||||
onChange={(event) => tryMatchSearchEngine(event.currentTarget.value, setSearchQuery)}
|
||||
// Replace %s if it is in selectedSearchEngine.url with searchQuery, otherwise append searchQuery at the end of it
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter' && searchQuery.length > 0) {
|
||||
if (selectedSearchEngine.url.includes('%s')) {
|
||||
window.open(selectedSearchEngine.url.replace('%s', searchQuery), openInNewTab);
|
||||
} else {
|
||||
window.open(selectedSearchEngine.url + searchQuery, openInNewTab);
|
||||
}
|
||||
}
|
||||
}}
|
||||
data={autocompleteData}
|
||||
icon={icon}
|
||||
ref={textInput}
|
||||
rightSectionWidth={90}
|
||||
rightSection={
|
||||
<div className={classes.hide}>
|
||||
<Kbd>Ctrl</Kbd>
|
||||
<span style={{ margin: '0 5px' }}>+</span>
|
||||
<Kbd>K</Kbd>
|
||||
</div>
|
||||
}
|
||||
radius="md"
|
||||
size="md"
|
||||
styles={{ rightSection: { pointerEvents: 'none' } }}
|
||||
placeholder={t('input.placeholder')}
|
||||
{...props}
|
||||
{...form.getInputProps('query')}
|
||||
/>
|
||||
</Popover.Target>
|
||||
|
||||
<Popover.Dropdown>
|
||||
<div ref={ref}>
|
||||
<ScrollArea style={{ height: 400, width: 400 }} offsetScrollbars>
|
||||
<div>
|
||||
<ScrollArea style={{ height: 400, width: 420 }} offsetScrollbars>
|
||||
{OverseerrResults.slice(0, 5).map((result, index) => (
|
||||
<React.Fragment key={index}>
|
||||
<OverseerrMediaDisplay key={result.id} media={result} />
|
||||
@@ -241,6 +167,71 @@ export default function SearchBar(props: any) {
|
||||
</div>
|
||||
</Popover.Dropdown>
|
||||
</Popover>
|
||||
</form>
|
||||
</Box>
|
||||
);
|
||||
|
||||
function tryMatchSearchEngine(query: string, setSearchQuery: (value: string) => void) {
|
||||
const foundSearchEngine = searchEnginesList.find(
|
||||
(engine) => query.includes(`!${engine.shortcut}`) && !engine.disabled
|
||||
);
|
||||
if (foundSearchEngine) {
|
||||
setSearchQuery(query.replace(`!${foundSearchEngine.shortcut}`, ''));
|
||||
changeSearchEngine(foundSearchEngine);
|
||||
} else {
|
||||
setSearchQuery(query);
|
||||
}
|
||||
}
|
||||
|
||||
function SearchModuleMenu() {
|
||||
return (
|
||||
<Menu shadow="md" width={200} withinPortal classNames={classes}>
|
||||
<Menu.Target>
|
||||
<ActionIcon>{selectedSearchEngine.icon}</ActionIcon>
|
||||
</Menu.Target>
|
||||
|
||||
<Menu.Dropdown>
|
||||
{searchEnginesList.map((item) => (
|
||||
<Tooltip
|
||||
multiline
|
||||
label={item.description}
|
||||
withinPortal
|
||||
width={200}
|
||||
position="left"
|
||||
key={item.value}
|
||||
>
|
||||
<Menu.Item
|
||||
key={item.value}
|
||||
icon={item.icon}
|
||||
rightSection={<Kbd>!{item.shortcut}</Kbd>}
|
||||
disabled={item.disabled}
|
||||
onClick={() => {
|
||||
changeSearchEngine(item);
|
||||
}}
|
||||
>
|
||||
{item.label}
|
||||
</Menu.Item>
|
||||
</Tooltip>
|
||||
))}
|
||||
<Menu.Divider />
|
||||
<Menu.Label>
|
||||
<Tip>
|
||||
{t('tip')} <Kbd>mod+k</Kbd>{' '}
|
||||
</Tip>
|
||||
</Menu.Label>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
|
||||
function changeSearchEngine(item: ItemProps) {
|
||||
setSearchEngine(item);
|
||||
showNotification({
|
||||
radius: 'lg',
|
||||
disallowClose: true,
|
||||
id: 'spotlight',
|
||||
autoClose: 1000,
|
||||
icon: <ActionIcon size="sm">{item.icon}</ActionIcon>,
|
||||
message: t('switchedSearchEngine', { searchEngine: t(`searchEngines.${item.value}.name`) }),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,12 @@ import {
|
||||
ScrollArea,
|
||||
Center,
|
||||
Stack,
|
||||
useMantineTheme,
|
||||
} from '@mantine/core';
|
||||
import { IconDownload as Download } from '@tabler/icons';
|
||||
import { useEffect, useState } from 'react';
|
||||
import axios from 'axios';
|
||||
import { useViewportSize } from '@mantine/hooks';
|
||||
import { useElementSize } from '@mantine/hooks';
|
||||
import { showNotification } from '@mantine/notifications';
|
||||
import { NormalizedTorrent } from '@ctrl/shared-torrent';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
@@ -34,15 +35,10 @@ export const TorrentsModule: IModule = {
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
padding: {
|
||||
right: 0,
|
||||
top: -10,
|
||||
},
|
||||
};
|
||||
|
||||
export default function TorrentsComponent() {
|
||||
const { config } = useConfig();
|
||||
const { height, width } = useViewportSize();
|
||||
const downloadServices =
|
||||
config.services.filter(
|
||||
(service) =>
|
||||
@@ -56,6 +52,8 @@ export default function TorrentsComponent() {
|
||||
const [torrents, setTorrents] = useState<NormalizedTorrent[]>([]);
|
||||
const setSafeInterval = useSetSafeInterval();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const { ref, width, height } = useElementSize();
|
||||
const MIN_WIDTH_MOBILE = useMantineTheme().breakpoints.xs;
|
||||
|
||||
const { t } = useTranslation(`modules/${TorrentsModule.id}`);
|
||||
|
||||
@@ -112,14 +110,13 @@ export default function TorrentsComponent() {
|
||||
</>
|
||||
);
|
||||
}
|
||||
const DEVICE_WIDTH = 576;
|
||||
const ths = (
|
||||
<tr>
|
||||
<tr ref={ref}>
|
||||
<th>{t('card.table.header.name')}</th>
|
||||
<th>{t('card.table.header.size')}</th>
|
||||
{width > 576 ? <th>{t('card.table.header.download')}</th> : ''}
|
||||
{width > 576 ? <th>{t('card.table.header.upload')}</th> : ''}
|
||||
<th>{t('card.table.header.estimatedTimeOfArrival')}</th>
|
||||
{width > MIN_WIDTH_MOBILE && <th>{t('card.table.header.download')}</th>}
|
||||
{width > MIN_WIDTH_MOBILE && <th>{t('card.table.header.upload')}</th>}
|
||||
{width > MIN_WIDTH_MOBILE && <th>{t('card.table.header.estimatedTimeOfArrival')}</th>}
|
||||
<th>{t('card.table.header.progress')}</th>
|
||||
</tr>
|
||||
);
|
||||
@@ -164,23 +161,21 @@ export default function TorrentsComponent() {
|
||||
<td>
|
||||
<Text size="xs">{humanFileSize(size)}</Text>
|
||||
</td>
|
||||
{width > 576 ? (
|
||||
{width > MIN_WIDTH_MOBILE && (
|
||||
<td>
|
||||
<Text size="xs">{downloadSpeed > 0 ? `${downloadSpeed.toFixed(1)} Mb/s` : '-'}</Text>
|
||||
</td>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
{width > 576 ? (
|
||||
{width > MIN_WIDTH_MOBILE && (
|
||||
<td>
|
||||
<Text size="xs">{uploadSpeed > 0 ? `${uploadSpeed.toFixed(1)} Mb/s` : '-'}</Text>
|
||||
</td>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
<td>
|
||||
<Text size="xs">{torrent.eta <= 0 ? '∞' : calculateETA(torrent.eta)}</Text>
|
||||
</td>
|
||||
{width > MIN_WIDTH_MOBILE && (
|
||||
<td>
|
||||
<Text size="xs">{torrent.eta <= 0 ? '∞' : calculateETA(torrent.eta)}</Text>
|
||||
</td>
|
||||
)}
|
||||
<td>
|
||||
<Text>{(torrent.progress * 100).toFixed(1)}%</Text>
|
||||
<Progress
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
import { Badge, Button, Group, Select, Stack, Tabs, Text, Title } from '@mantine/core';
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
Group,
|
||||
Select,
|
||||
Stack,
|
||||
Tabs,
|
||||
Text,
|
||||
Title,
|
||||
useMantineTheme,
|
||||
} from '@mantine/core';
|
||||
import { IconDownload, IconPlayerPause, IconPlayerPlay } from '@tabler/icons';
|
||||
import { FunctionComponent, useEffect, useState } from 'react';
|
||||
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import dayjs from 'dayjs';
|
||||
import duration from 'dayjs/plugin/duration';
|
||||
import { useElementSize } from '@mantine/hooks';
|
||||
import { IModule } from '../ModuleTypes';
|
||||
import { UsenetQueueList } from './UsenetQueueList';
|
||||
import { UsenetHistoryList } from './UsenetHistoryList';
|
||||
@@ -48,40 +59,46 @@ export const UsenetComponent: FunctionComponent = () => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { ref, width, height } = useElementSize();
|
||||
const MIN_WIDTH_MOBILE = useMantineTheme().breakpoints.xs;
|
||||
|
||||
return (
|
||||
<Tabs keepMounted={false} defaultValue="queue">
|
||||
<Group mb="md">
|
||||
<Tabs.List style={{ flex: 1 }}>
|
||||
<Tabs.Tab value="queue">{t('tabs.queue')}</Tabs.Tab>
|
||||
<Tabs.Tab value="history">{t('tabs.history')}</Tabs.Tab>
|
||||
{data && (
|
||||
<Group position="right" ml="auto" mb="lg">
|
||||
<Badge>{humanFileSize(data?.speed)}/s</Badge>
|
||||
<Badge>
|
||||
{t('info.sizeLeft')}: {humanFileSize(data?.sizeLeft)}
|
||||
</Badge>
|
||||
{data.paused ? (
|
||||
<Button uppercase onClick={() => resume()} radius="xl" size="xs">
|
||||
<IconPlayerPlay size={16} style={{ marginRight: 5 }} /> {t('info.paused')}
|
||||
</Button>
|
||||
) : (
|
||||
<Button uppercase onClick={() => pause()} radius="xl" size="xs">
|
||||
<IconPlayerPause size={16} style={{ marginRight: 5 }} />{' '}
|
||||
{dayjs.duration(data.eta, 's').format('HH:mm:ss')}
|
||||
</Button>
|
||||
)}
|
||||
</Group>
|
||||
)}
|
||||
</Tabs.List>
|
||||
{downloadServices.length > 1 && (
|
||||
<Select
|
||||
value={selectedServiceId}
|
||||
onChange={setSelectedService}
|
||||
ml="xs"
|
||||
data={downloadServices.map((service) => ({ value: service.id, label: service.name }))}
|
||||
/>
|
||||
<Tabs.List ref={ref} mb="md" style={{ flex: 1 }}>
|
||||
<Tabs.Tab value="queue">{t('tabs.queue')}</Tabs.Tab>
|
||||
<Tabs.Tab value="history">{t('tabs.history')}</Tabs.Tab>
|
||||
{data && (
|
||||
<Group position="right" ml="auto">
|
||||
{width > MIN_WIDTH_MOBILE && (
|
||||
<>
|
||||
<Badge>{humanFileSize(data?.speed)}/s</Badge>
|
||||
<Badge>
|
||||
{t('info.sizeLeft')}: {humanFileSize(data?.sizeLeft)}
|
||||
</Badge>
|
||||
</>
|
||||
)}
|
||||
|
||||
{data.paused ? (
|
||||
<Button uppercase onClick={() => resume()} radius="xl" size="xs">
|
||||
<IconPlayerPlay size={12} style={{ marginRight: 5 }} /> {t('info.paused')}
|
||||
</Button>
|
||||
) : (
|
||||
<Button uppercase onClick={() => pause()} radius="xl" size="xs">
|
||||
<IconPlayerPause size={12} style={{ marginRight: 5 }} />{' '}
|
||||
{dayjs.duration(data.eta, 's').format('HH:mm')}
|
||||
</Button>
|
||||
)}
|
||||
</Group>
|
||||
)}
|
||||
</Group>
|
||||
</Tabs.List>
|
||||
{downloadServices.length > 1 && (
|
||||
<Select
|
||||
value={selectedServiceId}
|
||||
onChange={setSelectedService}
|
||||
ml="xs"
|
||||
data={downloadServices.map((service) => ({ value: service.id, label: service.name }))}
|
||||
/>
|
||||
)}
|
||||
<Tabs.Panel value="queue">
|
||||
<UsenetQueueList serviceId={selectedServiceId} />
|
||||
</Tabs.Panel>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { GetServerSidePropsContext } from 'next';
|
||||
import { useState } from 'react';
|
||||
import { AppProps } from 'next/app';
|
||||
import { getCookie, setCookie } from 'cookies-next';
|
||||
import { getCookie } from 'cookies-next';
|
||||
import Head from 'next/head';
|
||||
import { MantineProvider, ColorScheme, ColorSchemeProvider, MantineTheme } from '@mantine/core';
|
||||
import { NotificationsProvider } from '@mantine/notifications';
|
||||
import { useColorScheme, useHotkeys } from '@mantine/hooks';
|
||||
import { useColorScheme, useHotkeys, useLocalStorage } from '@mantine/hooks';
|
||||
import { ModalsProvider } from '@mantine/modals';
|
||||
import { appWithTranslation } from 'next-i18next';
|
||||
import { QueryClientProvider } from '@tanstack/react-query';
|
||||
@@ -16,9 +16,6 @@ import { queryClient } from '../tools/queryClient';
|
||||
|
||||
function App(this: any, props: AppProps & { colorScheme: ColorScheme }) {
|
||||
const { Component, pageProps } = props;
|
||||
const preferredColorScheme = useColorScheme();
|
||||
const [colorScheme, setColorScheme] = useState<ColorScheme>(preferredColorScheme);
|
||||
|
||||
const [primaryColor, setPrimaryColor] = useState<MantineTheme['primaryColor']>('red');
|
||||
const [secondaryColor, setSecondaryColor] = useState<MantineTheme['primaryColor']>('orange');
|
||||
const [primaryShade, setPrimaryShade] = useState<MantineTheme['primaryShade']>(6);
|
||||
@@ -31,11 +28,18 @@ function App(this: any, props: AppProps & { colorScheme: ColorScheme }) {
|
||||
setPrimaryShade,
|
||||
};
|
||||
|
||||
const toggleColorScheme = (value?: ColorScheme) => {
|
||||
const nextColorScheme = value || (colorScheme === 'dark' ? 'light' : 'dark');
|
||||
setColorScheme(nextColorScheme);
|
||||
setCookie('color-scheme', nextColorScheme, { maxAge: 60 * 60 * 24 * 30 });
|
||||
};
|
||||
// hook will return either 'dark' or 'light' on client
|
||||
// and always 'light' during ssr as window.matchMedia is not available
|
||||
const preferredColorScheme = useColorScheme();
|
||||
const [colorScheme, setColorScheme] = useLocalStorage<ColorScheme>({
|
||||
key: 'mantine-color-scheme',
|
||||
defaultValue: preferredColorScheme,
|
||||
getInitialValueInEffect: true,
|
||||
});
|
||||
|
||||
const toggleColorScheme = (value?: ColorScheme) =>
|
||||
setColorScheme(value || (colorScheme === 'dark' ? 'light' : 'dark'));
|
||||
|
||||
useHotkeys([['mod+J', () => toggleColorScheme()]]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Consola from 'consola';
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
function Post(req: NextApiRequest, res: NextApiResponse) {
|
||||
@@ -8,6 +9,12 @@ function Post(req: NextApiRequest, res: NextApiResponse) {
|
||||
success: true,
|
||||
});
|
||||
}
|
||||
// Warn that there was a wrong password attempt (date : wrong password, person's IP)
|
||||
Consola.warn(
|
||||
`${new Date().toLocaleString()} : Wrong password attempt, from ${
|
||||
req.headers['x-forwarded-for']
|
||||
}`
|
||||
);
|
||||
return res.status(200).json({
|
||||
success: false,
|
||||
});
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import axios from 'axios';
|
||||
import https from 'https';
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
async function Get(req: NextApiRequest, res: NextApiResponse) {
|
||||
// Parse req.body as a ServiceItem
|
||||
const { url } = req.query;
|
||||
const agent = new https.Agent({ rejectUnauthorized: false });
|
||||
await axios
|
||||
.get(url as string)
|
||||
.get(url as string, { httpsAgent: agent })
|
||||
.then((response) => {
|
||||
res.status(response.status).json(response.statusText);
|
||||
})
|
||||
|
||||
258
yarn.lock
258
yarn.lock
@@ -550,38 +550,38 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/babel-plugin@npm:^11.10.0":
|
||||
version: 11.10.0
|
||||
resolution: "@emotion/babel-plugin@npm:11.10.0"
|
||||
"@emotion/babel-plugin@npm:^11.10.5":
|
||||
version: 11.10.5
|
||||
resolution: "@emotion/babel-plugin@npm:11.10.5"
|
||||
dependencies:
|
||||
"@babel/helper-module-imports": ^7.16.7
|
||||
"@babel/plugin-syntax-jsx": ^7.17.12
|
||||
"@babel/runtime": ^7.18.3
|
||||
"@emotion/hash": ^0.9.0
|
||||
"@emotion/memoize": ^0.8.0
|
||||
"@emotion/serialize": ^1.1.0
|
||||
"@emotion/serialize": ^1.1.1
|
||||
babel-plugin-macros: ^3.1.0
|
||||
convert-source-map: ^1.5.0
|
||||
escape-string-regexp: ^4.0.0
|
||||
find-root: ^1.1.0
|
||||
source-map: ^0.5.7
|
||||
stylis: 4.0.13
|
||||
stylis: 4.1.3
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0
|
||||
checksum: 7f1c615e5e559fd037eab8d08b842cd6c089543f9c8829d22d097f69c5436298ff4fa9e1a2117892ce26a60abc1f57641dd9ccb011096b2e34c5588bf994addc
|
||||
checksum: e3353499c76c4422d6e900c0dfab73607056d9da86161a3f27c3459c193c4908050c5d252c68fcde231e13f02a9d8e0dc07d260317ae0e5206841e331cc4caae
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/cache@npm:^11.10.0":
|
||||
version: 11.10.0
|
||||
resolution: "@emotion/cache@npm:11.10.0"
|
||||
"@emotion/cache@npm:^11.10.5":
|
||||
version: 11.10.5
|
||||
resolution: "@emotion/cache@npm:11.10.5"
|
||||
dependencies:
|
||||
"@emotion/memoize": ^0.8.0
|
||||
"@emotion/sheet": ^1.2.0
|
||||
"@emotion/sheet": ^1.2.1
|
||||
"@emotion/utils": ^1.2.0
|
||||
"@emotion/weak-memoize": ^0.3.0
|
||||
stylis: 4.0.13
|
||||
checksum: 60786e3108c35d3f79bd434119f1b6e34120fccc92f4a129bb67596944b703c3396efa51ed373f0ee3d71de780d78f4d767c264f7d76b073d06d435a2d3c1edf
|
||||
stylis: 4.1.3
|
||||
checksum: 1dd2d9af2d3ecbd3d4469ecdf91a335eef6034c851b57a474471b2d2280613eb35bbed98c0368cc4625f188619fbdaf04cf07e8107aaffce94b2178444c0fe7b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -615,14 +615,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/react@npm:^11.10.0":
|
||||
version: 11.10.0
|
||||
resolution: "@emotion/react@npm:11.10.0"
|
||||
"@emotion/react@npm:^11.10.5":
|
||||
version: 11.10.5
|
||||
resolution: "@emotion/react@npm:11.10.5"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.18.3
|
||||
"@emotion/babel-plugin": ^11.10.0
|
||||
"@emotion/cache": ^11.10.0
|
||||
"@emotion/serialize": ^1.1.0
|
||||
"@emotion/babel-plugin": ^11.10.5
|
||||
"@emotion/cache": ^11.10.5
|
||||
"@emotion/serialize": ^1.1.1
|
||||
"@emotion/use-insertion-effect-with-fallbacks": ^1.0.0
|
||||
"@emotion/utils": ^1.2.0
|
||||
"@emotion/weak-memoize": ^0.3.0
|
||||
hoist-non-react-statics: ^3.3.1
|
||||
@@ -634,20 +635,20 @@ __metadata:
|
||||
optional: true
|
||||
"@types/react":
|
||||
optional: true
|
||||
checksum: 6d692e43ff53fd3b87d4a000a9aec2ef080d66a0ebb7d0b9529c46d1e6bc1ac8a27c7dd74c27a8274ec1df1e3c960b78c035fca5d8a901a48eda445c6163b33b
|
||||
checksum: 32b67b28e9b6d6c53b970072680697f04c2521441050bdeb19a1a7f0164af549b4dad39ff375eda1b6a3cf1cc86ba2c6fa55460ec040e6ebbca3e9ec58353cf7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/serialize@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "@emotion/serialize@npm:1.1.0"
|
||||
"@emotion/serialize@npm:^1.1.1":
|
||||
version: 1.1.1
|
||||
resolution: "@emotion/serialize@npm:1.1.1"
|
||||
dependencies:
|
||||
"@emotion/hash": ^0.9.0
|
||||
"@emotion/memoize": ^0.8.0
|
||||
"@emotion/unitless": ^0.8.0
|
||||
"@emotion/utils": ^1.2.0
|
||||
csstype: ^3.0.2
|
||||
checksum: 8f22f83194ad76cb3bbee481daa57fdc65ca3078a5db9e219c04151341ef93af80c7057aea17b64446682d275918f7ecc0c20e977c1af153c79a1485503fe717
|
||||
checksum: 24cfd5b16e6f2335c032ca33804a876e0442aaf8f9c94d269d23735ebd194fb1ed142542dd92191a3e6ef8bad5bd560dfc5aaf363a1b70954726dbd4dd93085c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -668,10 +669,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/sheet@npm:^1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "@emotion/sheet@npm:1.2.0"
|
||||
checksum: b3771e47963d36c179f9a1119055d7e5d18e2718e73ebe2b4b1c56f4bbf4ea6b12c50bbc52cd502f03f7981beb2fbb3fee2638b6f5ef6c5f223b06f8bf88ec7b
|
||||
"@emotion/sheet@npm:^1.2.1":
|
||||
version: 1.2.1
|
||||
resolution: "@emotion/sheet@npm:1.2.1"
|
||||
checksum: ce78763588ea522438156344d9f592203e2da582d8d67b32e1b0b98eaba26994c6c270f8c7ad46442fc9c0a9f048685d819cd73ca87e544520fd06f0e24a1562
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -682,6 +683,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/use-insertion-effect-with-fallbacks@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.0.0"
|
||||
peerDependencies:
|
||||
react: ">=16.8.0"
|
||||
checksum: 4f06a3b48258c832aa8022a262572061a31ff078d377e9164cccc99951309d70f4466e774fe704461b2f8715007a82ed625a54a5c7a127c89017d3ce3187d4f1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@emotion/utils@npm:^1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "@emotion/utils@npm:1.2.0"
|
||||
@@ -713,46 +723,44 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/core@npm:^0.7.3":
|
||||
version: 0.7.3
|
||||
resolution: "@floating-ui/core@npm:0.7.3"
|
||||
checksum: f48f9fb0d19dcbe7a68c38e8de7fabb11f0c0e6e0ef215ae60b5004900bacb1386e7b89cb377d91a90ff7d147ea1f06c2905136ecf34dea162d9696d8f448d5f
|
||||
"@floating-ui/core@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "@floating-ui/core@npm:1.0.1"
|
||||
checksum: c8a5f1a491788e5bebfe747e9372df2c7cbee0d8790ddf95e25149ac91ccf1a2cca8f768029826cfd3d687617c1d0f3241b97f1648bdf2a28d421f39e79c2eee
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/dom@npm:^0.5.3":
|
||||
version: 0.5.4
|
||||
resolution: "@floating-ui/dom@npm:0.5.4"
|
||||
"@floating-ui/dom@npm:^1.0.0":
|
||||
version: 1.0.4
|
||||
resolution: "@floating-ui/dom@npm:1.0.4"
|
||||
dependencies:
|
||||
"@floating-ui/core": ^0.7.3
|
||||
checksum: 9f9d8a51a828c6be5f187204aa6d293c6c9ef70d51dcc5891a4d85683745fceebf79ff8826d0f75ae41b45c3b138367d339756f27f41be87a8770742ebc0de42
|
||||
"@floating-ui/core": ^1.0.1
|
||||
checksum: f038ad74c8c0d4e3668705396c9955018ec4fce5de4a3ebc0d2317fa10a0dbae3ff6c9d331423014ab7558864977a83a1664be2800cb1a1d57cd35647a3d4907
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/react-dom-interactions@npm:0.6.6":
|
||||
version: 0.6.6
|
||||
resolution: "@floating-ui/react-dom-interactions@npm:0.6.6"
|
||||
"@floating-ui/react-dom-interactions@npm:^0.10.1":
|
||||
version: 0.10.3
|
||||
resolution: "@floating-ui/react-dom-interactions@npm:0.10.3"
|
||||
dependencies:
|
||||
"@floating-ui/react-dom": ^0.7.2
|
||||
"@floating-ui/react-dom": ^1.0.0
|
||||
aria-hidden: ^1.1.3
|
||||
use-isomorphic-layout-effect: ^1.1.1
|
||||
peerDependencies:
|
||||
react: ">=16.8.0"
|
||||
react-dom: ">=16.8.0"
|
||||
checksum: 3c6cf848c0d9cee6a4f68817a2b32a9addf6f3057f9f120e4d537efe1d2935cdf8a368d9b599b49b97c8cbcf9f25c8da1683f41c563754dd5eca47b622a74cc5
|
||||
checksum: 8f3dbe9ab8b59edec825209a488c6e25b18e1019691c6d0cfa3ada0b83226efc76f4d06bfdd3cc12a27813cff197e1988917d371204d119ba67bd4e3c3c3a3c8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@floating-ui/react-dom@npm:^0.7.2":
|
||||
version: 0.7.2
|
||||
resolution: "@floating-ui/react-dom@npm:0.7.2"
|
||||
"@floating-ui/react-dom@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "@floating-ui/react-dom@npm:1.0.0"
|
||||
dependencies:
|
||||
"@floating-ui/dom": ^0.5.3
|
||||
use-isomorphic-layout-effect: ^1.1.1
|
||||
"@floating-ui/dom": ^1.0.0
|
||||
peerDependencies:
|
||||
react: ">=16.8.0"
|
||||
react-dom: ">=16.8.0"
|
||||
checksum: bc3f2b5557f87f6f4bbccfe3e8d097abafad61a41083d3b79f3499f27590e273bcb3dc7136c2444841ee7a8c0d2a70cc1385458c16103fa8b70eade80c24af52
|
||||
checksum: d79e3c8570b0eaef5e968cd9c69de2c6bb372a5316e4e69a1cd12dae81771863ef430e81b74a0c21cefba663a2f971d8540c7294d7fb3b9807e32ba2a00c1e76
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1098,84 +1106,84 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mantine/core@npm:^5.2.3":
|
||||
version: 5.2.3
|
||||
resolution: "@mantine/core@npm:5.2.3"
|
||||
"@mantine/core@npm:^5.7.2":
|
||||
version: 5.7.2
|
||||
resolution: "@mantine/core@npm:5.7.2"
|
||||
dependencies:
|
||||
"@floating-ui/react-dom-interactions": 0.6.6
|
||||
"@mantine/styles": 5.2.3
|
||||
"@mantine/utils": 5.2.3
|
||||
"@floating-ui/react-dom-interactions": ^0.10.1
|
||||
"@mantine/styles": 5.7.2
|
||||
"@mantine/utils": 5.7.2
|
||||
"@radix-ui/react-scroll-area": 1.0.0
|
||||
react-textarea-autosize: 8.3.4
|
||||
peerDependencies:
|
||||
"@mantine/hooks": 5.2.3
|
||||
"@mantine/hooks": 5.7.2
|
||||
react: ">=16.8.0"
|
||||
react-dom: ">=16.8.0"
|
||||
checksum: 39c3328335a9de3d1f72a8e7d043005f0920039e37ff4ff8029d1955ec5b4fad9f5fb2a112490862061e0ecf1803d0fdaeb532c0b716394681d17abd6b410cc8
|
||||
checksum: 54a5460d4367179d4016068e6cdfdd6d6776921ff8e0c24926881564655ec0255588a842e166fb754685bf31fb485160a1759d07e0435a5620307b771dce65c3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mantine/dates@npm:^5.2.3":
|
||||
version: 5.2.3
|
||||
resolution: "@mantine/dates@npm:5.2.3"
|
||||
"@mantine/dates@npm:^5.7.2":
|
||||
version: 5.7.2
|
||||
resolution: "@mantine/dates@npm:5.7.2"
|
||||
dependencies:
|
||||
"@mantine/utils": 5.2.3
|
||||
"@mantine/utils": 5.7.2
|
||||
peerDependencies:
|
||||
"@mantine/core": 5.2.3
|
||||
"@mantine/hooks": 5.2.3
|
||||
"@mantine/core": 5.7.2
|
||||
"@mantine/hooks": 5.7.2
|
||||
dayjs: ">=1.0.0"
|
||||
react: ">=16.8.0"
|
||||
checksum: 0d14f10b4b36a17c48cedbd7261c2d4a831812cb80d52aa0816176835ab3e569ef260a32592a0277235b1c559994cd289953749b6b7400948523ee2b8d9a67f7
|
||||
checksum: 76362eba6e51ab95e2343482203598a17b62aad510620cc5bf7f3a703b808c0ded61e995c70df80d09a1c36e15f76acc66dd589b9e3b0d32f1bc5246c705be31
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mantine/dropzone@npm:^5.2.3":
|
||||
version: 5.2.3
|
||||
resolution: "@mantine/dropzone@npm:5.2.3"
|
||||
"@mantine/dropzone@npm:^5.7.2":
|
||||
version: 5.7.2
|
||||
resolution: "@mantine/dropzone@npm:5.7.2"
|
||||
dependencies:
|
||||
"@mantine/utils": 5.2.3
|
||||
react-dropzone: 14.2.1
|
||||
"@mantine/utils": 5.7.2
|
||||
react-dropzone: 14.2.3
|
||||
peerDependencies:
|
||||
"@mantine/core": 5.2.3
|
||||
"@mantine/hooks": 5.2.3
|
||||
"@mantine/core": 5.7.2
|
||||
"@mantine/hooks": 5.7.2
|
||||
react: ">=16.8.0"
|
||||
react-dom: ">=16.8.0"
|
||||
checksum: a81945cbed3b778d8e842287f10a02176c8f75998ee420598ae125daf75154682ad27b9f2cfab22ecfaba7956a1f122cf43e134c7ef8c5cfc0f9ec0cebe63863
|
||||
checksum: 604c0adb49ee4939c739f19ec86ff1dbc27d59b46fc13f3ab2ff5cebd7cd6eae39936f54760db362d95a70a0b9b2c89af558a2acbd26ef1fa36b20a67803be5f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mantine/form@npm:^5.2.3":
|
||||
version: 5.2.3
|
||||
resolution: "@mantine/form@npm:5.2.3"
|
||||
"@mantine/form@npm:^5.7.2":
|
||||
version: 5.7.2
|
||||
resolution: "@mantine/form@npm:5.7.2"
|
||||
dependencies:
|
||||
fast-deep-equal: ^3.1.3
|
||||
klona: ^2.0.5
|
||||
peerDependencies:
|
||||
react: ">=16.8.0"
|
||||
checksum: e7285c99700d85657860dce516af29366d42fdc621f479069d648e6228e953513e19aa1bceab8f439990f9934c8cd74cd6468e608152c618808a434488796fa4
|
||||
checksum: 34d236411a0fbe32c194a2f5157246854446380b41e970f341703137d1422a6c43ae307175dd4c0d2c0512541e42aa1636ecd56d5550d6714c51f1f4890a592c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mantine/hooks@npm:^5.2.3":
|
||||
version: 5.2.3
|
||||
resolution: "@mantine/hooks@npm:5.2.3"
|
||||
"@mantine/hooks@npm:^5.7.2":
|
||||
version: 5.7.2
|
||||
resolution: "@mantine/hooks@npm:5.7.2"
|
||||
peerDependencies:
|
||||
react: ">=16.8.0"
|
||||
checksum: da49a092cd5401366609bb3def6c37df61a9d8cf86b1c1491f17483b1b31475ba50b4330edfe7ada712e37fc1bc9af1dd116ed0d411b2b143eadf30ec53e89d6
|
||||
checksum: 85977a0f3968be3ab5556e79cd378f210be3ffa0b4b3c59e995848ec05d8a8c9c340d2bfcbd1900fe05495a8c2a977653233f793a304984f5dc1f626d4d6b386
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mantine/modals@npm:^5.2.3":
|
||||
version: 5.2.3
|
||||
resolution: "@mantine/modals@npm:5.2.3"
|
||||
"@mantine/modals@npm:^5.7.2":
|
||||
version: 5.7.2
|
||||
resolution: "@mantine/modals@npm:5.7.2"
|
||||
dependencies:
|
||||
"@mantine/utils": 5.2.3
|
||||
"@mantine/utils": 5.7.2
|
||||
peerDependencies:
|
||||
"@mantine/core": 5.2.3
|
||||
"@mantine/hooks": 5.2.3
|
||||
"@mantine/core": 5.7.2
|
||||
"@mantine/hooks": 5.7.2
|
||||
react: ">=16.8.0"
|
||||
react-dom: ">=16.8.0"
|
||||
checksum: 37742fd4f4c740b3a7ff7b5ced1855391ccf8279be7dfe6d24410762fe39168e6eb715fb37b39b3dca7b213e013721939993932cd205836dd694812f86c39761
|
||||
checksum: f233d6aa976e519bde789534801395c1f9d3e84c14893b992ffef4e3ebcde5aa4b2b0360d4b33b98681992a72ce13fdc0f7591afd80bb58accb3c63260a07fa8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1193,18 +1201,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mantine/notifications@npm:^5.2.3":
|
||||
version: 5.2.3
|
||||
resolution: "@mantine/notifications@npm:5.2.3"
|
||||
"@mantine/notifications@npm:^5.7.2":
|
||||
version: 5.7.2
|
||||
resolution: "@mantine/notifications@npm:5.7.2"
|
||||
dependencies:
|
||||
"@mantine/utils": 5.2.3
|
||||
"@mantine/utils": 5.7.2
|
||||
react-transition-group: 4.4.2
|
||||
peerDependencies:
|
||||
"@mantine/core": 5.2.3
|
||||
"@mantine/hooks": 5.2.3
|
||||
"@mantine/core": 5.7.2
|
||||
"@mantine/hooks": 5.7.2
|
||||
react: ">=16.8.0"
|
||||
react-dom: ">=16.8.0"
|
||||
checksum: fd98213e6ec3dd952c8740a8f1f80df29f55978245141f96fb263f8eea28021bc98e09470af069fd63914cfaa551a25bc018ce5700d4887e2d30d3702948e004
|
||||
checksum: db1a8e343bda01dec80a9eb336daaa183ea73b8a8eed20cf80a5ef15b620f79488041dd492a68bd7460c0d9b2432a2f71ccc049bc44894c4c8837c5c078a5c3e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1252,6 +1260,20 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mantine/styles@npm:5.7.2":
|
||||
version: 5.7.2
|
||||
resolution: "@mantine/styles@npm:5.7.2"
|
||||
dependencies:
|
||||
clsx: 1.1.1
|
||||
csstype: 3.0.9
|
||||
peerDependencies:
|
||||
"@emotion/react": ">=11.9.0"
|
||||
react: ">=16.8.0"
|
||||
react-dom: ">=16.8.0"
|
||||
checksum: d440f92b830e232b4826e0ff8002f4821d5eee0f379d8e9e5cea9346ca550719b89aa850d5d06f0feebd6150172a398136391285d57e7174180bfa8294bbba65
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mantine/utils@npm:5.0.0":
|
||||
version: 5.0.0
|
||||
resolution: "@mantine/utils@npm:5.0.0"
|
||||
@@ -1270,12 +1292,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@mantine/utils@npm:5.2.3":
|
||||
version: 5.2.3
|
||||
resolution: "@mantine/utils@npm:5.2.3"
|
||||
"@mantine/utils@npm:5.7.2":
|
||||
version: 5.7.2
|
||||
resolution: "@mantine/utils@npm:5.7.2"
|
||||
peerDependencies:
|
||||
react: ">=16.8.0"
|
||||
checksum: bac3a5637efc2163b8308d42bbb4bc828b0cbeecfcbcb81dfb4b252afd728197b5a96abd37b0f0c7a432be2ab30e0525bbdefbe3f89f35bf321c168464af4a01
|
||||
checksum: 35ce46a03a24f8f2b649b833b725120e50e639a66a3a9b399a10f5c4083446a4338ececd8b1d6f0897743cb1bc6d6757c7a530c515f032c0ab23b4f8e9d04b2a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -3382,10 +3404,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"dayjs@npm:^1.11.5":
|
||||
version: 1.11.5
|
||||
resolution: "dayjs@npm:1.11.5"
|
||||
checksum: e3bbaa7b4883b31be4bf75a181f1447fbb19800c29b332852125aab96baeff3ac232dcba8b88c4ea17d3b636c99dac5fb9d1af4bb6ae26615698bbc4a852dffb
|
||||
"dayjs@npm:^1.11.6":
|
||||
version: 1.11.6
|
||||
resolution: "dayjs@npm:1.11.6"
|
||||
checksum: 18bdfd927009b68eab08dca578e421d4a581cefcbe9337f54c5d9e0d941ffb6b221c4b2c1cab15cdd9d419940e768ac4c984531461a90bbe1c158b75fe160580
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -4801,17 +4823,17 @@ __metadata:
|
||||
"@dnd-kit/core": ^6.0.5
|
||||
"@dnd-kit/sortable": ^7.0.1
|
||||
"@dnd-kit/utilities": ^3.2.0
|
||||
"@emotion/react": ^11.10.0
|
||||
"@emotion/react": ^11.10.5
|
||||
"@emotion/server": ^11.10.0
|
||||
"@mantine/carousel": ^5.1.0
|
||||
"@mantine/core": ^5.2.3
|
||||
"@mantine/dates": ^5.2.3
|
||||
"@mantine/dropzone": ^5.2.3
|
||||
"@mantine/form": ^5.2.3
|
||||
"@mantine/hooks": ^5.2.3
|
||||
"@mantine/modals": ^5.2.3
|
||||
"@mantine/core": ^5.7.2
|
||||
"@mantine/dates": ^5.7.2
|
||||
"@mantine/dropzone": ^5.7.2
|
||||
"@mantine/form": ^5.7.2
|
||||
"@mantine/hooks": ^5.7.2
|
||||
"@mantine/modals": ^5.7.2
|
||||
"@mantine/next": ^5.2.3
|
||||
"@mantine/notifications": ^5.2.3
|
||||
"@mantine/notifications": ^5.7.2
|
||||
"@mantine/prism": ^5.0.0
|
||||
"@next/bundle-analyzer": ^12.1.4
|
||||
"@next/eslint-plugin-next": ^12.1.4
|
||||
@@ -4829,7 +4851,7 @@ __metadata:
|
||||
axios: ^0.27.2
|
||||
consola: ^2.15.3
|
||||
cookies-next: ^2.1.1
|
||||
dayjs: ^1.11.5
|
||||
dayjs: ^1.11.6
|
||||
dockerode: ^3.3.2
|
||||
embla-carousel-react: ^7.0.0
|
||||
eslint: ^8.20.0
|
||||
@@ -7089,16 +7111,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-dropzone@npm:14.2.1":
|
||||
version: 14.2.1
|
||||
resolution: "react-dropzone@npm:14.2.1"
|
||||
"react-dropzone@npm:14.2.3":
|
||||
version: 14.2.3
|
||||
resolution: "react-dropzone@npm:14.2.3"
|
||||
dependencies:
|
||||
attr-accept: ^2.2.2
|
||||
file-selector: ^0.6.0
|
||||
prop-types: ^15.8.1
|
||||
peerDependencies:
|
||||
react: ">= 16.8 || 18.0.0"
|
||||
checksum: 8556d997d66bad79fe165a30d6dc8f917c67d8c7d23069c417eb2a0da6df824ba71b84b532707711e184da105122f6a6e81104341dc5b8c0f96e318267fdda91
|
||||
checksum: 174b744d5ca898cf3d84ec1aeb6cef5211c446697e45dc8ece8287a03d291f8d07253206d5a1247ef156fd385d65e7de666d4d5c2986020b8543b8f2434e8b40
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -7835,10 +7857,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stylis@npm:4.0.13":
|
||||
version: 4.0.13
|
||||
resolution: "stylis@npm:4.0.13"
|
||||
checksum: 8ea7a87028b6383c6a982231c4b5b6150031ce028e0fdaf7b2ace82253d28a8af50cc5a9da8a421d3c7c4441592f393086e332795add672aa4a825f0fe3713a3
|
||||
"stylis@npm:4.1.3":
|
||||
version: 4.1.3
|
||||
resolution: "stylis@npm:4.1.3"
|
||||
checksum: d04dbffcb9bf2c5ca8d8dc09534203c75df3bf711d33973ea22038a99cc475412a350b661ebd99cbc01daa50d7eedcf0d130d121800eb7318759a197023442a6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user