mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 09:00:10 +00:00
userpage: show expiry
This commit is contained in:
parent
a22f032924
commit
5beeeb958b
@ -33,7 +33,7 @@ func (app *appContext) MyDetails(gc *gin.Context) {
|
||||
|
||||
if emailEnabled {
|
||||
resp.Email = &MyDetailsContactMethodsDTO{}
|
||||
if email, ok := app.storage.emails[user.ID]; ok {
|
||||
if email, ok := app.storage.emails[user.ID]; ok && email.Addr != "" {
|
||||
resp.Email.Value = email.Addr
|
||||
resp.Email.Enabled = email.Contact
|
||||
}
|
||||
|
@ -44,13 +44,16 @@
|
||||
{{ template "login-modal.html" . }}
|
||||
<div class="page-container">
|
||||
<div class="card @low dark:~d_neutral mb-4" id="card-user">
|
||||
<span class="heading"></span>
|
||||
<span class="heading mb-2"></span>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div class="card @low dark:~d_neutral" id="card-times">
|
||||
<div class="card @low dark:~d_neutral unfocused" id="card-status">
|
||||
<span class="heading mb-2">{{ .strings.expiry }}</span>
|
||||
<aside class="aside ~warning user-expiry my-4"></aside>
|
||||
<div class="user-expiry-countdown"></div>
|
||||
</div>
|
||||
<div class="card @low dark:~d_neutral" id="card-contact">
|
||||
<span class="heading">{{ .strings.contactMethods }}</span>
|
||||
<span class="heading mb-2">{{ .strings.contactMethods }}</span>
|
||||
<div class="content"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
2
lang.go
2
lang.go
@ -29,6 +29,7 @@ type commonLang struct {
|
||||
Meta langMeta `json:"meta"`
|
||||
Strings langSection `json:"strings"`
|
||||
Notifications langSection `json:"notifications"`
|
||||
QuantityStrings map[string]quantityString `json:"quantityStrings"`
|
||||
}
|
||||
|
||||
type adminLang struct {
|
||||
@ -58,6 +59,7 @@ type userLang struct {
|
||||
notificationsJSON string
|
||||
ValidationStrings map[string]quantityString `json:"validationStrings"`
|
||||
validationStringsJSON string
|
||||
QuantityStrings map[string]quantityString `json:"quantityStrings"`
|
||||
JSON string
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
"lastActiveTime": "Sidst Aktiv",
|
||||
"from": "Fra",
|
||||
"user": "Bruger",
|
||||
"expiry": "Udløb",
|
||||
"userExpiry": "Brugerens Udløb",
|
||||
"userExpiryDescription": "En specificeret tid efter hver tilmelding, sletter/deaktiverer jfa-go kontoen. Du kan ændre denne adfærd i indstillingerne.",
|
||||
"aboutProgram": "Om",
|
||||
|
@ -81,7 +81,6 @@
|
||||
"download": "Herunterladen",
|
||||
"update": "Aktualisieren",
|
||||
"updates": "Aktualisierungen",
|
||||
"expiry": "Ablaufdatum",
|
||||
"extendExpiry": "Ablaufdatum verlängern",
|
||||
"donate": "Spenden",
|
||||
"conditionals": "Bedingungen",
|
||||
|
@ -75,7 +75,6 @@
|
||||
"download": "Λήψη",
|
||||
"search": "Αναζήτηση",
|
||||
"inviteDuration": "Διάρκεια Πρόσκλησης",
|
||||
"expiry": "Λήξη",
|
||||
"userExpiry": "Λήξη Χρήστη",
|
||||
"userExpiryDescription": "Μετά απο ένα καθορισμένο χρόνο μετά απο κάθε εγγραφή, το jfa-go θα διαγράφει/απενεργοποιεί τον λογαριασμό. Μπορείτε να αλλάξετε αυτή την συμπεριφορά στις ρυθμίσεις.",
|
||||
"announce": "Ανακοίνωση",
|
||||
|
@ -71,7 +71,6 @@
|
||||
"apply": "Apply",
|
||||
"delete": "Delete",
|
||||
"updates": "Updates",
|
||||
"expiry": "Expiry",
|
||||
"variables": "Variables",
|
||||
"preview": "Preview",
|
||||
"markdownSupported": "Markdown is supported.",
|
||||
|
@ -33,7 +33,6 @@
|
||||
"after": "After",
|
||||
"before": "Before",
|
||||
"user": "User",
|
||||
"expiry": "Expiry",
|
||||
"userExpiry": "User Expiry",
|
||||
"userExpiryDescription": "A specified amount of time after each signup, jfa-go will delete/disable the account. You can change this behaviour in settings.",
|
||||
"aboutProgram": "About",
|
||||
|
@ -28,7 +28,6 @@
|
||||
"lastActiveTime": "Último activo",
|
||||
"from": "De",
|
||||
"user": "Usuario",
|
||||
"expiry": "Expiración",
|
||||
"userExpiry": "Caducidad del usuario",
|
||||
"userExpiryDescription": "Una cantidad de tiempo específica después de cada registro, jfa-go eliminará / deshabilitará la cuenta. Puede cambiar este comportamiento en la configuración.",
|
||||
"aboutProgram": "Acerca de",
|
||||
|
@ -76,7 +76,6 @@
|
||||
"edit": "Éditer",
|
||||
"customizeMessages": "Personnaliser les e-mails",
|
||||
"inviteDuration": "Durée de l'invitation",
|
||||
"expiry": "Expiration",
|
||||
"advancedSettings": "Paramètres avancés",
|
||||
"userExpiry": "Expiration de l'utilisateur",
|
||||
"updates": "Mises à jour",
|
||||
|
@ -31,7 +31,6 @@
|
||||
"lastActiveTime": "Utoljára aktív",
|
||||
"from": "Feladó",
|
||||
"user": "Felhasználó",
|
||||
"expiry": "Lejárat",
|
||||
"userExpiry": "Felhasználói lejárat",
|
||||
"userExpiryDescription": "Egy meghatározott idő után minden regisztrációt töröl, vagy felfüggeszt a jfa-go. Ezt a működést megváltoztathatod a beállításokban.",
|
||||
"aboutProgram": "Névjegy",
|
||||
|
@ -75,7 +75,6 @@
|
||||
"customizeMessages": "E-mails aanpassen",
|
||||
"inviteDuration": "Geldigheidsduur uitnodiging",
|
||||
"userExpiryDescription": "Een bepaalde tijd na elke aanmelding, wordt de account verwijderd/uitgeschakeld door jfa-go. Dit kan aangepast worden in de instellingen.",
|
||||
"expiry": "Verloop",
|
||||
"userExpiry": "Gebruikersverloop",
|
||||
"extendExpiry": "Verleng verloop",
|
||||
"updates": "Updates",
|
||||
|
@ -31,7 +31,6 @@
|
||||
"lastActiveTime": "Ostatnia aktywność",
|
||||
"from": "Od",
|
||||
"user": "Użytkownik",
|
||||
"expiry": "Wygasa",
|
||||
"userExpiry": "Użytkownik wygasa",
|
||||
"userExpiryDescription": "",
|
||||
"aboutProgram": "O",
|
||||
|
@ -75,7 +75,6 @@
|
||||
"customizeMessages": "Customizar Emails",
|
||||
"userExpiryDescription": "Após um determinado período de tempo de cada inscrição, o jfa-go apagará/desabilitará a conta. Você pode alterar essa opção nas configurações.",
|
||||
"inviteDuration": "Duração do Convite",
|
||||
"expiry": "Expira",
|
||||
"userExpiry": "Vencimento do Usuário",
|
||||
"extendExpiry": "Extender o vencimento",
|
||||
"updates": "Atualizações",
|
||||
|
@ -74,7 +74,6 @@
|
||||
"notifyInviteExpiry": "Vid utgång",
|
||||
"notifyUserCreation": "Vid användarskapande",
|
||||
"inviteDuration": "Varaktighet för inbjudan",
|
||||
"expiry": "Löper ut",
|
||||
"userExpiry": "Användarutgång",
|
||||
"userExpiryDescription": "Efter en angiven tid efter varje registrering så tar jfa-go bort/inaktiverar kontot. Du kan ändra detta beteende i inställningarna.",
|
||||
"extendExpiry": "Förläng utgång"
|
||||
|
@ -31,7 +31,6 @@
|
||||
"lastActiveTime": "Lần cuối Hoạt động",
|
||||
"from": "Từ",
|
||||
"user": "Người dùng",
|
||||
"expiry": "Hết hạn",
|
||||
"userExpiry": "Hết hạn Người dùng",
|
||||
"userExpiryDescription": "Sau một khoảng thời gian nhất định sau khi mỗi đăng ký, jfa-go sẽ xóa/vô hiệu hóa tài khoản. Bạn có thể chỉnh sửa chế độ này trong cài đặt.",
|
||||
"aboutProgram": "Thông tin",
|
||||
|
@ -30,7 +30,6 @@
|
||||
"lastActiveTime": "上次活动",
|
||||
"from": "从",
|
||||
"user": "用户",
|
||||
"expiry": "到期",
|
||||
"userExpiry": "用户到期",
|
||||
"userExpiryDescription": "每次注册后的指定时间,jfa-go 将删除/禁用该帐户。您可以在设置中更改此行为。",
|
||||
"aboutProgram": "关于",
|
||||
|
@ -31,7 +31,6 @@
|
||||
"lastActiveTime": "上次啟用時間",
|
||||
"from": "從",
|
||||
"user": "帳戶",
|
||||
"expiry": "到期",
|
||||
"userExpiry": "帳戶到期",
|
||||
"userExpiryDescription": "每次註冊后指定的時間,jfa-go 將刪除/禁用該帳戶。您可以在設定中更改此行為。",
|
||||
"aboutProgram": "關於",
|
||||
|
@ -3,5 +3,6 @@
|
||||
"name": "العربية (AR)"
|
||||
},
|
||||
"strings": {},
|
||||
"notifications": {}
|
||||
"notifications": {},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -31,7 +31,8 @@
|
||||
"enabled": "Aktiveret",
|
||||
"disabled": "Deaktiveret",
|
||||
"reEnable": "Genaktiver",
|
||||
"disable": "Deaktiver"
|
||||
"disable": "Deaktiver",
|
||||
"expiry": "Udløb"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "Brugernavnet og/eller adgangskoden blev efterladt tomme.",
|
||||
@ -39,5 +40,6 @@
|
||||
"errorUnknown": "Ukendt fejl.",
|
||||
"error401Unauthorized": "Adgang nægtet. Prøv at genindlæse siden.",
|
||||
"errorSaveSettings": "Kunne ikke gemme indstillingerne."
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -31,7 +31,8 @@
|
||||
"enabled": "Aktiviert",
|
||||
"disabled": "Deaktiviert",
|
||||
"reEnable": "Wieder aktivieren",
|
||||
"disable": "Deaktivieren"
|
||||
"disable": "Deaktivieren",
|
||||
"expiry": "Ablaufdatum"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "Der Benutzername und/oder das Passwort wurden nicht ausgefüllt.",
|
||||
@ -39,5 +40,6 @@
|
||||
"errorUnknown": "Unbekannter Fehler.",
|
||||
"error401Unauthorized": "Unberechtigt. Versuch, die Seite zu aktualisieren.",
|
||||
"errorSaveSettings": "Einstellungen konnten nicht gespeichert werden."
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -22,7 +22,8 @@
|
||||
"enabled": "Ενεργοποιημένο",
|
||||
"disabled": "Απενεργοποιημένο",
|
||||
"reEnable": "Επανα-ενεργοποίηση",
|
||||
"disable": "Απενεργοποίηση"
|
||||
"disable": "Απενεργοποίηση",
|
||||
"expiry": "Λήξη"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "Το όνομα χρήστη και/ή ο κωδικός ήταν κενά.",
|
||||
@ -30,5 +31,6 @@
|
||||
"errorUnknown": "Άγνωστο σφάλμα.",
|
||||
"error401Unauthorized": "Ανεξουσιοδότητος. Προσπαθήστε να κάνετε επαναφόρτωση την σελίδα.",
|
||||
"errorSaveSettings": "Αποτυχία αποθήκευσης ρυθμίσεων."
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -31,7 +31,8 @@
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled",
|
||||
"reEnable": "Re-enable",
|
||||
"disable": "Disable"
|
||||
"disable": "Disable",
|
||||
"expiry": "Expiry"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "The username and/or password was left blank.",
|
||||
@ -39,5 +40,6 @@
|
||||
"errorUnknown": "Unknown error.",
|
||||
"error401Unauthorized": "Unauthorised. Try refreshing the page.",
|
||||
"errorSaveSettings": "Couldn't save settings."
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -32,7 +32,10 @@
|
||||
"disabled": "Disabled",
|
||||
"reEnable": "Re-enable",
|
||||
"disable": "Disable",
|
||||
"contactMethods": "Contact Methods"
|
||||
"contactMethods": "Contact Methods",
|
||||
"accountStatus": "Account Status",
|
||||
"notSet": "Not set",
|
||||
"expiry": "Expiry"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "The username and/or password were left blank.",
|
||||
@ -40,5 +43,19 @@
|
||||
"errorUnknown": "Unknown error.",
|
||||
"error401Unauthorized": "Unauthorized. Try refreshing the page.",
|
||||
"errorSaveSettings": "Couldn't save settings."
|
||||
},
|
||||
"quantityStrings": {
|
||||
"year": {
|
||||
"singular": "{n} Year",
|
||||
"plural": "{n} Years"
|
||||
},
|
||||
"month": {
|
||||
"singular": "{n} Month",
|
||||
"plural": "{n} Months"
|
||||
},
|
||||
"day": {
|
||||
"singular": "{n} Day",
|
||||
"plural": "{n} Days"
|
||||
}
|
||||
}
|
||||
}
|
@ -31,7 +31,8 @@
|
||||
"enabled": "Activado",
|
||||
"disabled": "Desactivado",
|
||||
"reEnable": "Reactivar",
|
||||
"disable": "Desactivar"
|
||||
"disable": "Desactivar",
|
||||
"expiry": "Expiración"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "El nombre de usuario y/o la contraseña se dejaron en blanco.",
|
||||
@ -39,5 +40,6 @@
|
||||
"errorUnknown": "Error desconocido.",
|
||||
"error401Unauthorized": "No autorizado. Intente actualizar la página.",
|
||||
"errorSaveSettings": "No se pudo guardar la configuración."
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -24,5 +24,6 @@
|
||||
"contactDiscord": "از طریق دیسکورد تماس بگیرید",
|
||||
"theme": "موضوع"
|
||||
},
|
||||
"notifications": {}
|
||||
"notifications": {},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -31,7 +31,8 @@
|
||||
"enabled": "Activé",
|
||||
"disabled": "Désactivé",
|
||||
"reEnable": "Ré-activé",
|
||||
"disable": "Désactivé"
|
||||
"disable": "Désactivé",
|
||||
"expiry": "Expiration"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "Le nom d'utilisateur et/ou le mot de passe sont vides.",
|
||||
@ -39,5 +40,6 @@
|
||||
"errorUnknown": "Erreur inconnue.",
|
||||
"error401Unauthorized": "Non autorisé. Essayez d'actualiser la page.",
|
||||
"errorSaveSettings": "Impossible d'enregistrer les paramètres."
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -9,7 +9,9 @@
|
||||
"enabled": "Engedélyezve",
|
||||
"disabled": "Tiltva",
|
||||
"reEnable": "Újra engedélyezés",
|
||||
"disable": "Letiltás"
|
||||
"disable": "Letiltás",
|
||||
"expiry": "Lejárat"
|
||||
},
|
||||
"notifications": {}
|
||||
"notifications": {},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -25,5 +25,6 @@
|
||||
"errorUnknown": "Kesalahan yang tidak diketahui.",
|
||||
"error401Unauthorized": "Tidak ter-otorisasi. Coba segarkan halaman.",
|
||||
"errorSaveSettings": "Tidak dapat menyimpan pengaturan."
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -26,5 +26,6 @@
|
||||
"refresh": "Aggiorna",
|
||||
"required": "Richiesto"
|
||||
},
|
||||
"notifications": {}
|
||||
"notifications": {},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -31,7 +31,8 @@
|
||||
"enabled": "Ingeschakeld",
|
||||
"disabled": "Uitgeschakeld",
|
||||
"reEnable": "Opnieuw inschakelen",
|
||||
"disable": "Uitschakelen"
|
||||
"disable": "Uitschakelen",
|
||||
"expiry": "Verloop"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "De gebruikersnaam en/of wachtwoord is leeg.",
|
||||
@ -39,5 +40,6 @@
|
||||
"errorUnknown": "Onbekende fout.",
|
||||
"error401Unauthorized": "Geen toegang. Probeer de pagina te vernieuwen.",
|
||||
"errorSaveSettings": "Opslaan van instellingen mislukt."
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -28,11 +28,13 @@
|
||||
"admin": "Admin",
|
||||
"enabled": "Włączone",
|
||||
"disabled": "Wyłączone",
|
||||
"disable": "Wyłączone"
|
||||
"disable": "Wyłączone",
|
||||
"expiry": "Wygasa"
|
||||
},
|
||||
"notifications": {
|
||||
"errorConnection": "Nie udało się połączyć z jfa-go.",
|
||||
"errorUnknown": "Nieznany błąd.",
|
||||
"error401Unauthorized": "Nieautoryzowany. Spróbuj odświeżyć stronę."
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -31,7 +31,8 @@
|
||||
"enabled": "Habilitado",
|
||||
"disabled": "Desativado",
|
||||
"reEnable": "Reativar",
|
||||
"disable": "Desativar"
|
||||
"disable": "Desativar",
|
||||
"expiry": "Expira"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "O nome de usuário e/ou senha foram deixados em branco.",
|
||||
@ -39,5 +40,6 @@
|
||||
"errorUnknown": "Erro desconhecido.",
|
||||
"error401Unauthorized": "Não autorizado. Tente atualizar a página.",
|
||||
"errorSaveSettings": "Não foi possível salvar as configurações."
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -3,5 +3,6 @@
|
||||
"name": "Română (ROU)"
|
||||
},
|
||||
"strings": {},
|
||||
"notifications": {}
|
||||
"notifications": {},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -26,5 +26,6 @@
|
||||
"refresh": "Osveži",
|
||||
"required": "Obvezno"
|
||||
},
|
||||
"notifications": {}
|
||||
"notifications": {},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -19,7 +19,8 @@
|
||||
"logout": "Logga ut",
|
||||
"admin": "Admin",
|
||||
"enabled": "Aktiverad",
|
||||
"disabled": "Inaktiverad"
|
||||
"disabled": "Inaktiverad",
|
||||
"expiry": "Löper ut"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "Användarnamnet och/eller lösenordet lämnades tomt.",
|
||||
@ -27,5 +28,6 @@
|
||||
"errorUnknown": "Okänt fel.",
|
||||
"error401Unauthorized": "Obehörig. Prova att uppdatera sidan.",
|
||||
"errorSaveSettings": "Det gick inte att spara inställningarna."
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -9,10 +9,12 @@
|
||||
"enabled": "Mở",
|
||||
"disabled": "Tắt",
|
||||
"reEnable": "Mở lại",
|
||||
"disable": "Tắt"
|
||||
"disable": "Tắt",
|
||||
"expiry": "Hết hạn"
|
||||
},
|
||||
"notifications": {
|
||||
"errorConnection": "Không thể kết nối với jfa-go.",
|
||||
"error401Unauthorized": "Không được phép. Hãy thử làm mới trang."
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -31,7 +31,8 @@
|
||||
"enabled": "已启用",
|
||||
"disabled": "已禁用",
|
||||
"reEnable": "重新启用",
|
||||
"disable": "禁用"
|
||||
"disable": "禁用",
|
||||
"expiry": "到期"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "用户名/密码留空。",
|
||||
@ -39,5 +40,6 @@
|
||||
"errorUnknown": "未知错误。",
|
||||
"error401Unauthorized": "无授权。尝试刷新页面。",
|
||||
"errorSaveSettings": "无法保存设置。"
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
@ -31,7 +31,8 @@
|
||||
"enabled": "已啟用",
|
||||
"disabled": "已禁用",
|
||||
"reEnable": "重新啟用",
|
||||
"disable": "禁用"
|
||||
"disable": "禁用",
|
||||
"expiry": "到期"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "帳戶名稱和/或密碼留空。",
|
||||
@ -39,5 +40,6 @@
|
||||
"errorUnknown": "未知的錯誤。",
|
||||
"error401Unauthorized": "未經授權。嘗試重新整理頁面。",
|
||||
"errorSaveSettings": "無法儲存設置。"
|
||||
}
|
||||
},
|
||||
"quantityStrings": {}
|
||||
}
|
52
scripts/langmover/common.json
Normal file
52
scripts/langmover/common.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"meta": {
|
||||
"name": "English (US)"
|
||||
},
|
||||
"strings": {
|
||||
"username": "common",
|
||||
"password": "common",
|
||||
"emailAddress": "common",
|
||||
"name": "common",
|
||||
"submit": "common",
|
||||
"send": "common",
|
||||
"success": "common",
|
||||
"continue": "common",
|
||||
"error": "common",
|
||||
"copy": "common",
|
||||
"copied": "common",
|
||||
"time24h": "common",
|
||||
"time12h": "common",
|
||||
"linkTelegram": "common",
|
||||
"contactEmail": "common",
|
||||
"contactTelegram": "common",
|
||||
"linkDiscord": "common",
|
||||
"linkMatrix": "common",
|
||||
"contactDiscord": "common",
|
||||
"theme": "common",
|
||||
"refresh": "common",
|
||||
"required": "common",
|
||||
"login": "common",
|
||||
"logout": "common",
|
||||
"admin": "common",
|
||||
"enabled": "common",
|
||||
"disabled": "common",
|
||||
"reEnable": "common",
|
||||
"disable": "common",
|
||||
"contactMethods": "common",
|
||||
"accountStatus": "common",
|
||||
"notSet": "common",
|
||||
"expiry": "admin"
|
||||
},
|
||||
"notifications": {
|
||||
"errorLoginBlank": "common",
|
||||
"errorConnection": "common",
|
||||
"errorUnknown": "common",
|
||||
"error401Unauthorized": "common",
|
||||
"errorSaveSettings": "common"
|
||||
},
|
||||
"quantityStrings": {
|
||||
"year": "common",
|
||||
"month": "common",
|
||||
"day": "common"
|
||||
}
|
||||
}
|
24
storage.go
24
storage.go
@ -202,6 +202,25 @@ func (common *commonLangs) patchCommonNotifications(to *langSection, from ...str
|
||||
}
|
||||
}
|
||||
|
||||
func (common *commonLangs) patchCommonQuantityStrings(to *map[string]quantityString, from ...string) {
|
||||
if *to == nil {
|
||||
*to = map[string]quantityString{}
|
||||
}
|
||||
for n, ev := range (*common)[from[len(from)-1]].QuantityStrings {
|
||||
if v, ok := (*to)[n]; !ok || (v.Singular == "" && v.Plural == "") {
|
||||
i := 0
|
||||
for i < len(from)-1 {
|
||||
ev, ok = (*common)[from[i]].QuantityStrings[n]
|
||||
if ok && ev.Singular != "" && ev.Plural != "" {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
(*to)[n] = ev
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func patchLang(to *langSection, from ...*langSection) {
|
||||
if *to == nil {
|
||||
*to = langSection{}
|
||||
@ -283,10 +302,14 @@ func (st *Storage) loadLangCommon(filesystems ...fs.FS) error {
|
||||
if err == nil {
|
||||
loadedLangs[fsIndex][lang.Meta.Fallback+".json"] = true
|
||||
patchLang(&lang.Strings, &fallback.Strings, &english.Strings)
|
||||
patchLang(&lang.Notifications, &fallback.Notifications, &english.Notifications)
|
||||
patchQuantityStrings(&lang.QuantityStrings, &fallback.QuantityStrings, &english.QuantityStrings)
|
||||
}
|
||||
}
|
||||
if (lang.Meta.Fallback != "" && err != nil) || lang.Meta.Fallback == "" {
|
||||
patchLang(&lang.Strings, &english.Strings)
|
||||
patchLang(&lang.Notifications, &english.Notifications)
|
||||
patchQuantityStrings(&lang.QuantityStrings, &english.QuantityStrings)
|
||||
}
|
||||
}
|
||||
st.lang.Common[index] = lang
|
||||
@ -437,6 +460,7 @@ func (st *Storage) loadLangUser(filesystems ...fs.FS) error {
|
||||
}
|
||||
st.lang.Common.patchCommonStrings(&lang.Strings, index)
|
||||
st.lang.Common.patchCommonNotifications(&lang.Notifications, index)
|
||||
st.lang.Common.patchCommonQuantityStrings(&lang.QuantityStrings, index)
|
||||
// turns out, a lot of email strings are useful on the user page.
|
||||
emailLang := []langSection{st.lang.Email[index].WelcomeEmail, st.lang.Email[index].UserDisabled, st.lang.Email[index].UserExpired}
|
||||
for _, v := range emailLang {
|
||||
|
87
ts/user.ts
87
ts/user.ts
@ -1,7 +1,7 @@
|
||||
import { ThemeManager } from "./modules/theme.js";
|
||||
import { lang, LangFile, loadLangSelector } from "./modules/lang.js";
|
||||
import { Modal } from "./modules/modal.js";
|
||||
import { _get, _post, notificationBox, whichAnimationEvent } from "./modules/common.js";
|
||||
import { _get, _post, notificationBox, whichAnimationEvent, toDateString } from "./modules/common.js";
|
||||
import { Login } from "./modules/login.js";
|
||||
|
||||
interface userWindow extends Window {
|
||||
@ -31,6 +31,7 @@ window.notifications = new notificationBox(document.getElementById('notification
|
||||
|
||||
var rootCard = document.getElementById("card-user");
|
||||
var contactCard = document.getElementById("card-contact");
|
||||
var statusCard = document.getElementById("card-status");
|
||||
|
||||
interface MyDetailsContactMethod {
|
||||
value: string;
|
||||
@ -58,15 +59,17 @@ interface ContactDTO {
|
||||
|
||||
class ContactMethods {
|
||||
private _card: HTMLElement;
|
||||
private _content: HTMLElement;
|
||||
private _buttons: { [name: string]: { element: HTMLElement, details: MyDetailsContactMethod } };
|
||||
|
||||
constructor (card: HTMLElement) {
|
||||
this._card = card;
|
||||
this._content = this._card.querySelector(".content");
|
||||
this._buttons = {};
|
||||
}
|
||||
|
||||
clear = () => {
|
||||
this._card.textContent = "";
|
||||
this._content.textContent = "";
|
||||
this._buttons = {};
|
||||
}
|
||||
|
||||
@ -80,7 +83,7 @@ class ContactMethods {
|
||||
${icon}
|
||||
</span>
|
||||
</span>
|
||||
<span class="ml-2 font-bold">${details.value}</span>
|
||||
<span class="ml-2 font-bold">${(details.value == "") ? window.lang.strings("notSet") : details.value}</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<button class="user-contact-enabled-disabled button ~neutral">
|
||||
@ -121,7 +124,7 @@ class ContactMethods {
|
||||
checkbox.checked = details.enabled;
|
||||
setButtonAppearance();
|
||||
|
||||
this._card.appendChild(row);
|
||||
this._content.appendChild(row);
|
||||
};
|
||||
|
||||
private _save = () => {
|
||||
@ -141,6 +144,80 @@ class ContactMethods {
|
||||
};
|
||||
}
|
||||
|
||||
class ExpiryCard {
|
||||
private _card: HTMLElement;
|
||||
private _expiry: Date;
|
||||
private _aside: HTMLElement;
|
||||
private _countdown: HTMLElement;
|
||||
private _interval: number = null;
|
||||
|
||||
constructor(card: HTMLElement) {
|
||||
this._card = card;
|
||||
this._aside = this._card.querySelector(".user-expiry") as HTMLElement;
|
||||
this._countdown = this._card.querySelector(".user-expiry-countdown") as HTMLElement;
|
||||
}
|
||||
|
||||
private _drawCountdown = () => {
|
||||
let now = new Date();
|
||||
// Years, Months, Days
|
||||
let ymd = [0, 0, 0];
|
||||
while (now.getFullYear() != this._expiry.getFullYear()) {
|
||||
ymd[0] += 1;
|
||||
now.setFullYear(now.getFullYear()+1);
|
||||
}
|
||||
if (now.getMonth() > this._expiry.getMonth()) {
|
||||
ymd[0] -=1;
|
||||
now.setFullYear(now.getFullYear()-1);
|
||||
}
|
||||
while (now.getMonth() != this._expiry.getMonth()) {
|
||||
ymd[1] += 1;
|
||||
now.setMonth(now.getMonth() + 1);
|
||||
}
|
||||
if (now.getDate() > this._expiry.getDate()) {
|
||||
ymd[1] -=1;
|
||||
now.setMonth(now.getMonth()-1);
|
||||
}
|
||||
while (now.getDate() != this._expiry.getDate()) {
|
||||
ymd[2] += 1;
|
||||
now.setDate(now.getDate() + 1);
|
||||
}
|
||||
|
||||
const langKeys = ["year", "month", "day"];
|
||||
let innerHTML = ``;
|
||||
for (let i = 0; i < langKeys.length; i++) {
|
||||
if (ymd[i] == 0) continue;
|
||||
const words = window.lang.quantity(langKeys[i], ymd[i]).split(" ");
|
||||
innerHTML += `
|
||||
<div class="row my-3">
|
||||
<div class="inline baseline">
|
||||
<span class="text-2xl">${words[0]}</span> <span class="text-gray-400 text-lg">${words[1]}</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
this._countdown.innerHTML = innerHTML;
|
||||
};
|
||||
|
||||
get expiry(): Date { return this._expiry; };
|
||||
set expiry(expiryUnix: number) {
|
||||
if (this._interval !== null) {
|
||||
window.clearInterval(this._interval);
|
||||
this._interval = null;
|
||||
}
|
||||
if (expiryUnix == 0) return;
|
||||
this._expiry = new Date(expiryUnix * 1000);
|
||||
this._aside.textContent = window.lang.strings("yourAccountIsValidUntil").replace("{date}", toDateString(this._expiry));
|
||||
this._card.classList.remove("unfocused");
|
||||
|
||||
this._interval = window.setInterval(this._drawCountdown, 60*1000);
|
||||
this._drawCountdown();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
var expiryCard = new ExpiryCard(statusCard);
|
||||
|
||||
var contactMethodList = new ContactMethods(contactCard);
|
||||
|
||||
document.addEventListener("details-reload", () => {
|
||||
@ -179,6 +256,8 @@ document.addEventListener("details-reload", () => {
|
||||
contactMethodList.append(method[0], details[method[0]], method[1]);
|
||||
}
|
||||
}
|
||||
|
||||
expiryCard.expiry = details.expiry;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user