Merge remote-tracking branch 'origin/dev' into enh-vuejs

This commit is contained in:
Axolotle 2020-11-05 15:12:45 +01:00
commit c0d1a90a53
35 changed files with 8279 additions and 400 deletions

1
.gitignore vendored
View file

@ -20,5 +20,4 @@ ca.crt
# Debug CSS file # Debug CSS file
src/css/style.css src/css/style.css
src/bower_components
src/dist src/dist

9
.travis.yml Normal file
View file

@ -0,0 +1,9 @@
language: node_js
node_js:
- "10"
before_install:
- cd src
script:
- npm ci
- gulp build --dev
- gulp lint --dev

View file

@ -479,5 +479,7 @@
"unmaintained_details": "Fa temps que no es manté aquesta aplicació i la persona que la mantenia ja no ho fa o no té temps per fer-ho. Us convidem a mirar el repositori de l'aplicació per oferir la vostra ajuda", "unmaintained_details": "Fa temps que no es manté aquesta aplicació i la persona que la mantenia ja no ho fa o no té temps per fer-ho. Us convidem a mirar el repositori de l'aplicació per oferir la vostra ajuda",
"issues": "%s problemes", "issues": "%s problemes",
"operation_failed_explanation": "Aquesta operació ha fallat! Ens sap molt greu :( Podeu intentar <a href='https://yunohost.org/help'>demanar ajuda</a>. Si us plau doneu *el registre complet* de l'operació a la gent que intenta ajudar-vos. Podeu fer-ho fent clic al botó verd \"Compartir amb Yunopaste\". Quan compartiu els registres, YunoHost intentarà anonimitzar automàticament dades privades com els noms de domini i les IPs.", "operation_failed_explanation": "Aquesta operació ha fallat! Ens sap molt greu :( Podeu intentar <a href='https://yunohost.org/help'>demanar ajuda</a>. Si us plau doneu *el registre complet* de l'operació a la gent que intenta ajudar-vos. Podeu fer-ho fent clic al botó verd \"Compartir amb Yunopaste\". Quan compartiu els registres, YunoHost intentarà anonimitzar automàticament dades privades com els noms de domini i les IPs.",
"diagnosis_explanation": "La funció de diagnòstic intentarà identificar els errors més comuns en diferents aspectes del servidor per verificar que tot funciona correctament. El diagnòstic s'executa automàticament dues vegades al dia i s'envia un correu electrònic a l'administrador si es troben errors. Tingueu en compte que no tots els tests seran rellevants si no s'utilitzen algunes funcions específiques (com per exemple XMPP) o pot ser que falli si teniu un sistema amb una configuració complexa. En aquests casos, i si sabeu el que feu, podeu ignorar els problemes o avisos corresponents." "diagnosis_explanation": "La funció de diagnòstic intentarà identificar els errors més comuns en diferents aspectes del servidor per verificar que tot funciona correctament. El diagnòstic s'executa automàticament dues vegades al dia i s'envia un correu electrònic a l'administrador si es troben errors. Tingueu en compte que no tots els tests seran rellevants si no s'utilitzen algunes funcions específiques (com per exemple XMPP) o pot ser que falli si teniu un sistema amb una configuració complexa. En aquests casos, i si sabeu el que feu, podeu ignorar els problemes o avisos corresponents.",
"pending_migrations": "Hi ha algunes migracions pendents esperant per ser executades. Aneu a <a href='#/tools/migrations'>Eines > Migracions</a> per fer-les.",
"log_suboperations": "Sub-operacions"
} }

View file

@ -14,7 +14,7 @@
"app_access_title": "%s Zugriffsrechte", "app_access_title": "%s Zugriffsrechte",
"app_debug_no_logs": "Anwendungslogs stehen nicht zur Verfügung", "app_debug_no_logs": "Anwendungslogs stehen nicht zur Verfügung",
"app_debug_tab": "Debugging Informationen anzeigen", "app_debug_tab": "Debugging Informationen anzeigen",
"app_info_access_desc": "Gruppen / Benutzer, die auf diese App zugreifen dürfen:", "app_info_access_desc": "Gruppen / Benutzer*innen, die auf diese App zugreifen dürfen:",
"app_info_debug_desc": "Debugging Informationen für diese Applikation anzeigen.", "app_info_debug_desc": "Debugging Informationen für diese Applikation anzeigen.",
"app_info_default_desc": "Hauptdomain auf diese App (%s) weiterleiten.", "app_info_default_desc": "Hauptdomain auf diese App (%s) weiterleiten.",
"app_info_uninstall_desc": "Diese App löschen.", "app_info_uninstall_desc": "Diese App löschen.",
@ -149,7 +149,7 @@
"mailbox_quota_description": "Zum Beispiel, eine CD verfügt über 700M, eine über 4700M.", "mailbox_quota_description": "Zum Beispiel, eine CD verfügt über 700M, eine über 4700M.",
"manage_apps": "Apps verwalten", "manage_apps": "Apps verwalten",
"manage_domains": "Domains verwalten", "manage_domains": "Domains verwalten",
"manage_users": "Benutzer verwalten", "manage_users": "Benutzer*innen verwalten",
"memory": "Arbeitsspeicher", "memory": "Arbeitsspeicher",
"menu": "Menü", "menu": "Menü",
"mode": "Modus", "mode": "Modus",
@ -182,7 +182,7 @@
"port": "Port", "port": "Port",
"ports": "Ports", "ports": "Ports",
"postinstall": "Einrichtung", "postinstall": "Einrichtung",
"postinstall_domain": "Dies ist die primäre Domain für deinen YunoHost Server und auch die Domain, an der sich die Benutzer anmelden werden. Sie wird für alle Benutzer sichtbar sein, daher wähle die primäre Domain sorgfältig aus.", "postinstall_domain": "Dies ist die primäre Domain für deinen YunoHost Server und auch die Domain, an der sich die Benutzer*innen anmelden werden. Sie wird für alle Benutzer*innen sichtbar sein, daher wähle die primäre Domain sorgfältig aus.",
"postinstall_intro_1": "Gratuliere! YunoHost wurde erfolgreich installiert.", "postinstall_intro_1": "Gratuliere! YunoHost wurde erfolgreich installiert.",
"postinstall_intro_2": "Zwei weitere Einstellungen sind notwendig, um den Dienst auf deinem Server zu aktivieren.", "postinstall_intro_2": "Zwei weitere Einstellungen sind notwendig, um den Dienst auf deinem Server zu aktivieren.",
"postinstall_intro_3": "Du kannst mehr Informationen in der <a href='//yunohost.org/postinstall' target='_blank'>Dokumentation</a> finden", "postinstall_intro_3": "Du kannst mehr Informationen in der <a href='//yunohost.org/postinstall' target='_blank'>Dokumentation</a> finden",
@ -218,7 +218,7 @@
"swap": "Auslagerungsspeicher", "swap": "Auslagerungsspeicher",
"system": "System", "system": "System",
"system_apps": "Apps", "system_apps": "Apps",
"system_apps_nothing": "Allen Apps sind auf dem neuesten Stand!", "system_apps_nothing": "Alle Applikationen sind auf dem neuesten Stand!",
"system_delayed_upgrade": "Zurückgestellte Aktualisierung", "system_delayed_upgrade": "Zurückgestellte Aktualisierung",
"system_delayed_upgrade_warning": "<b>%s</b> wird automatisch innerhalb der nächsten Stunde aktualisiert.", "system_delayed_upgrade_warning": "<b>%s</b> wird automatisch innerhalb der nächsten Stunde aktualisiert.",
"system_packages": "Systempakete", "system_packages": "Systempakete",
@ -260,19 +260,19 @@
"user_emailaliases": "E-Mail Aliase", "user_emailaliases": "E-Mail Aliase",
"user_emailforward": "E-Mail Weiterleitung", "user_emailforward": "E-Mail Weiterleitung",
"user_fullname": "Vollständiger Name", "user_fullname": "Vollständiger Name",
"user_interface_link": "Benutzeroberfläche", "user_interface_link": "Benutzer*innenoberfläche",
"user_mailbox_quota": "Mailbox Kontingent", "user_mailbox_quota": "Mailbox Kontingent",
"user_new_forward": "weiterleitung@externedomain.org", "user_new_forward": "weiterleitung@externedomain.org",
"user_new_mail": "newmail@mydomain.org", "user_new_mail": "newmail@mydomain.org",
"user_username": "Benutzername", "user_username": "Benutzer*innenname",
"user_username_edit": "Account von %s bearbeiten", "user_username_edit": "Account von %s bearbeiten",
"users": "Benutzer", "users": "Benutzer*in",
"users_list": "Benutzerliste", "users_list": "Benutzerliste",
"users_new": "Neuer Benutzer", "users_new": "Neue_r Benutzer*in",
"users_no": "Keine Benutzer.", "users_no": "Keine Benutzer*in.",
"versions": "Versionen", "versions": "Versionen",
"view_user_profile": "Das Profil von %s ansehen", "view_user_profile": "Das Profil von %s ansehen",
"warning_first_user": "Bitte zuerst einen <a href='#/users/create' class='alert-link'>Benutzer anlegen</a>.", "warning_first_user": "Bitte zuerst einen <a href='#/users/create' class='alert-link'>Benutzer*in anlegen</a>.",
"write": "Schreiben", "write": "Schreiben",
"wrong_password": "Falsches Passwort", "wrong_password": "Falsches Passwort",
"yes": "Ja", "yes": "Ja",
@ -281,7 +281,7 @@
"app_state": "Applikationsstatus: ", "app_state": "Applikationsstatus: ",
"app_repository": "Applikationsherkunft ", "app_repository": "Applikationsherkunft ",
"app_state_notworking": "nicht funktionierend", "app_state_notworking": "nicht funktionierend",
"app_state_working": "funktionierend", "app_state_working": "funktioniert",
"backup_experimental_warning": "Bitte beachte, dass das Backup-Feature noch experimentell ist und daher noch instabil sein könnte.", "backup_experimental_warning": "Bitte beachte, dass das Backup-Feature noch experimentell ist und daher noch instabil sein könnte.",
"diagnosis": "Diagnose", "diagnosis": "Diagnose",
"diagnosis_hide_private": "Zeige der Diagnose ohne persönliche Daten an", "diagnosis_hide_private": "Zeige der Diagnose ohne persönliche Daten an",
@ -300,7 +300,7 @@
"mailbox_quota_placeholder": "Leer lassen oder 0 zum Deaktivieren eintragen.", "mailbox_quota_placeholder": "Leer lassen oder 0 zum Deaktivieren eintragen.",
"user_mailbox_use": "von der Mailbox verwendeter Speicherplatz", "user_mailbox_use": "von der Mailbox verwendeter Speicherplatz",
"certificate_alert_not_valid": "KRITISCH : Das aktuelle Zertifikat ist nicht gültig ! HTTPS wird nicht funktionieren !", "certificate_alert_not_valid": "KRITISCH : Das aktuelle Zertifikat ist nicht gültig ! HTTPS wird nicht funktionieren !",
"certificate_alert_selfsigned": "WARNUNG : Es wird ein selbstsigniertes Zertifikat verwendet. Der Browser wird neuen Besuchern daher eine Fehlermeldung anzeigen !", "certificate_alert_selfsigned": "WARNUNG : Es wird ein selbstsigniertes Zertifikat verwendet. Der Browser wird neuen Besucher*innen daher eine Fehlermeldung anzeigen !",
"certificate_alert_letsencrypt_about_to_expire": "Das aktuelle Zertifikat läuft in Kürze ab. Es wird bald automatisch erneuert.", "certificate_alert_letsencrypt_about_to_expire": "Das aktuelle Zertifikat läuft in Kürze ab. Es wird bald automatisch erneuert.",
"certificate_alert_about_to_expire": "WARNUNG : Das aktuelle Zertifikat läuft in Kürze ab ! Es wird NICHT automatisch erneuert !", "certificate_alert_about_to_expire": "WARNUNG : Das aktuelle Zertifikat läuft in Kürze ab ! Es wird NICHT automatisch erneuert !",
"certificate_alert_good": "Okay, das aktuelle Zertifikat scheint zu funktionieren !", "certificate_alert_good": "Okay, das aktuelle Zertifikat scheint zu funktionieren !",
@ -317,7 +317,7 @@
"certificate_authority": "Zertifizierungsstelle", "certificate_authority": "Zertifizierungsstelle",
"validity": "Gültigkeit", "validity": "Gültigkeit",
"domain_is_eligible_for_ACME": "Die Domain scheint korrekt konfiguriert zu sein, um ein Let's Encrypt Zertifikat installieren zu können !", "domain_is_eligible_for_ACME": "Die Domain scheint korrekt konfiguriert zu sein, um ein Let's Encrypt Zertifikat installieren zu können !",
"domain_not_eligible_for_ACME": "Die Domain scheint nicht korrekt konfiguriert zu sein, um ein Let's Encrypt Zertifikat installieren zu können ! Bitte überprüfe deine DNS-Konfiguration und die Erreichbarkeit deines HTTP-Servers.", "domain_not_eligible_for_ACME": "Die Domain scheint nicht korrekt konfiguriert zu sein, um ein Let's Encrypt Zertifikat installieren zu können! Bitte überprüfen Sie Ihre DNS-Konfiguration und die Erreichbarkeit Ihres HTTP-Servers. Der 'DNS records' und 'Web' Bereich in <a href='#/diagnosis'>der Diagnose Seite</a> kann Ihnen helfen zu verstehen, was falsch konfiguriert ist.",
"install_letsencrypt_cert": "Let's Encrypt Zertifikat installieren", "install_letsencrypt_cert": "Let's Encrypt Zertifikat installieren",
"manually_renew_letsencrypt_message": "Das Zertifikat wird, innerhalb der letzten 15 Tage bevor es ungültig wird, automatisch erneuert. Du kannst es aber auch manuell erneuern. (Nicht empfohlen).", "manually_renew_letsencrypt_message": "Das Zertifikat wird, innerhalb der letzten 15 Tage bevor es ungültig wird, automatisch erneuert. Du kannst es aber auch manuell erneuern. (Nicht empfohlen).",
"manually_renew_letsencrypt": "Jetzt manuell erneuern", "manually_renew_letsencrypt": "Jetzt manuell erneuern",
@ -366,10 +366,10 @@
"name": "Name", "name": "Name",
"install_community_appslists_warning": "Nimm zur Kenntnis, dass diese Applikationen <strong>nicht</strong> offiziell sind und nicht von YunoHost gepflegt werden.<br /> Diese Applikationen sind auf eigenes Risiko zu installieren und können dein System demolieren.", "install_community_appslists_warning": "Nimm zur Kenntnis, dass diese Applikationen <strong>nicht</strong> offiziell sind und nicht von YunoHost gepflegt werden.<br /> Diese Applikationen sind auf eigenes Risiko zu installieren und können dein System demolieren.",
"app_change_label": "Label ändern", "app_change_label": "Label ändern",
"app_state_working_explanation": "Der Verwalter dieser App deklariert sie als 'funktionierend'. Das heißt sie sollte funktionieren (vgl. App Level) aber ist nicht zwangsläufig begutachtet, sie kann Probleme enthalten oder ist nicht vollkommen integriert in YunoHost.", "app_state_working_explanation": "Der/die Verwalter*in dieser App deklariert sie als 'funktionierend'. Das heißt sie sollte funktionieren (vgl. App Level) aber ist nicht zwangsläufig begutachtet, sie kann Probleme enthalten oder ist nicht vollkommen integriert in YunoHost.",
"app_state_high-quality": "hohe Qualität", "app_state_high-quality": "hohe Qualität",
"app_state_notworking_explanation": "Der Verwalter dieser App deklariert sie als 'nicht funktionierend'. SIE WIRD IHR SYSTEM ZERSTÖREN!", "app_state_notworking_explanation": "Der/die Verwalter*in dieser App deklariert sie als 'nicht funktionierend'. SIE WIRD IHR SYSTEM ZERSTÖREN!",
"app_state_inprogress_explanation": "Der Verwalter dieser App deklariert sie als nicht bereit für den produktiven Einsatz. SEIEN SIE VORSICHTIG!", "app_state_inprogress_explanation": "Der/die Verwalter*in dieser App deklariert sie als nicht bereit für den produktiven Einsatz. SEIEN SIE VORSICHTIG!",
"app_no_actions": "Diese Anwendung hat keine Aktionen", "app_no_actions": "Diese Anwendung hat keine Aktionen",
"app_level": "App Level", "app_level": "App Level",
"app_info_changelabel_desc": "Änder App Bezeichnung im Portal.", "app_info_changelabel_desc": "Änder App Bezeichnung im Portal.",
@ -396,15 +396,15 @@
"license": "Lizenz", "license": "Lizenz",
"level": "Level", "level": "Level",
"internal_exception": "<strong>Yunohost ist auf einen internen Fehler gestoßen:/</strong><br><em>Das tut uns wirklich leid.<br>Du solltest <a href=\"https://forum.yunohost.org/\">im Forum</a> nach Hilfe fragen oder <a href=\"https://chat.yunohost.org/\">im Chat</a>, um die Situation zu beheben, oder berichte den Fehler auf <a href=\"https://github.com/YunoHost/issues\">dem Bugtracker</a>.</em><br>Die folgenden Informationen können für die Person, die dir hilft, nützlich sein:<h3>Action</h3><pre>%s%s</pre><h3>Traceback</h3><pre>%s</pre>", "internal_exception": "<strong>Yunohost ist auf einen internen Fehler gestoßen:/</strong><br><em>Das tut uns wirklich leid.<br>Du solltest <a href=\"https://forum.yunohost.org/\">im Forum</a> nach Hilfe fragen oder <a href=\"https://chat.yunohost.org/\">im Chat</a>, um die Situation zu beheben, oder berichte den Fehler auf <a href=\"https://github.com/YunoHost/issues\">dem Bugtracker</a>.</em><br>Die folgenden Informationen können für die Person, die dir hilft, nützlich sein:<h3>Action</h3><pre>%s%s</pre><h3>Traceback</h3><pre>%s</pre>",
"maintained_details": "Diese App wurde von ihrem Betreuer in den letzten Monaten betreut.", "maintained_details": "Diese App wurde von ihrem/ihrer Betreuer*in in den letzten Monaten betreut.",
"only_highquality_apps": "Nur hochqualitative Apps", "only_highquality_apps": "Nur hochqualitative Apps",
"only_decent_quality_apps": "Nur qualitativ hochwertige Apps", "only_decent_quality_apps": "Nur qualitativ hochwertige Apps",
"orphaned": "Nicht betreut", "orphaned": "Nicht betreut",
"orphaned_details": "Diese App wird nicht mehr gepflegt. Sie kann noch funktionieren, wird aber kein Upgrade mehr erhalten bis jemand Freiwilliges die weitere Pflege übernimmt. Zögere nicht zu kommen und sie wiederzubeleben!", "orphaned_details": "Diese App wird nicht mehr gepflegt. Sie kann noch funktionieren, wird aber kein Upgrade mehr erhalten bis jemand Freiwilliges die weitere Pflege übernimmt. Zögere nicht zu kommen und sie wiederzubeleben!",
"request_adoption": "ausstehende Annahme", "request_adoption": "ausstehende Annahme",
"request_adoption_details": "Der aktuelle Betreuer möchte die Pflege dieser App einstellen. Zögere nicht, dich selbst als neuen Betreuer vorzuschlagen!", "request_adoption_details": "Der/die aktuelle Betreuer*in möchte die Pflege dieser App einstellen. Zögere nicht, dich selbst als neue_n Betreuer*in vorzuschlagen!",
"request_help": "Hilfe benötigt", "request_help": "Hilfe benötigt",
"request_help_details": "Der aktuelle Betreuer möchte Hilfe bei der Pflege dieser App. Zögere nicht, daran mitzuwirken!", "request_help_details": "Der/die aktuelle Betreuer*in möchte Hilfe bei der Pflege dieser App. Zögere nicht, daran mitzuwirken!",
"logs_system": "Kernel-Logs und andere Ereignisse auf niederer Ebene", "logs_system": "Kernel-Logs und andere Ereignisse auf niederer Ebene",
"select_none": "Wähle keine", "select_none": "Wähle keine",
"skip": "Überspringe", "skip": "Überspringe",
@ -413,7 +413,7 @@
"logs_operation": "Operationen, die auf dem System mit YunoHost durchgeführt wurden", "logs_operation": "Operationen, die auf dem System mit YunoHost durchgeführt wurden",
"search_for_apps": "Suche nach Apps...", "search_for_apps": "Suche nach Apps...",
"logs_history": "Historie der Befehlsausführung auf dem System", "logs_history": "Historie der Befehlsausführung auf dem System",
"purge_user_data_warning": "Die Löschung der Benutzerdaten ist nicht umkehrbar. Sei Dir sicher, was du tust!", "purge_user_data_warning": "Die Löschung der Benutzer*indaten ist nicht umkehrbar. Sei Dir sicher, was du tust!",
"logs_error": "Fehler", "logs_error": "Fehler",
"started_at": "Gestartet um:", "started_at": "Gestartet um:",
"logs_package": "Historie des Debian-Paket-Managements", "logs_package": "Historie des Debian-Paket-Managements",
@ -450,13 +450,13 @@
"everything_good": "Alles gut!", "everything_good": "Alles gut!",
"ignore": "Ignorieren", "ignore": "Ignorieren",
"configuration": "Konfiguration", "configuration": "Konfiguration",
"group_explain_all_users": "Dies ist eine spezielle Gruppe, die alle Benutzerkonten auf dem Server enthält", "group_explain_all_users": "Dies ist eine spezielle Gruppe, die alle Benutzer*innenkonten auf dem Server enthält",
"ignored": "%s wird ignoriert", "ignored": "%s wird ignoriert",
"last_ran": "Das letzte Mal lief es:", "last_ran": "Das letzte Mal lief es:",
"group_name": "Gruppenname", "group_name": "Gruppenname",
"group_all_users": "Alle Benutzer", "group_all_users": "Alle Benutzer*innen",
"group_visitors": "Besucher", "group_visitors": "Besucher*innen",
"group_add_member": "Einen Benutzer hinzufügen", "group_add_member": "Eine_n Benutzer*in hinzufügen",
"group_add_permission": "Hinzufügen einer Berechtigung", "group_add_permission": "Hinzufügen einer Berechtigung",
"group_specific_permissions": "Benutzerspezifische Berechtigungen", "group_specific_permissions": "Benutzerspezifische Berechtigungen",
"groups_and_permissions": "Gruppen und Berechtigungen", "groups_and_permissions": "Gruppen und Berechtigungen",
@ -466,7 +466,7 @@
"diagnosis_experimental_disclaimer": "Beachten Sie, dass die Diagnosefunktion noch experimentell und in Bearbeitung ist und möglicherweise nicht vollständig zuverlässig ist.", "diagnosis_experimental_disclaimer": "Beachten Sie, dass die Diagnosefunktion noch experimentell und in Bearbeitung ist und möglicherweise nicht vollständig zuverlässig ist.",
"group_format_name_help": "Sie können alphanumerische Zeichen und Leerzeichen verwenden", "group_format_name_help": "Sie können alphanumerische Zeichen und Leerzeichen verwenden",
"group_new": "Neue Gruppe", "group_new": "Neue Gruppe",
"group_explain_visitors": "Dies ist eine spezielle Gruppe, die anonyme Besucher repräsentiert", "group_explain_visitors": "Dies ist eine spezielle Gruppe, die anonyme Besucher*innen repräsentiert",
"rerun_diagnosis": "Diagnose wiederholen", "rerun_diagnosis": "Diagnose wiederholen",
"app_state_low_quality_explanation": "Diese App kann bereits funktionieren, enthält aber eventuell noch Fehler und/oder ist noch nicht vollständig integriert in YunoHost und/oder befolgt nicht die empfohlene Praxis.", "app_state_low_quality_explanation": "Diese App kann bereits funktionieren, enthält aber eventuell noch Fehler und/oder ist noch nicht vollständig integriert in YunoHost und/oder befolgt nicht die empfohlene Praxis.",
"others": "Anderes", "others": "Anderes",
@ -475,10 +475,15 @@
"all": "Alle", "all": "Alle",
"confirm_service_restart": "Bist du sicher, dass du %s neustarten möchtest?", "confirm_service_restart": "Bist du sicher, dass du %s neustarten möchtest?",
"run_first_diagnosis": "Initiale Diagnose läuft", "run_first_diagnosis": "Initiale Diagnose läuft",
"diagnosis_first_run": "Die Diagnose Funktion wird versuchen, gängige Probleme in verschiedenen Teilen deines Servers zu finden, damit alles reibungslos läuft. Bitte werde nicht panisch, wenn du ein paar Fehlermeldungen siehst nachdem du deinen Server aufgesetzt hast: es soll versuchen dir zu helfen, Probleme zu identifizieren und Tipps für Lösungen zu zeigen. Die Diagnose wird auch automatisch zweimal täglich ausgeführt, falls Fehler gefunden werden, bekommt der Administrator ein E-Mail.", "diagnosis_first_run": "Die Diagnosefunktion versucht, häufige Probleme in den verschiedenen Bereichen Ihres Servers zu identifizieren, um sicherzustellen, dass alles reibungslos läuft. Bitte geraten Sie nicht in Panik, wenn Sie direkt nach dem Einrichten Ihres Servers einen Haufen Fehler sehen: es soll Ihnen genau dabei helfen, Probleme zu identifizieren und Sie zur Behebung dieser Probleme anleiten. Die Diagnose läuft auch automatisch zweimal täglich, und wenn Probleme gefunden werden, wird eine E-Mail an den Administrator geschickt.",
"unmaintained_details": "Diese Anwendung wurde seit einiger Zeit nicht gewartet und der frühere Wart hat die Anwendung aufgegeben oder hat keine Zeit mehr für die Wartung. Du bist herzlich eingeladen dir die Quellen und Unterlagen anzusehen und Hilfe zu leisten", "unmaintained_details": "Diese Anwendung wurde seit einiger Zeit nicht gewartet und der frühere Wart hat die Anwendung aufgegeben oder hat keine Zeit mehr für die Wartung. Du bist herzlich eingeladen dir die Quellen und Unterlagen anzusehen und Hilfe zu leisten",
"group_explain_visitors_needed_for_external_client": "Sei vorsichtig und beachte, dass du manche Anwendungen für externe Besucher freigeben musst, falls du beabsichtigst, diese mit externen Clients aufzurufen. Zum Beispiel trifft das auf Nextcloud zu, wenn du eine Synchronisation auf dem Smartphone oder Desktop PC haben möchtest.", "group_explain_visitors_needed_for_external_client": "Sei vorsichtig und beachte, dass du manche Anwendungen für externe Besucher*innen freigeben musst, falls du beabsichtigst, diese mit externen Clients aufzurufen. Zum Beispiel trifft das auf Nextcloud zu, wenn du eine Synchronisation auf dem Smartphone oder Desktop PC haben möchtest.",
"groups": "Gruppen", "groups": "Gruppen",
"issues": "%s Probleme", "issues": "%s Probleme",
"restart": "Neustart" "restart": "Neustart",
"operation_failed_explanation": "Die Operation ist fehlgeschlagen! Das tut uns leid :( Sie können Sich <a href='https://yunohost.org/help'>hier Hilfe holen</a>. Bitte stellen Sie *die ganzen Logs* der Operation bereit, damit Ihnen besser geholfen werden kann. Dies tun Sie, indem Sie auf den grünen 'mit Yunopaste teilen' Knopf drücken. Wenn Sie die Logs teilen, wird Yunohost automatisch versuchen Ihre privaten Daten wie Domainnamen und IP's zu anonymisieren.",
"diagnosis_explanation": "Die Diagnose Funktion wird versuchen, gängige Probleme in verschiedenen Teilen deines Servers zu finden, damit alles reibungslos läuft. Die Diagnose wird auch automatisch zweimal täglich ausgeführt, falls Fehler gefunden werden, bekommt der Administrator ein E-Mail. Beachte, dass einige tests nicht relevant sind, wenn du einzelne Features (zum Beispiel XMPP) nicht benutzt oder du ein komplexes Setup hast. In diesem Fall und wenn du weisst was du tust ist es in Ordnung die dazugehoerigen Warnungen und Hinweise zu ignorieren.",
"pending_migrations": "Es gibt einige ausstehende Migrationen, die darauf warten, ausgeführt zu werden. Bitte gehen Sie auf <a href='#/tools/migrations'>Werkzeuge > Migrationen</a> um diese auszuführen.",
"tip_about_user_email": "Benutzer*innen werden mit einer verknüpften eMail-Adresse (und XMPP Account) erstellt im Format username@domain.tld. Zusätzliche eMail-Aliasse and eMail-Weiterleitungen können später durch den/die Admin und User*in hinzugefügt werden.",
"log_suboperations": "Unter-Operationen"
} }

View file

@ -28,6 +28,7 @@
"APIConnexionError": "Yunohost encountered an connexion error" "APIConnexionError": "Yunohost encountered an connexion error"
}, },
"all_apps": "All apps", "all_apps": "All apps",
"apply": "Apply",
"api_not_responding": "The YunoHost API is not responding. Maybe 'yunohost-api' is down or got restarted?", "api_not_responding": "The YunoHost API is not responding. Maybe 'yunohost-api' is down or got restarted?",
"api_waiting": "Waiting for the server's response...", "api_waiting": "Waiting for the server's response...",
"app_actions": "Actions", "app_actions": "Actions",
@ -39,13 +40,14 @@
"app_config_panel_label": "Configure this app", "app_config_panel_label": "Configure this app",
"app_config_panel_no_panel": "This application doesn't have any configuration available", "app_config_panel_no_panel": "This application doesn't have any configuration available",
"app_info_access_desc": "Groups / users currently allowed to access this app:", "app_info_access_desc": "Groups / users currently allowed to access this app:",
"app_info_changelabel_desc": "Change app label in the portal.",
"app_info_default_desc": "Redirect domain root to this application ({domain}).", "app_info_default_desc": "Redirect domain root to this application ({domain}).",
"app_info_managelabel_desc": "Manage permissions labels in the portal.",
"app_info_changeurl_desc": "Change the access URL of this application (domain and/or path).", "app_info_changeurl_desc": "Change the access URL of this application (domain and/or path).",
"app_info_change_url_disabled_tooltip": "This feature hasn't been implemented in this app yet", "app_info_change_url_disabled_tooltip": "This feature hasn't been implemented in this app yet",
"app_info_uninstall_desc": "Remove this application.", "app_info_uninstall_desc": "Remove this application.",
"app_install_cancel": "Installation cancelled.", "app_install_cancel": "Installation cancelled.",
"app_install_custom_no_manifest": "No manifest.json file", "app_install_custom_no_manifest": "No manifest.json file",
"app_manage_label_and_tiles": "Manage label and tiles",
"app_make_default": "Make default", "app_make_default": "Make default",
"app_no_actions": "This application doesn't have any actions", "app_no_actions": "This application doesn't have any actions",
"app_not_found": "Unable to find an app matching your criteria.", "app_not_found": "Unable to find an app matching your criteria.",
@ -149,7 +151,7 @@
"error_retrieve_feed": "Could not retrieve feed: %s. You might have a plugin prevent your browser from performing this request (or the website is down).", "error_retrieve_feed": "Could not retrieve feed: %s. You might have a plugin prevent your browser from performing this request (or the website is down).",
"error_select_domain": "You should indicate a domain", "error_select_domain": "You should indicate a domain",
"error_server_unexpected": "Unexpected server error (%s)", "error_server_unexpected": "Unexpected server error (%s)",
"error_connection_interrupted": "The server closed the connection instead of answering it. Has nginx or the yunohost-api been restarted or stoppted for some reason? (Error code/message: %s)", "error_connection_interrupted": "The server closed the connection instead of answering it. Has nginx or the yunohost-api been restarted or stopped for some reason? (Error code/message: %s)",
"everything_good": "Everything good!", "everything_good": "Everything good!",
"experimental": "Experimental", "experimental": "Experimental",
"experimental_warning": "Warning: this feature is experimental and not consider stable, you shouldn't be using it except if you know what you are doing.", "experimental_warning": "Warning: this feature is experimental and not consider stable, you shouldn't be using it except if you know what you are doing.",
@ -296,6 +298,7 @@
"day_validity": " Expired | 1 day | {count} days" "day_validity": " Expired | 1 day | {count} days"
}, },
"logs": "Logs", "logs": "Logs",
"log_suboperations": "Sub-operations",
"logs_operation": "Operations made on system with YunoHost", "logs_operation": "Operations made on system with YunoHost",
"logs_history": "History of command run on system", "logs_history": "History of command run on system",
"logs_package": "Debian packages management history", "logs_package": "Debian packages management history",
@ -312,6 +315,10 @@
"logs_share_with_yunopaste": "Share logs with YunoPaste", "logs_share_with_yunopaste": "Share logs with YunoPaste",
"logs_more": "Display more lines", "logs_more": "Display more lines",
"path_url": "Path", "path_url": "Path",
"pending_migrations": "There are some pending migrations waiting to be ran. Please go to the <a href='#/tools/migrations'>Tools > Migrations</a> view to run them.",
"permission_corresponding_url": "Corresponding URL",
"permission_main": "Main permission",
"permission_show_tile_enabled": "Show the tile in the user portal",
"port": "Port", "port": "Port",
"ports": "Ports", "ports": "Ports",
"postinstall": "Post-installation", "postinstall": "Post-installation",
@ -367,6 +374,7 @@
"system_upgrade_all_applications_btn": "Upgrade all applications", "system_upgrade_all_applications_btn": "Upgrade all applications",
"system_upgrade_all_packages_btn": "Upgrade all packages", "system_upgrade_all_packages_btn": "Upgrade all packages",
"tcp": "TCP", "tcp": "TCP",
"tip_about_user_email": "Users are created with an associated email address (and XMPP account) with the format username@domain.tld. Additional email aliases and email forwards can later be added by the admin and the user.",
"tools": "Tools", "tools": "Tools",
"tools_adminpw": "Change administration password", "tools_adminpw": "Change administration password",
"tools_adminpw_confirm_placeholder": "Confirm the new password", "tools_adminpw_confirm_placeholder": "Confirm the new password",

View file

@ -139,7 +139,7 @@
"hook_data_home": "Données de lutilisateur", "hook_data_home": "Données de lutilisateur",
"hook_data_home_desc": "Les données de lutilisateur situées dans /home/USER", "hook_data_home_desc": "Les données de lutilisateur situées dans /home/USER",
"hook_data_mail": "Courriel", "hook_data_mail": "Courriel",
"hook_data_mail_desc": "Courriels stockés sur le serveur", "hook_data_mail_desc": "Courriels (au format brut) stockés sur le serveur",
"hostname": "Nom d'hôte", "hostname": "Nom d'hôte",
"id": "ID", "id": "ID",
"inactive": "Inactif", "inactive": "Inactif",
@ -318,7 +318,7 @@
"certificate_authority": "Autorité de certification", "certificate_authority": "Autorité de certification",
"validity": "Validité", "validity": "Validité",
"domain_is_eligible_for_ACME": "Ce domaine semble correctement configuré pour installer un certificat Lets Encrypt !", "domain_is_eligible_for_ACME": "Ce domaine semble correctement configuré pour installer un certificat Lets Encrypt !",
"domain_not_eligible_for_ACME": "Ce domaine ne semble pas prêt pour installer un certificat Lets Encrypt. Veuillez vérifier votre configuration DNS et laccessibilité HTTP de votre serveur. Les sections 'enregistrement DNS' et 'Web' dans <a href='#/diagnosis'>la page de diagnostic</a> peuvent vous aider à comprendre ce qui est mal configurée.", "domain_not_eligible_for_ACME": "Ce domaine ne semble pas prêt pour installer un certificat Lets Encrypt. Veuillez vérifier votre configuration DNS et laccessibilité HTTP de votre serveur. Les sections 'enregistrement DNS' et 'Web' dans <a href='#/diagnosis'>la page de diagnostic</a> peuvent vous aider à comprendre ce qui est mal configuré.",
"install_letsencrypt_cert": "Installer un certificat Lets Encrypt", "install_letsencrypt_cert": "Installer un certificat Lets Encrypt",
"manually_renew_letsencrypt_message": "Le certificat sera renouvelé automatiquement durant les 15 derniers jours de sa validité. Vous pouvez le renouveler manuellement si vous le souhaitez (non recommandé).", "manually_renew_letsencrypt_message": "Le certificat sera renouvelé automatiquement durant les 15 derniers jours de sa validité. Vous pouvez le renouveler manuellement si vous le souhaitez (non recommandé).",
"manually_renew_letsencrypt": "Renouveler manuellement maintenant", "manually_renew_letsencrypt": "Renouveler manuellement maintenant",
@ -396,7 +396,7 @@
"confirm_install_app_warning": "Avertissement : cette application peut fonctionner mais nest pas bien intégrée dans YunoHost. Certaines fonctionnalités telles que lauthentification unique et la sauvegarde/restauration pourraient ne pas être disponibles.", "confirm_install_app_warning": "Avertissement : cette application peut fonctionner mais nest pas bien intégrée dans YunoHost. Certaines fonctionnalités telles que lauthentification unique et la sauvegarde/restauration pourraient ne pas être disponibles.",
"confirm_install_app_danger": "AVERTISSEMENT ! Cette application est encore expérimentale et risque de casser votre système ! Vous ne devriez probablement PAS linstaller si vous ne savez pas ce que vous faites. Voulez-vous vraiment prendre ce risque ?", "confirm_install_app_danger": "AVERTISSEMENT ! Cette application est encore expérimentale et risque de casser votre système ! Vous ne devriez probablement PAS linstaller si vous ne savez pas ce que vous faites. Voulez-vous vraiment prendre ce risque ?",
"current_maintainer_title": "Mainteneur actuel de ce paquet", "current_maintainer_title": "Mainteneur actuel de ce paquet",
"error_connection_interrupted": "Le serveur a fermé la connexion au lieu dy répondre. Est-ce que Nginx a été redémarré ou est-ce que l'API YunoHost s'est-elle arrêtée pour diverses raisons ? (code/message derreur : %s)", "error_connection_interrupted": "Le serveur a fermé la connexion au lieu dy répondre. Est-ce que NGINX ou l'API YunoHost aurait été redémarré ou arrêté ? (code/message derreur : %s)",
"experimental_warning": "Attention : cette fonctionnalité est expérimentale et ne doit pas être considérée comme stable, vous ne devriez pas lutiliser à moins que vous ne sachiez ce que vous faites...", "experimental_warning": "Attention : cette fonctionnalité est expérimentale et ne doit pas être considérée comme stable, vous ne devriez pas lutiliser à moins que vous ne sachiez ce que vous faites...",
"good_practices_about_admin_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe administrateur. Le mot de passe doit comporter au moins 8 caractères — bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères (majuscules, minuscules, chiffres et caractères spéciaux).", "good_practices_about_admin_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe administrateur. Le mot de passe doit comporter au moins 8 caractères — bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères (majuscules, minuscules, chiffres et caractères spéciaux).",
"good_practices_about_user_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe pour l'utilisateur. Le mot de passe doit comporter au moins 8 caractères - bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères tels que : majuscules, minuscules, chiffres et caractères spéciaux.", "good_practices_about_user_password": "Vous êtes maintenant sur le point de définir un nouveau mot de passe pour l'utilisateur. Le mot de passe doit comporter au moins 8 caractères - bien quil soit recommandé dutiliser un mot de passe plus long (cest-à-dire une phrase secrète) et/ou dutiliser différents types de caractères tels que : majuscules, minuscules, chiffres et caractères spéciaux.",
@ -422,28 +422,28 @@
"logs_more": "Afficher plus de lignes", "logs_more": "Afficher plus de lignes",
"search_for_apps": "Recherche des applications…", "search_for_apps": "Recherche des applications…",
"unmaintained": "Non maintenue", "unmaintained": "Non maintenue",
"purge_user_data_checkbox": "Purger les données de l'utilisateur %s ? (Cela supprimera le contenu de ses répertoires home et mail.)", "purge_user_data_checkbox": "Purger les données de l'utilisateur %s ? (Cela supprimera le contenu du dossier personnel de %s ainsi que tous les courriers électroniques de %s .)",
"purge_user_data_warning": "La purge des données de lutilisateur nest pas réversible. Assurez-vous de savoir ce que vous faites !", "purge_user_data_warning": "La purge des données de lutilisateur nest pas réversible. Assurez-vous de savoir ce que vous faites !",
"version": "Version", "version": "Version",
"confirm_update_system": "Voulez-vous vraiment mettre à jour tous les paquets système ?", "confirm_update_system": "Voulez-vous vraiment mettre à jour tous les paquets système ?",
"app_state_inprogress_explanation": "Le responsable de cette application a indiqué qu'elle n'est pas encore prête pour une utilisation en production. SOYEZ VIGILANT(E) !", "app_state_inprogress_explanation": "Le mainteneur de cette application précise qu'elle n'est pas encore prête à être utilisée en production. SOYEZ PRUDENTS !",
"app_state_notworking_explanation": "Le responsable de cette application a déclaré celle-ci comme \"non fonctionnelle\". SON INSTALLATION POURRAIT CASSER VOTRE SYSTÈME !", "app_state_notworking_explanation": "Le responsable de cette application a déclaré qu'elle 'ne fonctionne pas'. ATTENTION : SON INSTALLATION POURRAIT CASSER VOTRE SYSTÈME !",
"app_state_high-quality": "Haute qualité", "app_state_high-quality": "bonne qualité",
"app_state_high-quality_explanation": "Cette application est bien intégrée à YunoHost. Elle a été (et est !) revue par l'équipe applicative de YunoHost. On peut s'attendre à ce qu'elle soit sûre et maintenue sur le long terme.", "app_state_high-quality_explanation": "Cette application est bien intégrée à YunoHost. Elle a été (et est !) revue par l'équipe applicative de YunoHost. On peut s'attendre à ce qu'elle soit sûre et maintenue sur le long terme.",
"app_state_working_explanation": "Le responsable de cette application l'a déclarée comme 'fonctionnelle'. Cela signifie qu'elle doit fonctionner (voir son niveau d'intégration) mais n'est pas nécessairement revue, elle peut encore contenir des bugs ou bien n'est pas entièrement intégrée à YunoHost.", "app_state_working_explanation": "Le responsable de cette application l'a déclarée comme 'fonctionnelle'. Cela signifie qu'elle doit fonctionner (voir son niveau d'intégration) mais n'est pas nécessairement revue, elle peut encore contenir des bugs ou bien n'est pas entièrement intégrée à YunoHost.",
"hook_conf_ynh_currenthost": "Domaine principal actuel", "hook_conf_ynh_currenthost": "Domaine principal en vigueur",
"license": "Licence", "license": "Licence",
"maintained": "Maintenue", "maintained": "Maintenue",
"maintained_details": "Cette application a été maintenue par son responsable au cours des derniers mois.", "maintained_details": "Cette application a été maintenue par son responsable au cours des derniers mois.",
"only_highquality_apps": "Uniquement des applications de haute-qualité", "only_highquality_apps": "Seulement les applications de bonne qualité",
"only_decent_quality_apps": "Seulement des applications d'une qualité décente", "only_decent_quality_apps": "Seulement des applications d'une qualité satisfaisante",
"orphaned": "Non maintenue", "orphaned": "Non maintenue",
"orphaned_details": "Cette application n'a pas été maintenue depuis un certain temps. Il peut encore fonctionner, mais ne recevra aucune mise à niveau jusqu'à ce que quelqu'un se porte volontaire pour s'en occuper. N'hésitez pas à contribuer à la faire revivre !", "orphaned_details": "Cette application n'a pas été maintenue depuis un certain temps. Il peut encore fonctionner, mais ne recevra aucune mise à niveau jusqu'à ce que quelqu'un se porte volontaire pour s'en occuper. N'hésitez pas à contribuer à la faire revivre !",
"request_adoption": "en attente de responsable", "request_adoption": "en attente d'adoption",
"request_adoption_details": "Le responsable actuel ne souhaite plus s'occuper de cette application. N'hésitez pas à vous proposer comme nouveau responsable !", "request_adoption_details": "Le responsable actuel ne souhaite plus s'occuper de cette application. N'hésitez pas à vous proposer comme nouveau responsable !",
"request_help": "besoin d'assistance", "request_help": "besoin d'assistance",
"request_help_details": "Le responsable actuel aimerait de l'aide pour la maintenance de cette application. N'hésitez pas à y contribuer !", "request_help_details": "Le mainteneur actuel souhaiterait de l'aide pour la maintenance de cette application. N'hésitez pas à contribuer !",
"advanced": "Avancé", "advanced": "Avancée",
"from_to": "de %s à %s", "from_to": "de %s à %s",
"group_name": "Nom du groupe", "group_name": "Nom du groupe",
"nobody": "Personne", "nobody": "Personne",
@ -477,7 +477,7 @@
"app_state_low_quality_explanation": "Cette application peut être fonctionnelle, mais peut toujours contenir des problèmes, ou n'est pas entièrement intégrée à YunoHost, ou elle ne respecte pas les bonnes pratiques.", "app_state_low_quality_explanation": "Cette application peut être fonctionnelle, mais peut toujours contenir des problèmes, ou n'est pas entièrement intégrée à YunoHost, ou elle ne respecte pas les bonnes pratiques.",
"catalog": "Catalogue", "catalog": "Catalogue",
"others": "Autres", "others": "Autres",
"diagnosis_first_run": "La fonctionnalité de diagnostic va tenter de trouver certains problèmes communs sur différents aspects de votre serveur pour être sûr que tout fonctionne normalement. Merci de ne pas paniquer si vous voyez une multitude d'erreurs après avoir configuré votre serveur : la fonctionnalité est précisément prévue pour les identifier et vous aider à les résoudre. Le diagnostic sera également effectué deux fois par jour et enverra un mail à l'administrateur si des erreurs sont détectées.", "diagnosis_first_run": "La fonctionnalité de diagnostic va tenter de trouver certains problèmes communs sur différents aspects de votre serveur pour être sûr que tout fonctionne normalement. Merci de ne pas paniquer si vous voyez une multitude d'erreurs après avoir configuré votre serveur : la fonctionnalité est précisément prévue pour les identifier et vous aider à les résoudre. Le diagnostic sera également effectué deux fois par jour et enverra un courriel à l'administrateur si des erreurs sont détectées.",
"run_first_diagnosis": "Démarrer le diagnostic initial", "run_first_diagnosis": "Démarrer le diagnostic initial",
"confirm_service_restart": "Êtes-vous certain de vouloir redémarrer %s ?", "confirm_service_restart": "Êtes-vous certain de vouloir redémarrer %s ?",
"groups": "Groupes", "groups": "Groupes",
@ -486,5 +486,8 @@
"group_explain_visitors_needed_for_external_client": "Veillez à ce que certaines applications soient autorisées pour les visiteurs si vous avez l'intention de les utiliser avec des clients externes. Par exemple, c'est le cas pour Nextcloud si vous souhaitez avoir l'intention d'utiliser un client de synchronisation sur votre smartphone ou ordinateur de bureau.", "group_explain_visitors_needed_for_external_client": "Veillez à ce que certaines applications soient autorisées pour les visiteurs si vous avez l'intention de les utiliser avec des clients externes. Par exemple, c'est le cas pour Nextcloud si vous souhaitez avoir l'intention d'utiliser un client de synchronisation sur votre smartphone ou ordinateur de bureau.",
"issues": "%s problèmes", "issues": "%s problèmes",
"operation_failed_explanation": "L'opération a échoué ! Veuillez-nous excuser pour ça :( Vous pouvez essayer de <a href='https://yunohost.org/help'>demander de l'aide</a>. Merci de fournir *le log complet* de l'opération pour les personnes qui vont vous aider. Vous pouvez cliquer sur le bouton vert 'Partager avec Yunopaste'. Quand vous partagez les logs, YunoHost essaie automatiquement d'anonymiser les informations privées comme le nom de domaine et l'adresses IP.", "operation_failed_explanation": "L'opération a échoué ! Veuillez-nous excuser pour ça :( Vous pouvez essayer de <a href='https://yunohost.org/help'>demander de l'aide</a>. Merci de fournir *le log complet* de l'opération pour les personnes qui vont vous aider. Vous pouvez cliquer sur le bouton vert 'Partager avec Yunopaste'. Quand vous partagez les logs, YunoHost essaie automatiquement d'anonymiser les informations privées comme le nom de domaine et l'adresses IP.",
"diagnosis_explanation": "La fonctionnalité de diagnostic va tenter de trouver certains problèmes communs sur différents aspects de votre serveur pour être sûr que tout fonctionne normalement. Le diagnostic sera également effectué deux fois par jour et enverra un mail à l'administrateur si des erreurs sont détectées. À noter que certains tests ne seront pas montrés si vous n'utilisez pas certaines fonctions spécifiques (XMPP, par exemple) ou s'ils échouent à cause d'une configuration trop complexe. Dans ce cas, et si vous savez ce que vous avez modifié, vous pouvez ignorer les problèmes et les avertissements correspondantes." "diagnosis_explanation": "La fonctionnalité de diagnostic va tenter de trouver certains problèmes communs sur différents aspects de votre serveur pour être sûr que tout fonctionne normalement. Le diagnostic sera également effectué deux fois par jour et enverra un courriel à l'administrateur si des erreurs sont détectées. À noter que certains tests ne seront pas montrés si vous n'utilisez pas certaines fonctions spécifiques (XMPP, par exemple) ou s'ils échouent à cause d'une configuration trop complexe. Dans ce cas, et si vous savez ce que vous avez modifié, vous pouvez ignorer les problèmes et les avertissements correspondantes.",
"pending_migrations": "Il y a des migrations en suspens qui attentent d'être exécutées. Veuillez aller dans <a href='#/tools/migrations'>Outils > Migrations</a> pour les exécuter.",
"tip_about_user_email": "Les utilisateurs sont créés avec une adresse e-mail associée (et un compte XMPP) au format username@domain.tld. Des alias d'email et des transferts d'emails supplémentaires peuvent être ajoutés ultérieurement par l'administrateur et l'utilisateur.",
"log_suboperations": "Sous-opérations"
} }

View file

@ -485,5 +485,8 @@
"catalog": "Catalogo", "catalog": "Catalogo",
"app_state_low_quality_explanation": "Questa applicazione può essere funzionale ma potrebbe presentare dei problemi oppure non essere pienamente integrata con YunoHost oppure non rispettare le pratiche consigliate.", "app_state_low_quality_explanation": "Questa applicazione può essere funzionale ma potrebbe presentare dei problemi oppure non essere pienamente integrata con YunoHost oppure non rispettare le pratiche consigliate.",
"app_state_low_quality": "bassa qualità", "app_state_low_quality": "bassa qualità",
"all": "Tutti" "all": "Tutti",
"pending_migrations": "Ci sono alcune migrazioni in sospeso in attesa di essere eseguite. Consulta <a href='#/tools/migrations'>Tools > Migrations</a> per visualizzarle.",
"tip_about_user_email": "Gli utenti sono creati associati ad un indirizzo email (e un account XMPP) del tipo utente@domain.tld. Indirizzi email addizionali e forward possono essere aggiunti successivamente dall'amministratore e dall'utente.",
"log_suboperations": "Sub-operazioni"
} }

View file

@ -375,7 +375,7 @@
"certificate_alert_great": "Perfièch! Sètz a utilizar un certificat Lets Encrypt valid!", "certificate_alert_great": "Perfièch! Sètz a utilizar un certificat Lets Encrypt valid!",
"certificate_old_letsencrypt_app_conflict": "Laplicacion «letsencrypt» es actualament installada e es en conflicte amb aquesta foncionalitat. Mercés de la desinstallar per utilizar la novèla interfàcia de gestion dels certificats.", "certificate_old_letsencrypt_app_conflict": "Laplicacion «letsencrypt» es actualament installada e es en conflicte amb aquesta foncionalitat. Mercés de la desinstallar per utilizar la novèla interfàcia de gestion dels certificats.",
"domain_not_eligible_for_ACME": "Aqueste domeni sembla pas prèst per un certificat Lets Encrypt. Mercés de verificar la configuracion DNS e laccessibilitat del servidor HTTP. Las seccions «enregistrament DNS» e «Web» de <a href='#/diagnosis'>la pagina de diagnostic</a> pòt vos ajudar a comprendre çò ques pas configurat coma cal.", "domain_not_eligible_for_ACME": "Aqueste domeni sembla pas prèst per un certificat Lets Encrypt. Mercés de verificar la configuracion DNS e laccessibilitat del servidor HTTP. Las seccions «enregistrament DNS» e «Web» de <a href='#/diagnosis'>la pagina de diagnostic</a> pòt vos ajudar a comprendre çò ques pas configurat coma cal.",
"manually_renew_letsencrypt_message": "Lo certificat serà renovat automaticament pendent los 15 darrièrs jorns de validitat. Podètz lo renovar manualament se volètz. (Pas recomandat).", "manually_renew_letsencrypt_message": "Lo certificat serà renovat automaticament pendent los darrièrs 15 jorns de validitat. Podètz lo renovar manualament se volètz. (Pas recomandat).",
"meltdown": "Sètz vulnerable a la falha de seguretat critica <a target=\"_blank\" href=\"https://meltdownattack.com/\">meltdown</a>. Per dire de resòlvre aqueste problèma, vos cal <a href=\"#/update\">actualizar vòstre sistèma</a> puèi <a href=\"#/tools/reboot\"> lo tornar aviar</a> per cargar lo nòu nuclèu linux.", "meltdown": "Sètz vulnerable a la falha de seguretat critica <a target=\"_blank\" href=\"https://meltdownattack.com/\">meltdown</a>. Per dire de resòlvre aqueste problèma, vos cal <a href=\"#/update\">actualizar vòstre sistèma</a> puèi <a href=\"#/tools/reboot\"> lo tornar aviar</a> per cargar lo nòu nuclèu linux.",
"revert_to_selfsigned_cert_message": "So volètz vertadièrament, podètz tornar installar lo certificat auto-signat. (Pas recomandat)", "revert_to_selfsigned_cert_message": "So volètz vertadièrament, podètz tornar installar lo certificat auto-signat. (Pas recomandat)",
"started_at": "Aviat a:", "started_at": "Aviat a:",
@ -443,7 +443,7 @@
"last_ran": "Darrièra execucion :", "last_ran": "Darrièra execucion :",
"permissions": "Permissions", "permissions": "Permissions",
"details": "Detalhs", "details": "Detalhs",
"diagnosis_experimental_disclaimer": "Remembratz-vos que lopcion de diagnostic es encara experimentala e se melhorar, e pòt pas èsser fisabla.", "diagnosis_experimental_disclaimer": "Remembratz-vos que lopcion de diagnostic es encara experimentala e a se melhorar, e pòt pas èsser fisabla.",
"errors": "%s errors", "errors": "%s errors",
"everything_good": "Tot es bon !", "everything_good": "Tot es bon !",
"group": "Grop", "group": "Grop",
@ -475,5 +475,13 @@
"confirm_service_restart": "Volètz vertadièrament reaviar %s?", "confirm_service_restart": "Volètz vertadièrament reaviar %s?",
"restart": "Reaviar", "restart": "Reaviar",
"groups": "Grops", "groups": "Grops",
"issues": "%s problèmas" "issues": "%s problèmas",
"unmaintained_details": "Fa un moment quaquesta aplicacion es pas mai mantenguda e la persona que la manteniá es partida o a pas de temps per la mantenir. Esitetz pas a consultar lo repertòri de las aplicacions per aportar vòstra ajuda",
"tip_about_user_email": "Los utilizaires son creats amb una adreça e-mails ligada (e un compte XMPP) al format utilizaire@domeni.tld. Las adreças de transferiments suplementàrias pòdon èsser ajustadas ulteriorament per ladministrator e lutilizaire.",
"operation_failed_explanation": "Aquesta operacion a pas capitat! O planhèm :( Podètz ensajar de <a href='https://yunohost.org/help'>demandar dajuda</a>. Se vos plai donar lo *jornal complèt* de loperacion quensajan de vos ajudar. Podètz clicar sul boton verd «Partejar amb Yunopaste». En partejant lo jornal daudit, YunoHost provarà automaticament danonimizar las donadas coma los noms de domeni e adreças IP.",
"group_explain_visitors_needed_for_external_client": "Agachatz que certanas aplicacions sián autorizadas pels visitaires se volètz las utilizar amb de clients extèrns. Per exemple, es lo cas per Nextcloud savètz idèa demplegar un client de sincronizacion pel vòstre smartphone o ordenador de burèu.",
"diagnosis_explanation": "La foncionalitat de diagnostic provarà trobar problèmas comuns sus diferents aspèctes de vòstre servidor per sassegurar que tot fonciona normalament. Lo diagnostic serà tanben realizat dos còps per jorn e enviarà un corrièl a ladministrator se derrors son detectadas. De notar que dunes ensages seràn pas mostrats sutilizatz pas certanas foncions especificas (XMPP, per exemple) o se fracassan a causa duna configuracion tròp complèxa. Dins aqueste cas, e se sabètz çò quavètz modificat, podètz ignorar los problèmas e avertiments correspondents.",
"pending_migrations": "I a unas migracions en espèra dexecucion. Anatz a <a href='#/tools/migrations'>Aisinas > Migracions</a> per las lançar.",
"log_suboperations": "Jos-operacions",
"diagnosis_first_run": "La foncionalitat de diagnostic ensajarà didentificar los problèmas abituals de diferents aspèctes del servidor per dire dassegurar que tot foncione de la melhora manièra possibla. Ajatz pas paur se vesètz mantunas error aprèp configurar lo servidor: es precisament fach per ajudar a identificar los problèmas e ofrir una guida per los reglar. Lo diagnostic sexecutarà tanben dos còps per jorn e enviarà un corrièl a ladministrator se tròba unas error."
} }

View file

@ -12,5 +12,36 @@
"cancel": "取消", "cancel": "取消",
"ok": "好", "ok": "好",
"password": "密码", "password": "密码",
"logged_in": "登录" "logged_in": "登录",
"configuration": "配置",
"close": "关闭",
"check": "检查",
"catalog": "目录",
"both": "同时",
"begin": "开始",
"backups_no": "无备份",
"backup_optional_password": "可选密码",
"backup_optional_encryption": "可选加密",
"backup_new": "新备份",
"backup_create": "创建一个备份",
"backup_content": "备份内容",
"backup_action": "备份",
"backup": "备份",
"applications": "应用程序",
"app_state_working": "工作",
"app_state_high-quality": "高质量",
"app_state_notworking": "不工作",
"app_make_default": "设为默认",
"app_install_custom_no_manifest": "manifest.json文件不存在",
"app_install_cancel": "安装已取消。",
"app_info_uninstall_desc": "删除此应用程序。",
"app_info_default_desc": "重定向域根到这个应用(%s。",
"app_info_changelabel_desc": "在门户中修改应用标签。",
"unignore": "取消忽略",
"last_ran": "最近一次运行:",
"app_info_change_url_disabled_tooltip": "此应用尚未实现该功能",
"archive_empty": "空存档",
"backup_archive_delete": "删除这个存档",
"app_state_low_quality": "低质量",
"app_state_inprogress": "暂不工作"
} }

49
debian/changelog vendored
View file

@ -1,3 +1,52 @@
yunohost-admin (4.0.4) stable; urgency=low
- [fix] migrations link in french translation (#309)
- [fix] Stupid typo breaking yunopaste for service logs (7e03213)
- [fix] In log views, sometimes 'error' is empty despite success:false ... so rely on the value of success instead (7894c84)
Thanks to all contributors <3 ! (opi)
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 04 Sep 2020 14:54:01 +0200
yunohost-admin (4.0.3) stable; urgency=low
- Bump version number for stable release
-- Alexandre Aubin <alex.aubin@mailoo.org> Wed, 29 Jul 2020 17:00:00 +0200
yunohost-admin (4.0.2~beta) testing; urgency=low
- Bump version number for beta release
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 19 Jun 2020 15:41:15 +0200
yunohost-admin (4.0.1~alpha) testing; urgency=low
- [mod] Update deb dependencies and build workflow (fd9949d, 01e452a, f6b8202, 8d35eac, 1a9b16c)
- [fix] Update npm dependencies and build workflow (#304)
Thanks to all contributors <3 ! (Arthur Lutz, Kay0u)
-- Alexandre Aubin <alex.aubin@mailoo.org> Fri, 05 Jun 2020 17:21:38 +0200
yunohost-admin (3.8.3.5) stable; urgency=low
- [fix] Add a hack to have some sort of cache management as well for .ms files, to avoid stupid issue where people need to force the browser cache refresh after upgrades (7bb8a90)
- [i18n] Translations updated for Catalan, French, German, Italian
Thanks to all contributors <3 ! (Jibec, L. Noferini, ppr, V. Rubiolo, xaloc33, Yasss Gurl)
-- Alexandre Aubin <alex.aubin@mailoo.org> Mon, 27 Jul 2020 17:36:43 +0200
yunohost-admin (3.8.3.4) stable; urgency=low
- [enh] Add a tip about pending migrations on update view (7bf9669)
- [i18n] Translations updated for Occitan
Thanks to all contributors <3 ! (Quentí)
-- Alexandre Aubin <alex.aubin@mailoo.org> Sat, 06 Jun 2020 02:23:20 +0200
yunohost-admin (3.8.3.3) stable; urgency=low yunohost-admin (3.8.3.3) stable; urgency=low
- [i18n] Translations updated for Arabic, Italian - [i18n] Translations updated for Arabic, Italian

8
debian/control vendored
View file

@ -2,17 +2,15 @@ Source: yunohost-admin
Section: utils Section: utils
Priority: extra Priority: extra
Maintainer: YunoHost Contributors <contrib@yunohost.org> Maintainer: YunoHost Contributors <contrib@yunohost.org>
Build-Depends: debhelper (>=9) Build-Depends: debhelper (>=12)
, nodejs (>=4.4.0), git , nodejs (>=10.15.2), npm (>=5.8.0), git
Standards-Version: 3.9.6 Standards-Version: 3.9.6
Homepage: https://yunohost.org/ Homepage: https://yunohost.org/
Package: yunohost-admin Package: yunohost-admin
Architecture: all Architecture: all
Conflicts: yunohost-apps-admin
Replaces: yunohost-apps-admin
Depends: ${misc:Depends} Depends: ${misc:Depends}
, yunohost (>= 3.8) , yunohost (>= 4.0.0~alpha)
Description: web administration interface for yunohost Description: web administration interface for yunohost
YunoHost aims to make self-hosting accessible to everyone. It configures YunoHost aims to make self-hosting accessible to everyone. It configures
an email, Web and IM server alongside a LDAP base. It also provides an email, Web and IM server alongside a LDAP base. It also provides

2
debian/rules vendored
View file

@ -15,7 +15,7 @@ TMPDIR = $$(pwd)/debian/yunohost-admin
dh $@ dh $@
override_dh_auto_build: override_dh_auto_build:
# Run npm/bower/gulp # Run npm install and build
cd app ; npm --progress false --loglevel warn --color false install cd app ; npm --progress false --loglevel warn --color false install
cd app ; npm run build cd app ; npm run build

View file

@ -1,17 +0,0 @@
{
"name": "yunohost-admin",
"description": "YunoHost Admin web interface",
"license": "AGPL-3.0",
"private": true,
"dependencies": {
"bootstrap": "3.3.6",
"fork-awesome": "1.1.7",
"handlebars-helper-intl": "1.1.2",
"handlebars": "4.0.11",
"sammy": "0.7.6",
"js-cookie": "2.1.0",
"isotope-layout": "3.0.6",
"source-sans-pro": "git://github.com/adobe-fonts/source-sans-pro.git#2.020R-ro/1.075R-it",
"source-code-pro": "git://github.com/adobe-fonts/source-code-pro.git#2.010R-ro/1.030R-it"
}
}

View file

@ -3,7 +3,7 @@
/* /*
* Bootstrap * Bootstrap
*/ */
@import "../bower_components/bootstrap/less/bootstrap.less"; @import "../node_modules/bootstrap/less/bootstrap.less";
// Bootstrap variables override // Bootstrap variables override
@font-family-sans-serif: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif; @font-family-sans-serif: "Source Sans Pro", "Helvetica Neue", Helvetica, Arial, sans-serif;
@ -25,7 +25,7 @@
/* /*
* FontAwesome * FontAwesome
*/ */
@import "../bower_components/fork-awesome/less/fork-awesome.less"; @import "../node_modules/fork-awesome/less/fork-awesome.less";
// Fixes // Fixes

View file

@ -6,6 +6,7 @@ var concat = require('gulp-concat'),
uglify = require('gulp-uglify'), uglify = require('gulp-uglify'),
csslint = require('gulp-csslint'), csslint = require('gulp-csslint'),
jshint = require('gulp-jshint'), jshint = require('gulp-jshint'),
mustache = require('gulp-mustache'),
less = require('gulp-less'), less = require('gulp-less'),
autoprefixer = require('gulp-autoprefixer'), autoprefixer = require('gulp-autoprefixer'),
cssmin = require('gulp-cssmin'), cssmin = require('gulp-cssmin'),
@ -19,35 +20,18 @@ var concat = require('gulp-concat'),
isDev = (util.env.dev) ? true : false; isDev = (util.env.dev) ? true : false;
isProduction = !isDev; isProduction = !isDev;
// Global build task
gulp.task('build', [
'css',
'fonts',
'js',
'img',
]);
// Watch task
gulp.task('watch', function(){
gulp.watch('js/**/*.js', ['js']);
gulp.watch('css/*.less', ['css']);
});
// JS task // JS task
gulp.task('js', function() { gulp.task('js', function() {
return gulp.src([ return gulp.src([
'bower_components/jquery/dist/jquery.js', 'node_modules/jquery/dist/jquery.js',
'bower_components/js-cookie/src/js.cookie.js', 'node_modules/handlebars/dist/handlebars.js',
'bower_components/handlebars/handlebars.js', 'node_modules/handlebars-intl/dist/handlebars-intl-with-locales.js',
'bower_components/handlebars-helper-intl/dist/handlebars-intl-with-locales.js', 'node_modules/sammy/lib/sammy.js',
'bower_components/sammy/lib/sammy.js', 'node_modules/sammy/lib/plugins/sammy.handlebars.js',
'bower_components/sammy/lib/plugins/sammy.handlebars.js', 'node_modules/sammy/lib/plugins/sammy.json.js',
'bower_components/sammy/lib/plugins/sammy.json.js', 'node_modules/sammy/lib/plugins/sammy.storage.js',
'bower_components/sammy/lib/plugins/sammy.storage.js', 'node_modules/bootstrap/dist/js/bootstrap.js',
'bower_components/bootstrap/dist/js/bootstrap.js', 'node_modules/isotope-layout/dist/isotope.pkgd.js',
'bower_components/isotope-layout/dist/isotope.pkgd.js',
'js/yunohost/y18n.js', 'js/yunohost/y18n.js',
'js/yunohost/main.js', 'js/yunohost/main.js',
'js/yunohost/helpers.js', 'js/yunohost/helpers.js',
@ -63,25 +47,26 @@ gulp.task('js', function() {
// JS Lint task // JS Lint task
gulp.task('js-lint', function() { gulp.task('js-lint', function() {
return gulp.src('js/*.js') return gulp.src('js/**/*.js')
.pipe(jshint()) .pipe(jshint())
.pipe(jshint.reporter('default')); .pipe(jshint.reporter('default'))
.pipe(jshint.reporter('fail'))
}); });
// Fonts // Fonts
gulp.task('fonts', function() { gulp.task('fonts', function() {
return gulp.src([ return gulp.src([
'bower_components/fork-awesome/fonts/*', 'node_modules/fork-awesome/fonts/*',
'bower_components/source-code-pro/EOT/*.eot', 'node_modules/source-code-pro/EOT/*.eot',
'bower_components/source-code-pro/OTF/*.otf', 'node_modules/source-code-pro/OTF/*.otf',
'bower_components/source-code-pro/TTF/*.ttf', 'node_modules/source-code-pro/TTF/*.ttf',
'bower_components/source-code-pro/WOFF/OTF/*.woff', 'node_modules/source-code-pro/WOFF/OTF/*.woff',
'bower_components/source-code-pro/WOFF2/TTF/*.woff2', 'node_modules/source-code-pro/WOFF2/TTF/*.woff2',
'bower_components/source-sans-pro/EOT/*.eot', 'node_modules/source-sans-pro/EOT/*.eot',
'bower_components/source-sans-pro/OTF/*.otf', 'node_modules/source-sans-pro/OTF/*.otf',
'bower_components/source-sans-pro/TTF/*.ttf', 'node_modules/source-sans-pro/TTF/*.ttf',
'bower_components/source-sans-pro/WOFF/OTF/*.woff', 'node_modules/source-sans-pro/WOFF/OTF/*.woff',
'bower_components/source-sans-pro/WOFF2/TTF/*.woff2', 'node_modules/source-sans-pro/WOFF2/TTF/*.woff2',
]) ])
.pipe(gulp.dest('./dist/fonts')) .pipe(gulp.dest('./dist/fonts'))
}); });
@ -105,8 +90,7 @@ gulp.task('css-lint', function() {
.pipe(less()) .pipe(less())
.pipe(autoprefixer()) .pipe(autoprefixer())
.pipe(csslint()) .pipe(csslint())
.pipe(csslint.reporter('compact')) .pipe(csslint.formatter())
.pipe(gulp.dest('./css/'))
}); });
@ -116,3 +100,23 @@ gulp.task('img', function () {
.pipe(gulpif(isProduction, imagemin())) .pipe(gulpif(isProduction, imagemin()))
.pipe(gulp.dest('./dist/img')) .pipe(gulp.dest('./dist/img'))
}); });
// Views task
gulp.task('views', function () {
return gulp.src('views/**/*.ms')
.pipe(gulp.dest("./dist/views"));
});
// Global build task
gulp.task('build', gulp.series('css', 'fonts', 'js', 'img', 'views'));
// Watch task
gulp.task('watch', function() {
gulp.watch('js/**/*.js', gulp.series('js'));
gulp.watch('css/*.less', gulp.series('css'));
gulp.watch('views/**/*.ms', gulp.series('views'));
});
gulp.task('lint', gulp.series('css-lint', 'js-lint'));
gulp.task('default', gulp.series('build', 'watch'));

View file

@ -12,6 +12,11 @@
app.get('#/apps', function (c) { app.get('#/apps', function (c) {
c.api('GET', '/apps?full', {}, function(data) { c.api('GET', '/apps?full', {}, function(data) {
var apps = data['apps']; var apps = data['apps'];
for (var a in apps)
{
var app = apps[a]
app['label'] = app['permissions'][app['id'] + ".main"]['label']
}
c.arraySortById(apps); c.arraySortById(apps);
c.view('app/app_list', {apps: apps}); c.view('app/app_list', {apps: apps});
}); });
@ -206,7 +211,7 @@
// Check text search // Check text search
var input = jQuery("#filter-app-cards").val().toLowerCase(); var input = jQuery("#filter-app-cards").val().toLowerCase();
if (jQuery(this).find('.app-title').text().toLowerCase().indexOf(input) <= -1) return false; if (jQuery(this).find('.app-title, .app-card-desc').text().toLowerCase().indexOf(input) <= -1) return false;
// Check subtags // Check subtags
var subtag = $(".subtag-selector button.active").data("subtag"); var subtag = $(".subtag-selector button.active").data("subtag");
@ -262,10 +267,9 @@
// Get app information // Get app information
app.get('#/apps/:app', function (c) { app.get('#/apps/:app', function (c) {
c.api('GET', '/apps/'+c.params['app']+'?full', {}, function(data) { c.api('GET', '/apps/'+c.params['app']+'?full', {}, function(data) {
c.api('GET', '/users/permissions', {}, function(data_permissions) { data.label = data.permissions[c.params['app']+".main"]['label']
// Permissions data.permissions = data.permissions[c.params['app']+".main"]["allowed"];
data.permissions = data_permissions.permissions[c.params['app']+".main"]["allowed"];
// Multilingual description // Multilingual description
data.description = (typeof data.manifest.description[y18n.locale] !== 'undefined') ? data.description = (typeof data.manifest.description[y18n.locale] !== 'undefined') ?
@ -305,7 +309,6 @@
}); });
}); });
}); });
});
// //
// App actions // App actions
@ -677,12 +680,48 @@
}); });
// A small utility to convert a string to title case
// e.g. "hAvE a NicE dAy" --> "Have A Nice Day"
// Savagely stolen from https://stackoverflow.com/a/196991
function toFriendlyName(str) {
return str.split('.')[1].replace(/_/g, " ").replace(
/\w\S*/g,
function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
}
);
}
// Get app change label page // Get app change label page
app.get('#/apps/:app/changelabel', function (c) { app.get('#/apps/:app/changelabel', function (c) {
c.api('GET', '/apps/'+c.params['app']+'?full', {}, function(app_data) { c.api('GET', '/apps/'+c.params['app']+'?full', {}, function(app_data) {
var permissions_dict = app_data.permissions;
var permissions = [
permissions_dict[c.params['app'] + '.main']
];
permissions[0].name = c.params['app'] + '.main';
permissions[0].title = y18n.t('permission_main');
permissions[0].tile_available = permissions[0].url != null && ! permissions[0].url.startsWith('re:');
var i = 1;
for (var permission in permissions_dict) {
if (! permission.endsWith('.main')) {
permissions[i] = permissions_dict[permission];
permissions[i].name = permission;
permissions[i].label = permissions[i].sublabel;
permissions[i].title = toFriendlyName(permission);
permissions[i].tile_available = permissions_dict[permission].url != null && ! permissions_dict[permission].url.startsWith('re:');
}
i++;
}
data = { data = {
id: c.params['app'], 'id': c.params['app'],
label: app_data.settings.label, 'label': permissions[0].label,
'permissions': permissions,
'show_tile': function(permission_name) {
return permissions_dict[permission_name].show_tile;
}
}; };
c.view('app/app_changelabel', data); c.view('app/app_changelabel', data);
}); });
@ -690,10 +729,19 @@
// Change app label // Change app label
app.post('#/apps/:app/changelabel', function (c) { app.post('#/apps/:app/changelabel', function (c) {
params = {'new_label': c.params['label']};
c.api('PUT', '/apps/' + c.params['app'] + '/label', params, function(data) { $.each($(".permission-row", c.target), function() {
c.redirect_to('#/apps/'+ c.params['app']); var perm = $(this).data('permission');
if ('show_tile_' + perm in c.params) {
show_tile = "True";
} else {
show_tile = "False";
}
new_label = c.params["label_" + perm]
c.api('PUT', '/users/permissions/' + perm, {show_tile: show_tile, label: new_label}, function(data) {});
}); });
c.redirect_to('#/apps/'+ c.params['app']);
}); });
// Get app change URL page // Get app change URL page

View file

@ -102,19 +102,21 @@
data.locale = y18n.locale; data.locale = y18n.locale;
c.view('backup/backup_info', data, function() { c.view('backup/backup_info', data, function() {
// Configure buttons "select all" and "select none"
// Remove active style from buttons
$(".select_all-none input").click(function(){ $(this).toggleClass("active"); });
// Select all checkbox in this panel // Select all checkbox in this panel
$(".select_all").click(function(){ $('button[data-action="select_all"]').on('click', function() {
$(this).parents(".panel").children(".list-group").find("input").prop("checked", true); $(this).parents(".panel").children(".list-group").find("input").prop("checked", true);
}); });
// Deselect all checkbox in this panel // Deselect all checkbox in this panel
$(".select_none").click(function(){ $('button[data-action="select_none"]').on('click', function() {
$(this).parents(".panel").children(".list-group").find("input").prop("checked", false); $(this).parents(".panel").children(".list-group").find("input").prop("checked", false);
}); });
$('button[data-action="download"]').on('click', function() {
var archive = $(this).data('archive');
window.open('https://' + store.get('url') + '/backup/download/'+archive, '_blank');
});
// Delete button // Delete button
$('button[data-action="delete"]').on('click', function() { $('button[data-action="delete"]').on('click', function() {
var storage = $(this).data('storage'); var storage = $(this).data('storage');

View file

@ -8,7 +8,7 @@
// ********* // *********
app.get('#/diagnosis', function (c) { app.get('#/diagnosis', function (c) {
c.api('POST', '/diagnosis/run?except-if-never-ran-yet', {}, function() { c.api('POST', '/diagnosis/run?except_if_never_ran_yet', {}, function() {
updateDiagnosisView(); updateDiagnosisView();
}); });
}); });

View file

@ -108,7 +108,7 @@
url: 'https://paste.yunohost.org/documents', url: 'https://paste.yunohost.org/documents',
data: $("#logs").text(), data: $("#logs").text(),
}) })
.success(function(data, textStatus, jqXHR) { .done(function(data, textStatus, jqXHR) {
window.open('https://paste.yunohost.org/' + data.key, '_blank'); window.open('https://paste.yunohost.org/' + data.key, '_blank');
}) })
.fail(function() { .fail(function() {

View file

@ -50,6 +50,8 @@
// System update & upgrade // System update & upgrade
app.get('#/update', function (c) { app.get('#/update', function (c) {
c.api('PUT', '/update', {}, function(data) { c.api('PUT', '/update', {}, function(data) {
c.api('GET', '/migrations?pending', {}, function(pending_migrations) {
data.pending_migrations = pending_migrations.migrations;
c.view('tools/tools_update', data, function() { c.view('tools/tools_update', data, function() {
// Configure buttons behaviors // Configure buttons behaviors
$("button[data-upgrade]").on("click", function() { $("button[data-upgrade]").on("click", function() {
@ -85,41 +87,24 @@
}); });
}); });
}); });
});
// Display journals list // Display journals list
app.get('#/tools/logs', function (c) { app.get('#/tools/logs', function (c) {
c.api('GET', "/logs?limit=25&with_details", {}, function(categories) { c.api('GET', "/logs?limit=40&with_details", {}, function(operations) {
data = []; operations = operations["operation"];
category_icons = {
'operation': 'wrench',
'history': 'history',
'package': 'puzzle-piece',
'system': 'cogs',
'access': 'ban',
'service': 'cog',
'app': 'cubes'
}
success_icons = { success_icons = {
true: 'check text-success', true: 'check text-success',
false: 'close text-danger', false: 'close text-danger',
'?': 'question text-warning' '?': 'question text-warning'
} }
for (var category in categories) { for (var log in operations)
for (var log in categories[category])
{ {
categories[category][log].success_icon = success_icons[categories[category][log].success] operations[log].success_icon = success_icons[operations[log].success]
}
if (categories.hasOwnProperty(category)) {
data.push({
key:category,
icon:(category in category_icons)?category_icons[category]:'info-circle',
value:categories[category]
});
}
} }
c.view('tools/tools_logs', { c.view('tools/tools_logs', {
"data": data, "operations": operations,
"locale": y18n.locale "locale": y18n.locale
}); });
}); });
@ -128,16 +113,10 @@
// One journal // One journal
app.get(/\#\/tools\/logs\/(.*)(\?number=(\d+))?/, function (c) { app.get(/\#\/tools\/logs\/(.*)(\?number=(\d+))?/, function (c) {
var params = "?path=" + c.params["splat"][0]; var params = "?path=" + c.params["splat"][0];
var number = (c.params["number"])?c.params["number"]:50; var number = (c.params["number"])?c.params["number"]:25;
params += "&filter_irrelevant&number=" + number; params += "&filter_irrelevant&with_suboperations&number=" + number;
c.api('GET', "/logs/display" + params, {}, function(log) { c.api('GET', "/logs/display" + params, {}, function(log) {
if ('metadata' in log) {
if (!'env' in log.metadata && 'args' in log.metadata) {
log.metadata.env = log.metadata.args
}
}
c.view('tools/tools_log', { c.view('tools/tools_log', {
"log": log, "log": log,
"next_number": log.logs.length == number ? number * 10:false, "next_number": log.logs.length == number ? number * 10:false,

View file

@ -5,18 +5,6 @@
var PASSWORD_MIN_LENGTH = 4; var PASSWORD_MIN_LENGTH = 4;
// A small utility to convert a string to title case
// e.g. "hAvE a NicE dAy" --> "Have A Nice Day"
// Savagely stolen from https://stackoverflow.com/a/196991
function toTitleCase(str) {
return str.replace(
/\w\S*/g,
function(txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
}
);
}
/** /**
* Groups and permissions * Groups and permissions
* *
@ -119,7 +107,7 @@
app.get('#/groups', function (c) { app.get('#/groups', function (c) {
c.api('GET', '/users/groups?full&include_primary_groups', {}, function(data_groups) { c.api('GET', '/users/groups?full&include_primary_groups', {}, function(data_groups) {
c.api('GET', '/users', {}, function(data_users) { c.api('GET', '/users', {}, function(data_users) {
c.api('GET', '/users/permissions?short', {}, function(data_permissions) { c.api('GET', '/users/permissions?full', {}, function(data_permissions) {
//var perms = data_permissions.permissions; //var perms = data_permissions.permissions;
var specific_perms = {}; var specific_perms = {};
var all_perms = data_permissions.permissions; var all_perms = data_permissions.permissions;
@ -128,10 +116,11 @@
// Enrich groups data with primary group indicator and inversed items list // Enrich groups data with primary group indicator and inversed items list
for (var group in data_groups.groups) { for (var group in data_groups.groups) {
data_groups.groups[group].primary = users.indexOf(group) !== -1; data_groups.groups[group].primary = users.indexOf(group) !== -1;
data_groups.groups[group].permissionsInv = all_perms.filter(function(item) { data_groups.groups[group].permissionsInv = Object.keys(all_perms).filter(function(item) {
return data_groups.groups[group].permissions.indexOf(item) === -1; return data_groups.groups[group].permissions.indexOf(item) === -1;
}).filter(function(item) { }).filter(function(item) {
return group != "visitors" || (item != "mail.main" && item != "xmpp.main"); // Remove 'email' and 'xmpp' in visitors's permission choice list // Remove 'email', 'xmpp' and protected permission in visitors's permission choice list
return group != "visitors" || (item != "mail.main" && item != "xmpp.main" && ! all_perms[item].protected == true);
}); });
data_groups.groups[group].membersInv = users.filter(function(item) { data_groups.groups[group].membersInv = users.filter(function(item) {
return data_groups.groups[group].members.indexOf(item) === -1; return data_groups.groups[group].members.indexOf(item) === -1;
@ -147,23 +136,18 @@
data = { data = {
'groups':data_groups.groups, 'groups':data_groups.groups,
'displayPermission': function (text) { 'displayPermission': function (text) {
// Display a permission correctly for a human return all_perms[text].label;
text = text.replace('.main', '');
if (text.indexOf('.') > -1)
text = text.replace('.', ' (') + ')';
if (text == "mail")
text = "E-mail";
else if (text == "xmpp")
text = "XMPP";
else
text = toTitleCase(text);
return text;
}, },
'displayUser': function (text) { 'displayUser': function (text) {
return text; return text;
}, },
'is_protected': function (item, type, group) {
if (type == 'permission' && group == 'visitors') {
return all_perms[item].protected;
} else {
return false
}
},
}; };
updateView(data); updateView(data);
}); });
@ -203,11 +187,9 @@
data.password_min_length = PASSWORD_MIN_LENGTH; data.password_min_length = PASSWORD_MIN_LENGTH;
c.view('user/user_create', data, function(){ c.view('user/user_create', data, function(){
var usernameField = $('#username'); var usernameField = $('#username');
usernameField.on('blur', function(){ usernameField.on('input', function(){
var emailField = $('#email'); var emailLeft = $('#email-left');
if (emailField.val() == '') { emailLeft.html(usernameField.val());
emailField.val(usernameField.val());
}
}); });
}); });
}); });
@ -215,27 +197,21 @@
// Create user (POST) // Create user (POST)
app.post('#/users/create', function (c) { app.post('#/users/create', function (c) {
if (c.params['password'] == c.params['confirmation']) { if (c.params['password'] != c.params['confirmation']) {
c.flash('fail', y18n.t('passwords_dont_match'));
return;
}
if (c.params['password'].length < PASSWORD_MIN_LENGTH) { if (c.params['password'].length < PASSWORD_MIN_LENGTH) {
c.flash('fail', y18n.t('passwords_too_short')); c.flash('fail', y18n.t('passwords_too_short'));
return;
} }
else {
// Force unit or disable quota
if (c.params['mailbox_quota']) {
c.params['mailbox_quota'] += "M";
}
else {c.params['mailbox_quota'] = 0;}
// Compute email field c.params['domain'] = c.params['domain'].slice(1);
c.params['mail'] = c.params['email'] + c.params['domain']; c.params['username'] = c.params['username'].trim();
c.api('POST', '/users', c.params.toHash(), function(data) { c.api('POST', '/users', c.params.toHash(), function(data) {
c.redirect_to('#/users'); c.redirect_to('#/users');
}); });
}
} else {
c.flash('fail', y18n.t('passwords_dont_match'));
}
}); });
// Show user information // Show user information

View file

@ -1,4 +1,10 @@
(function() { (function() {
// This is to fetch the "RANDOMID" after script.min.js?version= in
// index.html
// We later use the same ID as a hacky cache mechanism for the .ms files
var ynh_assets_version = document.getElementsByTagName('script')[0].src.split("=")[1];
// Get application context // Get application context
var app = Sammy.apps['#main']; var app = Sammy.apps['#main'];
var store = app.store; var store = app.store;
@ -118,13 +124,13 @@
$.ajax({ $.ajax({
dataType: "json", dataType: "json",
url: 'https://'+ baseUrl +'/installed', url: 'https://'+ baseUrl +'/installed',
timeout: 3000 timeout: 3000,
}) success: function(data) {
.success(function(data) {
callback(data.installed); callback(data.installed);
}) },
.fail(function() { fail: function() {
callback(undefined); callback(undefined);
}
}); });
}, },
@ -319,7 +325,7 @@
$('#modal').modal('hide'); $('#modal').modal('hide');
// Render content // Render content
var rendered = this.render('views/'+ view +'.ms', data); var rendered = this.render('dist/views/' + view + '.ms?version=' + ynh_assets_version, data);
// Update content helper // Update content helper
var leSwap = function() { var leSwap = function() {

7792
src/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,6 @@
"url": "https://github.com/YunoHost/yunohost-admin" "url": "https://github.com/YunoHost/yunohost-admin"
}, },
"scripts": { "scripts": {
"postinstall": "bower install",
"build": "gulp build", "build": "gulp build",
"build-dev": "gulp build --dev", "build-dev": "gulp build --dev",
"watch": "gulp watch", "watch": "gulp watch",
@ -19,18 +18,30 @@
}, },
"homepage": "https://github.com/YunoHost/yunohost-admin", "homepage": "https://github.com/YunoHost/yunohost-admin",
"devDependencies": { "devDependencies": {
"bower": "^1.7.7", "gulp": "^4.0.2",
"gulp": "^3.9.0", "gulp-autoprefixer": "^7.0.1",
"gulp-autoprefixer": "^2.3.1", "gulp-concat": "^2.6.1",
"gulp-concat": "^2.6.0", "gulp-csslint": "^1.0.1",
"gulp-csslint": "^0.2.0", "gulp-cssmin": "^0.2.0",
"gulp-cssmin": "^0.1.7", "gulp-if": "^3.0.0",
"gulp-if": "^2.0.0", "gulp-imagemin": "^7.1.0",
"gulp-imagemin": "^2.3.0", "gulp-jshint": "^2.1.0",
"gulp-jshint": "^1.11.2", "jshint": "^2.11.1",
"gulp-less": "^3.0.3", "gulp-less": "^4.0.1",
"gulp-rename": "^1.2.2", "gulp-rename": "^2.0.0",
"gulp-uglify": "^1.2.0", "gulp-uglify": "^3.0.2",
"gulp-util": "^3.0.7" "gulp-mustache": "^5.0.0"
},
"dependencies": {
"bootstrap": "^3.3.7",
"fork-awesome": "^1.1.7",
"handlebars": "^4.7.6",
"handlebars-intl": "1.1.2",
"isotope-layout": "^3.0.6",
"jquery": "^3.5.1",
"js-cookie": "^2.2.1",
"sammy": "^0.7.6",
"source-code-pro": "^2.30.2",
"source-sans-pro": "^3.6.0"
} }
} }

View file

@ -3,7 +3,7 @@
<a href="#/apps" class="hidden-xs">{{t 'applications'}}</a> <a href="#/apps" class="hidden-xs">{{t 'applications'}}</a>
<a href="#/apps" class="visible-xs">&hellip;</a> <a href="#/apps" class="visible-xs">&hellip;</a>
<a href="#/apps/{{id}}">{{label}}</a> <a href="#/apps/{{id}}">{{label}}</a>
<a href="#/apps/{{id}}/changelabel">{{t 'app_change_label'}}</a> <a href="#/apps/{{id}}/changelabel">{{t 'app_manage_label_and_tiles'}}</a>
</div> </div>
<div class="separator"></div> <div class="separator"></div>
@ -11,19 +11,25 @@
<form action="#/apps/{{id}}/changelabel" method="POST" class="form-horizontal form-app-install"> <form action="#/apps/{{id}}/changelabel" method="POST" class="form-horizontal form-app-install">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title"><span class="fa-fw fa-tag"></span> {{t 'app_change_label'}}</h2> <h2 class="panel-title"><span class="fa-fw fa-tag"></span> {{t 'app_manage_label_and_tiles'}}</h2>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div class="form-group"> {{#each permissions}}
<label for="label" class="col-sm-12">{{t 'label'}}</label> <div class="permission-row" data-permission="{{name}}">
<div class="col-sm-12"> <h3>{{title}}</h3>
<input class="col-sm-12" type="text" id="label" name="label" class="form-control" value="{{label}}" required="required"> {{#if tile_available}}
<p>{{t 'permission_corresponding_url'}}: <a href=https://{{url}}>https://{{url}}</a></p>
{{/if}}
<input type="text" id="label" name="label_{{name}}" class="form-control" value="{{label}}" required="required">
{{#if tile_available}}
<input type="checkbox" id="show_tile_{{name}}" name="show_tile_{{name}}" value="{{name}}" {{#if show_tile}} checked {{/if}}>
<label for="show_tile_{{name}}" style="font-weight:normal;"> {{t 'permission_show_tile_enabled'}}</label>
{{/if}}
</div> </div>
</div> <hr />
<hr> {{/each}}
<input type="hidden" name="app" value="{{id}}">
<div class="text-center"> <div class="text-center">
<input type="submit" role="button" class="btn btn-success slide back" value="{{t 'app_change_label'}}"> <input type="submit" role="button" class="btn btn-success slide back" value="{{t 'apply'}}">
</div> </div>
</div> </div>
</div> </div>

View file

@ -16,7 +16,7 @@
<dt>{{t 'id'}}</dt> <dt>{{t 'id'}}</dt>
<dd>{{settings.id}}</dd> <dd>{{settings.id}}</dd>
<dt>{{t 'label'}}</dt> <dt>{{t 'label'}}</dt>
<dd>{{settings.label}}</dd> <dd>{{label}}</dd>
<dt>{{t 'description'}}</dt> <dt>{{t 'description'}}</dt>
<dd>{{description}}</dd> <dd>{{description}}</dd>
<dt>{{t 'version'}}</dt> <dt>{{t 'version'}}</dt>
@ -41,9 +41,9 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div class="container"> <div class="container">
<p>{{t 'app_info_changelabel_desc' settings.label}}</p> <p>{{t 'app_info_managelabel_desc' settings.label}}</p>
<a role="button" href="#/apps/{{settings.id}}/changelabel" class="btn btn-info slide"> <a role="button" href="#/apps/{{settings.id}}/changelabel" class="btn btn-info slide">
<span class="fa-tag"></span> {{t 'app_change_label'}} <span class="fa-tag"></span> {{t 'app_manage_label_and_tiles'}}
</a> </a>
</div> </div>
<hr> <hr>

View file

@ -16,7 +16,7 @@
<a href="#/apps/{{id}}" class="list-group-item slide" title="{{t 'infos'}}"> <a href="#/apps/{{id}}" class="list-group-item slide" title="{{t 'infos'}}">
<span class="fa-chevron-right pull-right"></span> <span class="fa-chevron-right pull-right"></span>
<h2 class="list-group-item-heading"> <h2 class="list-group-item-heading">
{{settings.label}} <small>{{name}}</small> {{label}} <small>{{name}}</small>
</h2> </h2>
<p class="list-group-item-text">{{description}}</p> <p class="list-group-item-text">{{description}}</p>
</a> </a>

View file

@ -45,7 +45,7 @@
<div class="list-group"> <div class="list-group">
{{#each apps}} {{#each apps}}
<div class="list-group-item"> <div class="list-group-item">
<input type="checkbox" id="{{id}}" name="apps" value="{{id}}" checked class="nice-checkbox"> <input type="checkbox" id="{{id}}" name="apps" value="1" checked class="nice-checkbox">
<label for="{{id}}" class="pull-right"><span class="sr-only">{{t 'check'}}</span></label> <label for="{{id}}" class="pull-right"><span class="sr-only">{{t 'check'}}</span></label>
<h2 class="list-group-item-heading">{{label}} <small>{{id}}</small></h2> <h2 class="list-group-item-heading">{{label}} <small>{{id}}</small></h2>
</div> </div>

View file

@ -9,7 +9,13 @@
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title"><span class="fa-fw fa-info-circle"></span> {{t 'infos'}}</h2> <h2 class="panel-title" style="display: inline-block;"><span class="fa-fw fa-info-circle"></span> {{t 'infos'}}</h2>
<button class="btn btn-sm btn-success pull-right" data-action="download" data-storage="{{storage.id}}" data-archive="{{name}}">
<span class="fa-download"></span> {{t 'download'}}
</button>
<button class="btn btn-sm btn-danger slide pull-right" data-action="delete" data-storage="{{storage.id}}" data-archive="{{name}}">
<span class="fa-trash-o"></span> {{t 'delete'}}
</button>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<dl class="dl-horizontal"> <dl class="dl-horizontal">
@ -25,14 +31,12 @@
<form action="#/backup/{{storage.id}}/{{name}}/restore" method="POST" class="form-horizontal"> <form action="#/backup/{{storage.id}}/{{name}}/restore" method="POST" class="form-horizontal">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title"> <h2 class="panel-title" style="display: inline-block;">
<span class="fa-fw fa-archive"></span> <span class="fa-fw fa-archive"></span>
{{t 'backup_content'}} {{t 'backup_content'}}
<span class="select_all-none pull-right">
<input type="button" role="select_all" class="btn btn-default slide back select_all" value="{{t 'select_all'}}" />
<input type="button" role="select_none" class="btn btn-default slide back select_none" value="{{t 'select_none'}}" />
</span>
</h2> </h2>
<button type="button" data-action="select_all" class="btn btn-sm btn-default pull-right">{{t 'select_all'}}</button>
<button type="button" data-action="select_none" class="btn btn-sm btn-default pull-right">{{t 'select_none'}}</button>
</div> </div>
{{#if items}} {{#if items}}
<div class="list-group"> <div class="list-group">
@ -73,21 +77,3 @@
{{/if}} {{/if}}
</div> </div>
</form> </form>
<div class="separator"></div>
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<span class="fa-fw fa-wrench"></span> {{t 'operations'}}
</h2>
</div>
<div class="panel-body">
<div class="container">
<p>{{t 'backup_archive_delete'}}</p>
<button class="btn btn-danger slide" data-action="delete" data-storage="{{storage.id}}" data-archive="{{name}}">
<span class="fa-trash-o"></span> {{t 'delete'}}
</button>
</div>
</div>
</div>

View file

@ -23,37 +23,23 @@
{{#if log.metadata.started_at}}<dt>{{t 'logs_started_at'}}</dt> <dd>{{formatTime log.metadata.started_at day="numeric" month="long" year="numeric" hour="numeric" minute="numeric"}}</dd> {{#if log.metadata.started_at}}<dt>{{t 'logs_started_at'}}</dt> <dd>{{formatTime log.metadata.started_at day="numeric" month="long" year="numeric" hour="numeric" minute="numeric"}}</dd>
{{/if}}{{#if log.metadata.ended_at}}<dt>{{t 'logs_ended_at'}}</dt> <dd>{{formatTime log.metadata.ended_at day="numeric" month="long" year="numeric" hour="numeric" minute="numeric"}}</dd>{{/if}} {{/if}}{{#if log.metadata.ended_at}}<dt>{{t 'logs_ended_at'}}</dt> <dd>{{formatTime log.metadata.ended_at day="numeric" month="long" year="numeric" hour="numeric" minute="numeric"}}</dd>{{/if}}
{{#if log.metadata.error}}<dt>{{t 'logs_error'}}</dt> <dd>{{log.metadata.error}}</dd>{{/if}} {{#if log.metadata.error}}<dt>{{t 'logs_error'}}</dt> <dd>{{log.metadata.error}}</dd>{{/if}}
{{#if log.metadata.suboperations}}
<dt>{{t 'log_suboperations'}}</dt>
{{#log.metadata.suboperations}}
<dd>{{#unless success }}<span class="fa-fw fa-close text-danger"></span>{{/unless}}
<a href="#/tools/logs/{{ name }}">{{ description }}</a></dd>
{{/log.metadata.suboperations}}
{{/if}}
</dl> </dl>
</div> </div>
</div> </div>
{{#if log.metadata.error}} {{#unless log.metadata.success}}
<div class="alert alert-danger text-center"> <div class="alert alert-danger text-center">
<p>{{t 'operation_failed_explanation'}}</p> <p>{{t 'operation_failed_explanation'}}</p>
</div> </div>
{{/if}} {{/unless}}
<!--
{{#if log.metadata.env}}
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading-context">
<h2 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse-context" aria-expanded="true" aria-controls="collapse-context">
<span class="fa-fw fa-bug"></span>{{t 'logs_context'}}
</a>
</h2>
</div>
<div id="collapse-context" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading-context">
<div class="panel-body">
<dl class="dl-horizontal" id="env">
{{#each log.metadata.env}}<dt>{{@key}}</dt> <dd>{{.}}</dd>
{{/each}}
</dl>
</div>
</div>
</div>
{{/if}}
-->
{{/if}} {{/if}}
<div class="panel panel-default"> <div class="panel panel-default">

View file

@ -7,29 +7,17 @@
<div class="separator"></div> <div class="separator"></div>
{{#intl locales=locale}} {{#intl locales=locale}}
{{#if data}}
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
{{#data}}
{{#if value}}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading-{{key}}"> <div class="panel-heading">
<h2 class="panel-title"> <h2 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse-{{key}}" aria-expanded="true" aria-controls="collapse-{{key}}"> <span class="fa-fw fa-wrench"></span>{{t 'logs_operation'}}
<span class="fa-fw fa-{{icon}}"></span>{{t (concat 'logs_' key)}}
</a>
</h2> </h2>
</div> </div>
<div id="collapse-{{key}}" class="panel-collapse{{#if @first}}{{else}} collapse{{/if}}" role="tabpanel" aria-labelledby="heading-{{key}}">
<div class="list-group"> <div class="list-group">
{{#value}} {{#operations}}
<a href="#/tools/logs/{{ name }}" class="list-group-item slide" title='{{formatTime started_at day="numeric" month="long" year="numeric" hour="numeric" minute="numeric"}}'><small style="margin-right:20px;" >{{formatRelative started_at}}</small> <a href="#/tools/logs/{{ name }}" class="list-group-item slide" title='{{formatTime started_at day="numeric" month="long" year="numeric" hour="numeric" minute="numeric"}}'><small style="margin-right:20px;" >{{formatRelative started_at}}</small>
<span class="fa-fw fa-{{success_icon}}"></span> {{ description }}</a> <span class="fa-fw fa-{{success_icon}}"></span> {{ description }}</a>
{{/value}} {{/operations}}
</div> </div>
</div> </div>
</div>
{{/if}}
{{/data}}
</div>
{{/if}}
{{/intl}} {{/intl}}

View file

@ -5,6 +5,12 @@
<div class="separator"></div> <div class="separator"></div>
{{#if pending_migrations}}
<div class="alert alert-warning">
{{t 'pending_migrations' "#/tools/migrations"}}
</div>
{{/if}}
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h2 class="panel-title"><span class="fa-fw fa-server"></span> {{t 'system'}}</h2> <h2 class="panel-title"><span class="fa-fw fa-server"></span> {{t 'system'}}</h2>

View file

@ -18,15 +18,17 @@
<span class="fa-fw fa-{{icon}}"></span> <span class="fa-fw fa-{{icon}}"></span>
{{text}} {{text}}
<button data-type="{{type}}s" data-action="remove" data-item="{{value}}" data-group="{{group}}"> <button data-type="{{type}}s" data-action="remove" data-item="{{value}}" data-group="{{group}}">
{{#unless protected}}
<span class="fa-close" style="margin-left:5px"></span> <span class="fa-close" style="margin-left:5px"></span>
<span class="sr-only">{{t 'delete'}}</span> <span class="sr-only">{{t 'delete'}}</span>
{{/unless}}
</button> </button>
</span> </span>
{{/inline}} {{/inline}}
{{#*inline "labelsLine"}} {{#*inline "labelsLine"}}
{{#each items}} {{#each items}}
{{> label text=(call ../display .) value=. icon=../icon type=../type item=. group=../group}} {{> label text=(call ../display .) value=. icon=../icon type=../type item=. group=../group protected=(call ../is_protected . ../type ../group)}}
{{/each}} {{/each}}
{{#if inv}} {{#if inv}}
<div class="btn-group"> <div class="btn-group">
@ -73,7 +75,7 @@
<div style="font-style:italic">{{t 'group_explain_visitors_needed_for_external_client'}}</div> <div style="font-style:italic">{{t 'group_explain_visitors_needed_for_external_client'}}</div>
{{/if}} {{/if}}
{{else}} {{else}}
{{> labelsLine display=../displayUser icon="user" type="member" items=members inv=membersInv group=@key}} {{> labelsLine display=../displayUser icon="user" type="member" items=members inv=membersInv group=@key is_protected=../is_protected}}
{{/if}} {{/if}}
</div> </div>
</div> </div>
@ -83,7 +85,7 @@
<h3>{{t 'permissions'}}</h3> <h3>{{t 'permissions'}}</h3>
</div> </div>
<div class="col-sm-10"> <div class="col-sm-10">
{{> labelsLine display=../displayPermission icon="key-modern" type="permission" items=permissions inv=permissionsInv group=@key}} {{> labelsLine display=../displayPermission icon="key-modern" type="permission" items=permissions inv=permissionsInv group=@key is_protected=../is_protected}}
</div> </div>
</div> </div>
</div> </div>
@ -111,7 +113,7 @@
<h3><span class="fa-fw fa-user"></span> {{@key}}</h3> <h3><span class="fa-fw fa-user"></span> {{@key}}</h3>
</div> </div>
<div class="col-sm-10"> <div class="col-sm-10">
{{> labelsLine display=../displayPermission icon="key-modern" type="permission" items=permissions inv=permissionsInv group=@key}} {{> labelsLine display=../displayPermission icon="key-modern" type="permission" items=permissions inv=permissionsInv group=@key is_protected=../is_protected}}
</div> </div>
</div> </div>
<hr /> <hr />

View file

@ -28,11 +28,26 @@
</div> </div>
</div> </div>
<hr> <hr>
<div class="alert alert-warning col-sm-offset-3 col-sm-9"><i class="fa fa-lock fa-fw"></i> {{t 'good_practices_about_user_password'}}</div>
<div class="form-group">
<label for="password" class="col-sm-3 control-label">{{t 'password'}}</label>
<div class="col-sm-9">
<input type="password" id="password" name="password" class="form-control" placeholder="••••••••••" required>
</div>
</div>
<div class="form-group">
<label for="confirmation" class="col-sm-3 control-label">{{t 'password_confirmation'}}</label>
<div class="col-sm-9">
<input type="password" id="confirmation" name="confirmation" class="form-control" placeholder="••••••••••" required>
</div>
</div>
<hr>
<div class="alert alert-info col-sm-offset-3 col-sm-9"><i class="fa fa-envelope fa-fw"></i> {{t 'tip_about_user_email'}}</div>
<div class="form-group"> <div class="form-group">
<label for="mail" class="col-sm-3 control-label">{{t 'user_email'}}</label> <label for="mail" class="col-sm-3 control-label">{{t 'user_email'}}</label>
<div class="clearfix visible-xs"></div> <div class="clearfix visible-xs"></div>
<div class="col-sm-4 col-xs-6"> <div class="col-sm-4 col-xs-6">
<input type="text" id="email" name="email" class="form-control" placeholder="johndoe" required> <p id="email-left" class="form-control-static" style="text-align:right;">johndoe</p>
</div> </div>
<div class="col-sm-5 col-xs-6"> <div class="col-sm-5 col-xs-6">
<select class="form-control" name="domain"> <select class="form-control" name="domain">
@ -42,32 +57,7 @@
</select> </select>
</div> </div>
</div> </div>
<hr>
<div class="form-group">
<label for="mailbox-quota" class="col-sm-3 control-label">{{t 'user_mailbox_quota'}}</label>
<div class="col-sm-4">
<div class="input-group">
<input type="number" min="0" id="mailbox-quota" name="mailbox_quota" class="form-control" placeholder="{{t 'mailbox_quota_placeholder'}}">
<div class="input-group-addon">M</div>
</div>
</div>
<div class="col-sm-5">
<div class="help-block quota-help-block">{{t 'mailbox_quota_description'}}</div>
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-3 control-label">{{t 'password'}}</label>
<div class="col-sm-9">
<input type="password" id="password" name="password" class="form-control" placeholder="•••••" required>
</div>
</div>
<div class="form-group">
<label for="confirmation" class="col-sm-3 control-label">{{t 'password_confirmation'}}</label>
<div class="col-sm-9">
<input type="password" id="confirmation" name="confirmation" class="form-control" placeholder="•••••" required>
<div class="help-block">{{t 'good_practices_about_user_password'}}</div>
</div>
</div>
</div> </div>
</div> </div>

View file

@ -28,6 +28,21 @@
<input type="text" name="lastname" class="form-control" value="{{lastname}}"> <input type="text" name="lastname" class="form-control" value="{{lastname}}">
</div> </div>
</div> </div>
<hr>
<div class="form-group">
<label for="password" class="col-sm-3 control-label">{{t 'password'}}</label>
<div class="col-sm-9">
<input type="password" id="password" name="password" class="form-control" placeholder="••••••••••">
</div>
</div>
<div class="form-group">
<label for="confirmation" class="col-sm-3 control-label">{{t 'password_confirmation'}}</label>
<div class="col-sm-9">
<input type="password" id="confirmation" name="confirmation" class="form-control" placeholder="••••••••••">
<div class="help-block">{{t 'good_practices_about_user_password'}}</div>
</div>
</div>
<hr>
<div class="form-group"> <div class="form-group">
<label for="email" class="col-sm-3 control-label">{{t 'user_email'}}</label> <label for="email" class="col-sm-3 control-label">{{t 'user_email'}}</label>
<div class="clearfix visible-xs"></div> <div class="clearfix visible-xs"></div>
@ -77,22 +92,6 @@
<input id="mailforward" type="email" name="mailforward" class="mailforward-input form-control" placeholder="{{t 'user_new_forward'}}"> <input id="mailforward" type="email" name="mailforward" class="mailforward-input form-control" placeholder="{{t 'user_new_forward'}}">
</div> </div>
</div> </div>
<hr>
<div class="form-group">
<label for="password" class="col-sm-3 control-label">{{t 'password'}}</label>
<div class="col-sm-9">
<input type="password" id="password" name="password" class="form-control" placeholder="•••••">
</div>
</div>
<div class="form-group">
<label for="confirmation" class="col-sm-3 control-label">{{t 'password_confirmation'}}</label>
<div class="col-sm-9">
<input type="password" id="confirmation" name="confirmation" class="form-control" placeholder="•••••">
<div class="help-block">{{t 'good_practices_about_user_password'}}</div>
</div>
</div>
</div> </div>
</div> </div>