mirror of
https://github.com/seriousm4x/UpSnap.git
synced 2026-08-02 10:29:48 -04:00
feat: i18n add rest of routes #71
This commit is contained in:
@@ -2,7 +2,7 @@ import en_US from '../en-US';
|
||||
import type { Translation } from '../i18n-types';
|
||||
|
||||
const de_DE = {
|
||||
...(en_US as Translation),
|
||||
...(en_US as unknown as Translation),
|
||||
home: {
|
||||
order_groups: 'Gruppen',
|
||||
order_name: 'Name',
|
||||
@@ -24,15 +24,97 @@ const de_DE = {
|
||||
change_password_body: 'Nachdem das Passwort geändert wurde, musst du dich neu einloggen.',
|
||||
change_password_label: 'Altes Passwort',
|
||||
change_password_new: 'Neues Password',
|
||||
change_password_confirm: 'Password bestätigen',
|
||||
toast_admin_saved: 'Admin gespeichert',
|
||||
toast_user_saved: 'Benutzer gespeichert',
|
||||
toast_password_changed: 'Passwort geändert. Bitte neu einloggen.',
|
||||
toast_passwords_missmatch: 'Passwörter stimmen nicht überein'
|
||||
change_password_confirm: 'Password bestätigen'
|
||||
},
|
||||
device: {
|
||||
page_title: 'Neues Gerät',
|
||||
tabs: ['Manuell', 'Netzwerkscan']
|
||||
},
|
||||
login: {
|
||||
welcome: 'Willkommen',
|
||||
email_label: 'Email oder Nutzername:',
|
||||
password_label: 'Passwort:',
|
||||
btn_more: 'Mehr',
|
||||
menu_title_auth_providers: 'Andere Login Provider',
|
||||
btn_login: 'Login'
|
||||
},
|
||||
settings: {
|
||||
settings_title: 'Einstellungen',
|
||||
ping_interval_title: 'Ping Intervall',
|
||||
ping_interval_desc1:
|
||||
'Legt den Intervall fest, in dem Geräte gepingt werden. Leer lassen um den Standardwert von <span class="badge">@every 3s</span> zu verwenden.',
|
||||
ping_interval_desc2:
|
||||
'Lerne mehr über die korrekte Cron Syntax auf <a class="link" href="https://de.wikipedia.org/wiki/Cron" target="_blank">Wikipedia</a> oder sieh dir die <a class="link" href="https://pkg.go.dev/github.com/robfig/cron/v3" target="_blank">Paketdokumentation</a> an.',
|
||||
lazy_ping_title: 'Lazy Ping',
|
||||
lazy_ping_desc:
|
||||
'Wenn Lazy Ping aktiviert ist, pingt UpSnap die Geräte nur an, wenn ein aktiver Benutzer die Website besucht. Wenn es ausgeschaltet ist, pingt UpSnap die Geräte immer an.',
|
||||
lazy_ping_enable: 'Aktivieren',
|
||||
website_title_title: 'Seitentitel',
|
||||
website_title_desc: 'Setzt den Seiten- und den Tabtitel.',
|
||||
icon_title: 'Icon',
|
||||
icon_desc: 'Eigenes Favicon nutzen. Unterstützte Dateitypen sind:',
|
||||
upsnap_version: 'UpSnap Version'
|
||||
},
|
||||
users: {
|
||||
page_title: 'Benutzer',
|
||||
allow_create_devices:
|
||||
'{username} erlauben neue Geräte zu erstellen und Gerätegruppen zu bearbeiten',
|
||||
device_permissions: 'Geräteberechtigungen',
|
||||
create_new_device: 'Neues Gerät erstellen',
|
||||
read: 'Lesen',
|
||||
update: 'Ändern',
|
||||
delete: 'Löschen',
|
||||
power: 'Power',
|
||||
toggle: 'Toggle',
|
||||
confirm_delete_title: 'Löschen bestätigen',
|
||||
confirm_delete_desc: 'Soll {username} wirklich gelöscht werden?',
|
||||
create_new_user: 'Neuen Benutzer erstellen',
|
||||
username: 'Benutzername',
|
||||
password: 'Passwort',
|
||||
password_confirm: 'Passwort bestätigen',
|
||||
required_field: 'Pflichtfeld'
|
||||
},
|
||||
buttons: {
|
||||
save: 'Speichern',
|
||||
change: 'Ändern'
|
||||
delete: 'Löschen',
|
||||
change: 'Ändern',
|
||||
reset: 'Zurücksetzen',
|
||||
cancle: 'Abbrechen',
|
||||
add: 'Hinzufügen'
|
||||
},
|
||||
welcome: {
|
||||
step1_page_title: 'Willkommen bei UpSnap 🥳',
|
||||
step1_setup_desc:
|
||||
'Bitte schließe die nachfolgenden Schritte ab, um die Einrichtung abzuschließen.',
|
||||
step1_setup_btn_next: 'Weiter',
|
||||
step2_page_title: 'Erstelle einen Admin Account',
|
||||
step2_label_email: 'Email:',
|
||||
step2_label_password: 'Passwort:',
|
||||
step2_label_min_chars: 'min. 10 Zeichen',
|
||||
step2_label_password_confirm: 'Passwort bestätigen:',
|
||||
step2_btn_create: 'Erstellen',
|
||||
step3_page_title: 'Du bist fertig! 🎉',
|
||||
step3_page_desc: 'Füge Geräte zu deinem Dashboard hinzu.',
|
||||
step3_btn_done: 'Lets go!',
|
||||
not_expected_title: 'Ich hab dich hier nicht erwartet! 🧐',
|
||||
not_expected_desc: 'Du hast die Einrichtung bereits abgeschlossen! Hier gibts nichts zu tun.',
|
||||
not_expected_back: 'Bring mich zurück',
|
||||
progress_step1: 'Willkommen',
|
||||
progress_step2: 'Account erstellen',
|
||||
progress_step3: 'Fertig'
|
||||
},
|
||||
toasts: {
|
||||
admin_saved: 'Admin gespeichert',
|
||||
user_saved: 'Benutzer gespeichert',
|
||||
user_created: 'Benutzer {username} erstellt',
|
||||
user_deleted: 'Benutzer {username} gelöscht',
|
||||
settings_saved: 'Einstellungen gespeichert',
|
||||
password_changed: 'Passwort geändert. Bitte neu einloggen.',
|
||||
passwords_missmatch: 'Passwörter stimmen nicht überein',
|
||||
permissions_created: 'Berechtigungen für {username} erstellt',
|
||||
permissions_deleted: 'Berechtigungen für {username} gelöscht',
|
||||
permissions_updated: 'Berechtigungen für {username} geändert',
|
||||
no_permission: 'Du hast keine Berechtigung für {url}'
|
||||
}
|
||||
} satisfies Translation;
|
||||
|
||||
|
||||
@@ -22,15 +22,95 @@ const en_US = {
|
||||
change_password_body: 'After the password has been changed, you will need to log in again.',
|
||||
change_password_label: 'Old password',
|
||||
change_password_new: 'New password',
|
||||
change_password_confirm: 'Confirm password',
|
||||
toast_admin_saved: 'Admin saved',
|
||||
toast_user_saved: 'User saved',
|
||||
toast_password_changed: 'Password changed. Please login again.',
|
||||
toast_passwords_missmatch: "Passwords don't match"
|
||||
change_password_confirm: 'Confirm password'
|
||||
},
|
||||
device: {
|
||||
page_title: 'New device',
|
||||
tabs: ['Manual', 'Network Scan']
|
||||
},
|
||||
login: {
|
||||
welcome: 'Welcome',
|
||||
email_label: 'Email or Username:',
|
||||
password_label: 'Password:',
|
||||
btn_more: 'More',
|
||||
menu_title_auth_providers: 'Other Auth Providers',
|
||||
btn_login: 'Login'
|
||||
},
|
||||
settings: {
|
||||
settings_title: 'Settings',
|
||||
ping_interval_title: 'Ping interval',
|
||||
ping_interval_desc1:
|
||||
'Sets the interval in which the devices are pinged. Leave blank to use default value of <span class="badge">@every 3s</span>.',
|
||||
ping_interval_desc2:
|
||||
'Learn more about the correct syntax for cron on <a class="link" href="https://en.wikipedia.org/wiki/Cron" target="_blank">Wikipedia</a> or refer to the <a class="link" href="https://pkg.go.dev/github.com/robfig/cron/v3" target="_blank">package documentation</a>.',
|
||||
lazy_ping_title: 'Lazy ping',
|
||||
lazy_ping_desc:
|
||||
"When lazy ping is turned on, UpSnap will only ping devices if there is an active user visiting the website. If it's turned off, UpSnap will always ping devices.",
|
||||
lazy_ping_enable: 'Enable',
|
||||
website_title_title: 'Website title',
|
||||
website_title_desc: 'Sets the title of the website and in the browser tab.',
|
||||
icon_title: 'Icon',
|
||||
icon_desc: 'Set a custom favicon. Supported file types are:',
|
||||
upsnap_version: 'UpSnap version'
|
||||
},
|
||||
users: {
|
||||
page_title: 'Users',
|
||||
allow_create_devices: 'Allow {username} to create new devices and edit device groups',
|
||||
device_permissions: 'Device permissions',
|
||||
create_new_device: 'Create new device',
|
||||
read: 'Read',
|
||||
update: 'Update',
|
||||
delete: 'Delete',
|
||||
power: 'Power',
|
||||
toggle: 'Toggle',
|
||||
confirm_delete_title: 'Confirm delete',
|
||||
confirm_delete_desc: 'Are you sure you want to delete {username}?',
|
||||
create_new_user: 'Create new user',
|
||||
username: 'Username',
|
||||
password: 'Password',
|
||||
password_confirm: 'Password confirm',
|
||||
required_field: 'required field'
|
||||
},
|
||||
buttons: {
|
||||
save: 'Save',
|
||||
change: 'Change'
|
||||
delete: 'Delete',
|
||||
change: 'Change',
|
||||
reset: 'Reset',
|
||||
cancle: 'Cancle',
|
||||
add: 'Add'
|
||||
},
|
||||
welcome: {
|
||||
step1_page_title: 'Welcome to UpSnap 🥳',
|
||||
step1_setup_desc: 'Please complete the following steps to finish the setup.',
|
||||
step1_setup_btn_next: 'Next',
|
||||
step2_page_title: 'Create an admin account',
|
||||
step2_label_email: 'Email:',
|
||||
step2_label_password: 'Password:',
|
||||
step2_label_min_chars: 'min. 10 characters',
|
||||
step2_label_password_confirm: 'Password confirm:',
|
||||
step2_btn_create: 'Create',
|
||||
step3_page_title: 'You are all set! 🎉',
|
||||
step3_page_desc: 'Go ahead and add some devices to your dashboard.',
|
||||
step3_btn_done: 'Lets go!',
|
||||
not_expected_title: "I didn't expect you here! 🧐",
|
||||
not_expected_desc: 'You are already done with the setup! Nothing to do.',
|
||||
not_expected_back: 'Take me back',
|
||||
progress_step1: 'Welcome',
|
||||
progress_step2: 'Create account',
|
||||
progress_step3: 'Done'
|
||||
},
|
||||
toasts: {
|
||||
admin_saved: 'Admin saved',
|
||||
user_saved: 'User saved',
|
||||
user_created: 'User {username} created',
|
||||
user_deleted: 'User {username} deleted',
|
||||
settings_saved: 'Saved settings',
|
||||
password_changed: 'Password changed. Please login again.',
|
||||
passwords_missmatch: "Passwords don't match",
|
||||
permissions_created: 'Permissions for {username} created',
|
||||
permissions_deleted: 'Permissions for {username} deleted',
|
||||
permissions_updated: 'Permissions for {username} updated',
|
||||
no_permission: "You don't have permission to visit {url}"
|
||||
}
|
||||
} satisfies BaseTranslation;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
|
||||
/* eslint-disable */
|
||||
import type { BaseTranslation as BaseTranslationType, LocalizedString } from 'typesafe-i18n'
|
||||
import type { BaseTranslation as BaseTranslationType, LocalizedString, RequiredParams } from 'typesafe-i18n'
|
||||
|
||||
export type BaseTranslation = BaseTranslationType
|
||||
export type BaseLocale = 'en-US'
|
||||
@@ -89,32 +89,318 @@ type RootTranslation = {
|
||||
* Confirm password
|
||||
*/
|
||||
change_password_confirm: string
|
||||
}
|
||||
device: {
|
||||
/**
|
||||
* Admin saved
|
||||
* New device
|
||||
*/
|
||||
toast_admin_saved: string
|
||||
page_title: string
|
||||
tabs: {
|
||||
/**
|
||||
* Manual
|
||||
*/
|
||||
'0': string
|
||||
/**
|
||||
* Network Scan
|
||||
*/
|
||||
'1': string
|
||||
}
|
||||
}
|
||||
login: {
|
||||
/**
|
||||
* User saved
|
||||
* Welcome
|
||||
*/
|
||||
toast_user_saved: string
|
||||
welcome: string
|
||||
/**
|
||||
* Password changed. Please login again.
|
||||
* Email or Username:
|
||||
*/
|
||||
toast_password_changed: string
|
||||
email_label: string
|
||||
/**
|
||||
* Passwords don't match
|
||||
* Password:
|
||||
*/
|
||||
toast_passwords_missmatch: string
|
||||
password_label: string
|
||||
/**
|
||||
* More
|
||||
*/
|
||||
btn_more: string
|
||||
/**
|
||||
* Other Auth Providers
|
||||
*/
|
||||
menu_title_auth_providers: string
|
||||
/**
|
||||
* Login
|
||||
*/
|
||||
btn_login: string
|
||||
}
|
||||
settings: {
|
||||
/**
|
||||
* Settings
|
||||
*/
|
||||
settings_title: string
|
||||
/**
|
||||
* Ping interval
|
||||
*/
|
||||
ping_interval_title: string
|
||||
/**
|
||||
* Sets the interval in which the devices are pinged. Leave blank to use default value of <span class="badge">@every 3s</span>.
|
||||
*/
|
||||
ping_interval_desc1: string
|
||||
/**
|
||||
* Learn more about the correct syntax for cron on <a class="link" href="https://en.wikipedia.org/wiki/Cron" target="_blank">Wikipedia</a> or refer to the <a class="link" href="https://pkg.go.dev/github.com/robfig/cron/v3" target="_blank">package documentation</a>.
|
||||
*/
|
||||
ping_interval_desc2: string
|
||||
/**
|
||||
* Lazy ping
|
||||
*/
|
||||
lazy_ping_title: string
|
||||
/**
|
||||
* When lazy ping is turned on, UpSnap will only ping devices if there is an active user visiting the website. If it's turned off, UpSnap will always ping devices.
|
||||
*/
|
||||
lazy_ping_desc: string
|
||||
/**
|
||||
* Enable
|
||||
*/
|
||||
lazy_ping_enable: string
|
||||
/**
|
||||
* Website title
|
||||
*/
|
||||
website_title_title: string
|
||||
/**
|
||||
* Sets the title of the website and in the browser tab.
|
||||
*/
|
||||
website_title_desc: string
|
||||
/**
|
||||
* Icon
|
||||
*/
|
||||
icon_title: string
|
||||
/**
|
||||
* Set a custom favicon. Supported file types are:
|
||||
*/
|
||||
icon_desc: string
|
||||
/**
|
||||
* UpSnap version
|
||||
*/
|
||||
upsnap_version: string
|
||||
}
|
||||
users: {
|
||||
/**
|
||||
* Users
|
||||
*/
|
||||
page_title: string
|
||||
/**
|
||||
* Allow {username} to create new devices and edit device groups
|
||||
* @param {unknown} username
|
||||
*/
|
||||
allow_create_devices: RequiredParams<'username'>
|
||||
/**
|
||||
* Device permissions
|
||||
*/
|
||||
device_permissions: string
|
||||
/**
|
||||
* Create new device
|
||||
*/
|
||||
create_new_device: string
|
||||
/**
|
||||
* Read
|
||||
*/
|
||||
read: string
|
||||
/**
|
||||
* Update
|
||||
*/
|
||||
update: string
|
||||
/**
|
||||
* Delete
|
||||
*/
|
||||
'delete': string
|
||||
/**
|
||||
* Power
|
||||
*/
|
||||
power: string
|
||||
/**
|
||||
* Toggle
|
||||
*/
|
||||
toggle: string
|
||||
/**
|
||||
* Confirm delete
|
||||
*/
|
||||
confirm_delete_title: string
|
||||
/**
|
||||
* Are you sure you want to delete {username}?
|
||||
* @param {unknown} username
|
||||
*/
|
||||
confirm_delete_desc: RequiredParams<'username'>
|
||||
/**
|
||||
* Create new user
|
||||
*/
|
||||
create_new_user: string
|
||||
/**
|
||||
* Username
|
||||
*/
|
||||
username: string
|
||||
/**
|
||||
* Password
|
||||
*/
|
||||
password: string
|
||||
/**
|
||||
* Password confirm
|
||||
*/
|
||||
password_confirm: string
|
||||
/**
|
||||
* required field
|
||||
*/
|
||||
required_field: string
|
||||
}
|
||||
buttons: {
|
||||
/**
|
||||
* Save
|
||||
*/
|
||||
save: string
|
||||
/**
|
||||
* Delete
|
||||
*/
|
||||
'delete': string
|
||||
/**
|
||||
* Change
|
||||
*/
|
||||
change: string
|
||||
/**
|
||||
* Reset
|
||||
*/
|
||||
reset: string
|
||||
/**
|
||||
* Cancle
|
||||
*/
|
||||
cancle: string
|
||||
/**
|
||||
* Add
|
||||
*/
|
||||
add: string
|
||||
}
|
||||
welcome: {
|
||||
/**
|
||||
* Welcome to UpSnap <><EFBFBD>
|
||||
*/
|
||||
step1_page_title: string
|
||||
/**
|
||||
* Please complete the following steps to finish the setup.
|
||||
*/
|
||||
step1_setup_desc: string
|
||||
/**
|
||||
* Next
|
||||
*/
|
||||
step1_setup_btn_next: string
|
||||
/**
|
||||
* Create an admin account
|
||||
*/
|
||||
step2_page_title: string
|
||||
/**
|
||||
* Email:
|
||||
*/
|
||||
step2_label_email: string
|
||||
/**
|
||||
* Password:
|
||||
*/
|
||||
step2_label_password: string
|
||||
/**
|
||||
* min. 10 characters
|
||||
*/
|
||||
step2_label_min_chars: string
|
||||
/**
|
||||
* Password confirm:
|
||||
*/
|
||||
step2_label_password_confirm: string
|
||||
/**
|
||||
* Create
|
||||
*/
|
||||
step2_btn_create: string
|
||||
/**
|
||||
* You are all set! <><EFBFBD>
|
||||
*/
|
||||
step3_page_title: string
|
||||
/**
|
||||
* Go ahead and add some devices to your dashboard.
|
||||
*/
|
||||
step3_page_desc: string
|
||||
/**
|
||||
* Lets go!
|
||||
*/
|
||||
step3_btn_done: string
|
||||
/**
|
||||
* I didn't expect you here! <><EFBFBD>
|
||||
*/
|
||||
not_expected_title: string
|
||||
/**
|
||||
* You are already done with the setup! Nothing to do.
|
||||
*/
|
||||
not_expected_desc: string
|
||||
/**
|
||||
* Take me back
|
||||
*/
|
||||
not_expected_back: string
|
||||
/**
|
||||
* Welcome
|
||||
*/
|
||||
progress_step1: string
|
||||
/**
|
||||
* Create account
|
||||
*/
|
||||
progress_step2: string
|
||||
/**
|
||||
* Done
|
||||
*/
|
||||
progress_step3: string
|
||||
}
|
||||
toasts: {
|
||||
/**
|
||||
* Admin saved
|
||||
*/
|
||||
admin_saved: string
|
||||
/**
|
||||
* User saved
|
||||
*/
|
||||
user_saved: string
|
||||
/**
|
||||
* User {username} created
|
||||
* @param {unknown} username
|
||||
*/
|
||||
user_created: RequiredParams<'username'>
|
||||
/**
|
||||
* User {username} deleted
|
||||
* @param {unknown} username
|
||||
*/
|
||||
user_deleted: RequiredParams<'username'>
|
||||
/**
|
||||
* Saved settings
|
||||
*/
|
||||
settings_saved: string
|
||||
/**
|
||||
* Password changed. Please login again.
|
||||
*/
|
||||
password_changed: string
|
||||
/**
|
||||
* Passwords don't match
|
||||
*/
|
||||
passwords_missmatch: string
|
||||
/**
|
||||
* Permissions for {username} created
|
||||
* @param {unknown} username
|
||||
*/
|
||||
permissions_created: RequiredParams<'username'>
|
||||
/**
|
||||
* Permissions for {username} deleted
|
||||
* @param {unknown} username
|
||||
*/
|
||||
permissions_deleted: RequiredParams<'username'>
|
||||
/**
|
||||
* Permissions for {username} updated
|
||||
* @param {unknown} username
|
||||
*/
|
||||
permissions_updated: RequiredParams<'username'>
|
||||
/**
|
||||
* You don't have permission to visit {url}
|
||||
* @param {unknown} url
|
||||
*/
|
||||
no_permission: RequiredParams<'url'>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,32 +480,310 @@ export type TranslationFunctions = {
|
||||
* Confirm password
|
||||
*/
|
||||
change_password_confirm: () => LocalizedString
|
||||
}
|
||||
device: {
|
||||
/**
|
||||
* Admin saved
|
||||
* New device
|
||||
*/
|
||||
toast_admin_saved: () => LocalizedString
|
||||
page_title: () => LocalizedString
|
||||
tabs: {
|
||||
/**
|
||||
* Manual
|
||||
*/
|
||||
'0': () => LocalizedString
|
||||
/**
|
||||
* Network Scan
|
||||
*/
|
||||
'1': () => LocalizedString
|
||||
}
|
||||
}
|
||||
login: {
|
||||
/**
|
||||
* User saved
|
||||
* Welcome
|
||||
*/
|
||||
toast_user_saved: () => LocalizedString
|
||||
welcome: () => LocalizedString
|
||||
/**
|
||||
* Password changed. Please login again.
|
||||
* Email or Username:
|
||||
*/
|
||||
toast_password_changed: () => LocalizedString
|
||||
email_label: () => LocalizedString
|
||||
/**
|
||||
* Passwords don't match
|
||||
* Password:
|
||||
*/
|
||||
toast_passwords_missmatch: () => LocalizedString
|
||||
password_label: () => LocalizedString
|
||||
/**
|
||||
* More
|
||||
*/
|
||||
btn_more: () => LocalizedString
|
||||
/**
|
||||
* Other Auth Providers
|
||||
*/
|
||||
menu_title_auth_providers: () => LocalizedString
|
||||
/**
|
||||
* Login
|
||||
*/
|
||||
btn_login: () => LocalizedString
|
||||
}
|
||||
settings: {
|
||||
/**
|
||||
* Settings
|
||||
*/
|
||||
settings_title: () => LocalizedString
|
||||
/**
|
||||
* Ping interval
|
||||
*/
|
||||
ping_interval_title: () => LocalizedString
|
||||
/**
|
||||
* Sets the interval in which the devices are pinged. Leave blank to use default value of <span class="badge">@every 3s</span>.
|
||||
*/
|
||||
ping_interval_desc1: () => LocalizedString
|
||||
/**
|
||||
* Learn more about the correct syntax for cron on <a class="link" href="https://en.wikipedia.org/wiki/Cron" target="_blank">Wikipedia</a> or refer to the <a class="link" href="https://pkg.go.dev/github.com/robfig/cron/v3" target="_blank">package documentation</a>.
|
||||
*/
|
||||
ping_interval_desc2: () => LocalizedString
|
||||
/**
|
||||
* Lazy ping
|
||||
*/
|
||||
lazy_ping_title: () => LocalizedString
|
||||
/**
|
||||
* When lazy ping is turned on, UpSnap will only ping devices if there is an active user visiting the website. If it's turned off, UpSnap will always ping devices.
|
||||
*/
|
||||
lazy_ping_desc: () => LocalizedString
|
||||
/**
|
||||
* Enable
|
||||
*/
|
||||
lazy_ping_enable: () => LocalizedString
|
||||
/**
|
||||
* Website title
|
||||
*/
|
||||
website_title_title: () => LocalizedString
|
||||
/**
|
||||
* Sets the title of the website and in the browser tab.
|
||||
*/
|
||||
website_title_desc: () => LocalizedString
|
||||
/**
|
||||
* Icon
|
||||
*/
|
||||
icon_title: () => LocalizedString
|
||||
/**
|
||||
* Set a custom favicon. Supported file types are:
|
||||
*/
|
||||
icon_desc: () => LocalizedString
|
||||
/**
|
||||
* UpSnap version
|
||||
*/
|
||||
upsnap_version: () => LocalizedString
|
||||
}
|
||||
users: {
|
||||
/**
|
||||
* Users
|
||||
*/
|
||||
page_title: () => LocalizedString
|
||||
/**
|
||||
* Allow {username} to create new devices and edit device groups
|
||||
*/
|
||||
allow_create_devices: (arg: { username: unknown }) => LocalizedString
|
||||
/**
|
||||
* Device permissions
|
||||
*/
|
||||
device_permissions: () => LocalizedString
|
||||
/**
|
||||
* Create new device
|
||||
*/
|
||||
create_new_device: () => LocalizedString
|
||||
/**
|
||||
* Read
|
||||
*/
|
||||
read: () => LocalizedString
|
||||
/**
|
||||
* Update
|
||||
*/
|
||||
update: () => LocalizedString
|
||||
/**
|
||||
* Delete
|
||||
*/
|
||||
'delete': () => LocalizedString
|
||||
/**
|
||||
* Power
|
||||
*/
|
||||
power: () => LocalizedString
|
||||
/**
|
||||
* Toggle
|
||||
*/
|
||||
toggle: () => LocalizedString
|
||||
/**
|
||||
* Confirm delete
|
||||
*/
|
||||
confirm_delete_title: () => LocalizedString
|
||||
/**
|
||||
* Are you sure you want to delete {username}?
|
||||
*/
|
||||
confirm_delete_desc: (arg: { username: unknown }) => LocalizedString
|
||||
/**
|
||||
* Create new user
|
||||
*/
|
||||
create_new_user: () => LocalizedString
|
||||
/**
|
||||
* Username
|
||||
*/
|
||||
username: () => LocalizedString
|
||||
/**
|
||||
* Password
|
||||
*/
|
||||
password: () => LocalizedString
|
||||
/**
|
||||
* Password confirm
|
||||
*/
|
||||
password_confirm: () => LocalizedString
|
||||
/**
|
||||
* required field
|
||||
*/
|
||||
required_field: () => LocalizedString
|
||||
}
|
||||
buttons: {
|
||||
/**
|
||||
* Save
|
||||
*/
|
||||
save: () => LocalizedString
|
||||
/**
|
||||
* Delete
|
||||
*/
|
||||
'delete': () => LocalizedString
|
||||
/**
|
||||
* Change
|
||||
*/
|
||||
change: () => LocalizedString
|
||||
/**
|
||||
* Reset
|
||||
*/
|
||||
reset: () => LocalizedString
|
||||
/**
|
||||
* Cancle
|
||||
*/
|
||||
cancle: () => LocalizedString
|
||||
/**
|
||||
* Add
|
||||
*/
|
||||
add: () => LocalizedString
|
||||
}
|
||||
welcome: {
|
||||
/**
|
||||
* Welcome to UpSnap 🥳
|
||||
*/
|
||||
step1_page_title: () => LocalizedString
|
||||
/**
|
||||
* Please complete the following steps to finish the setup.
|
||||
*/
|
||||
step1_setup_desc: () => LocalizedString
|
||||
/**
|
||||
* Next
|
||||
*/
|
||||
step1_setup_btn_next: () => LocalizedString
|
||||
/**
|
||||
* Create an admin account
|
||||
*/
|
||||
step2_page_title: () => LocalizedString
|
||||
/**
|
||||
* Email:
|
||||
*/
|
||||
step2_label_email: () => LocalizedString
|
||||
/**
|
||||
* Password:
|
||||
*/
|
||||
step2_label_password: () => LocalizedString
|
||||
/**
|
||||
* min. 10 characters
|
||||
*/
|
||||
step2_label_min_chars: () => LocalizedString
|
||||
/**
|
||||
* Password confirm:
|
||||
*/
|
||||
step2_label_password_confirm: () => LocalizedString
|
||||
/**
|
||||
* Create
|
||||
*/
|
||||
step2_btn_create: () => LocalizedString
|
||||
/**
|
||||
* You are all set! 🎉
|
||||
*/
|
||||
step3_page_title: () => LocalizedString
|
||||
/**
|
||||
* Go ahead and add some devices to your dashboard.
|
||||
*/
|
||||
step3_page_desc: () => LocalizedString
|
||||
/**
|
||||
* Lets go!
|
||||
*/
|
||||
step3_btn_done: () => LocalizedString
|
||||
/**
|
||||
* I didn't expect you here! 🧐
|
||||
*/
|
||||
not_expected_title: () => LocalizedString
|
||||
/**
|
||||
* You are already done with the setup! Nothing to do.
|
||||
*/
|
||||
not_expected_desc: () => LocalizedString
|
||||
/**
|
||||
* Take me back
|
||||
*/
|
||||
not_expected_back: () => LocalizedString
|
||||
/**
|
||||
* Welcome
|
||||
*/
|
||||
progress_step1: () => LocalizedString
|
||||
/**
|
||||
* Create account
|
||||
*/
|
||||
progress_step2: () => LocalizedString
|
||||
/**
|
||||
* Done
|
||||
*/
|
||||
progress_step3: () => LocalizedString
|
||||
}
|
||||
toasts: {
|
||||
/**
|
||||
* Admin saved
|
||||
*/
|
||||
admin_saved: () => LocalizedString
|
||||
/**
|
||||
* User saved
|
||||
*/
|
||||
user_saved: () => LocalizedString
|
||||
/**
|
||||
* User {username} created
|
||||
*/
|
||||
user_created: (arg: { username: unknown }) => LocalizedString
|
||||
/**
|
||||
* User {username} deleted
|
||||
*/
|
||||
user_deleted: (arg: { username: unknown }) => LocalizedString
|
||||
/**
|
||||
* Saved settings
|
||||
*/
|
||||
settings_saved: () => LocalizedString
|
||||
/**
|
||||
* Password changed. Please login again.
|
||||
*/
|
||||
password_changed: () => LocalizedString
|
||||
/**
|
||||
* Passwords don't match
|
||||
*/
|
||||
passwords_missmatch: () => LocalizedString
|
||||
/**
|
||||
* Permissions for {username} created
|
||||
*/
|
||||
permissions_created: (arg: { username: unknown }) => LocalizedString
|
||||
/**
|
||||
* Permissions for {username} deleted
|
||||
*/
|
||||
permissions_deleted: (arg: { username: unknown }) => LocalizedString
|
||||
/**
|
||||
* Permissions for {username} updated
|
||||
*/
|
||||
permissions_updated: (arg: { username: unknown }) => LocalizedString
|
||||
/**
|
||||
* You don't have permission to visit {url}
|
||||
*/
|
||||
no_permission: (arg: { url: unknown }) => LocalizedString
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
$pocketbase.admins
|
||||
.update($pocketbase.authStore.model.id, { avatar: newAvatar })
|
||||
.then(() => {
|
||||
toast.success($LL.account.toast_admin_saved());
|
||||
toast.success($LL.toasts.admin_saved());
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.error(err.message);
|
||||
@@ -69,7 +69,7 @@
|
||||
.collection('users')
|
||||
.update($pocketbase.authStore.model.id, { avatar: newAvatar })
|
||||
.then(() => {
|
||||
toast.success($LL.account.toast_user_saved());
|
||||
toast.success($LL.toasts.user_saved());
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.error(err.message);
|
||||
@@ -93,7 +93,7 @@
|
||||
)
|
||||
.then(async (data) => {
|
||||
if (data.ok) {
|
||||
toast.success($LL.account.toast_password_changed());
|
||||
toast.success($LL.toasts.password_changed());
|
||||
$pocketbase.authStore.clear();
|
||||
goto('/login');
|
||||
} else {
|
||||
@@ -101,7 +101,7 @@
|
||||
if (j?.data?.password?.message) {
|
||||
toast.error(j?.data?.password?.message);
|
||||
} else if (j?.data?.passwordConfirm?.message) {
|
||||
toast.error($LL.account.toast_passwords_missmatch());
|
||||
toast.error($LL.toasts.passwords_missmatch());
|
||||
} else if (j.data?.oldPassword?.message) {
|
||||
toast.error(j.data.oldPassword.message);
|
||||
} else {
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
import { page } from '$app/stores';
|
||||
import DeviceForm from '$lib/components/DeviceForm.svelte';
|
||||
import PageLoading from '$lib/components/PageLoading.svelte';
|
||||
import LL from '$lib/i18n/i18n-svelte';
|
||||
import { permission, pocketbase } from '$lib/stores/pocketbase';
|
||||
import type { Device, Port } from '$lib/types/device';
|
||||
import toast from 'svelte-french-toast';
|
||||
|
||||
$: if (Object.hasOwn($permission, 'update')) {
|
||||
if (!$pocketbase.authStore.isAdmin && !$permission.update.includes($page.params.id)) {
|
||||
toast(`You don't have permission to visit ${$page.url.pathname}`, {
|
||||
toast($LL.toasts.no_permission({ url: $page.url.pathname }), {
|
||||
icon: '⛔'
|
||||
});
|
||||
goto('/');
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { page } from '$app/stores';
|
||||
import DeviceForm from '$lib/components/DeviceForm.svelte';
|
||||
import NetworkScan from '$lib/components/NetworkScan.svelte';
|
||||
import LL from '$lib/i18n/i18n-svelte';
|
||||
import { permission, pocketbase } from '$lib/stores/pocketbase';
|
||||
import type { Device, Port } from '$lib/types/device';
|
||||
import { faBinoculars, faWrench } from '@fortawesome/free-solid-svg-icons';
|
||||
@@ -18,7 +19,7 @@
|
||||
|
||||
$: if (Object.hasOwn($permission, 'create')) {
|
||||
if (!$pocketbase.authStore.isAdmin && !$permission.create) {
|
||||
toast(`You don't have permission to visit ${$page.url.pathname}`, {
|
||||
toast($LL.toasts.no_permission({ url: $page.url.pathname }), {
|
||||
icon: '⛔'
|
||||
});
|
||||
goto('/');
|
||||
@@ -28,11 +29,13 @@
|
||||
let tabs = [
|
||||
{
|
||||
name: 'manual',
|
||||
ll_name: $LL.device.tabs[0](),
|
||||
icon: faWrench,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
name: 'network scan',
|
||||
name: 'scan',
|
||||
ll_name: $LL.device.tabs[1](),
|
||||
icon: faBinoculars,
|
||||
show: $pocketbase.authStore.isAdmin
|
||||
}
|
||||
@@ -40,17 +43,14 @@
|
||||
let activeTab = 'manual';
|
||||
</script>
|
||||
|
||||
<h1 class="text-3xl font-bold mb-8">New device</h1>
|
||||
<h1 class="text-3xl font-bold mb-8">{$LL.device.page_title()}</h1>
|
||||
<div class="flex justify-center mb-6">
|
||||
<ul class="menu menu-horizontal bg-base-300 rounded-box gap-1">
|
||||
{#each tabs as tab}
|
||||
{#if tab.show}
|
||||
<li>
|
||||
<button
|
||||
class="capitalize"
|
||||
class:active={activeTab === tab.name}
|
||||
on:click={() => (activeTab = tab.name)}
|
||||
>{tab.name} <Fa icon={tab.icon} class="ms-2" /></button
|
||||
<button class:active={activeTab === tab.name} on:click={() => (activeTab = tab.name)}
|
||||
>{tab.ll_name} <Fa icon={tab.icon} class="ms-2" /></button
|
||||
>
|
||||
</li>
|
||||
{/if}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { toggleVisibility } from '$lib/helpers/forms';
|
||||
import LL from '$lib/i18n/i18n-svelte';
|
||||
import { pocketbase } from '$lib/stores/pocketbase';
|
||||
import { settingsPub } from '$lib/stores/settings';
|
||||
import { faEye, faLockOpen, faQuestionCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
@@ -62,11 +63,11 @@
|
||||
{/if}
|
||||
<div class="flex flex-row gap-4">
|
||||
<figure class="w-16"><img src="/gopher.svg" alt="Gopher" /></figure>
|
||||
<h2 class="card-title">Welcome</h2>
|
||||
<h2 class="card-title">{$LL.login.welcome()}</h2>
|
||||
</div>
|
||||
<form class="form-control w-full" on:submit|preventDefault={tryAdminThenUser}>
|
||||
<label class="label" for="email">
|
||||
<span class="label-text">Email or Username:</span>
|
||||
<span class="label-text">{$LL.login.email_label()}</span>
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
@@ -76,7 +77,7 @@
|
||||
bind:value={form.email}
|
||||
/>
|
||||
<label class="label" for="password">
|
||||
<span class="label-text">Password:</span>
|
||||
<span class="label-text">{$LL.login.password_label()}</span>
|
||||
</label>
|
||||
<label class="relative block">
|
||||
<div
|
||||
@@ -99,16 +100,18 @@
|
||||
</label>
|
||||
<div class="card-actions mt-4">
|
||||
<div class="dropdown">
|
||||
<label tabindex="-1" class="btn btn-neutral" for="other-providers">Other</label>
|
||||
<label tabindex="-1" class="btn btn-neutral" for="other-providers"
|
||||
>{$LL.login.btn_more()}</label
|
||||
>
|
||||
<ul
|
||||
id="other-providers"
|
||||
tabindex="-1"
|
||||
class="dropdown-content z-[1] menu p-2 shadow bg-base-200 rounded-box w-56"
|
||||
>
|
||||
<li class="menu-title flex flex-row gap-2 items-center">
|
||||
Other Auth Providers <a
|
||||
href="https://github.com/seriousm4x/UpSnap/wiki/Auth-providers"
|
||||
target="_blank"><Fa icon={faQuestionCircle} /></a
|
||||
{$LL.login.menu_title_auth_providers()}
|
||||
<a href="https://github.com/seriousm4x/UpSnap/wiki/Auth-providers" target="_blank"
|
||||
><Fa icon={faQuestionCircle} /></a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
@@ -117,7 +120,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
<button class="btn btn-primary ms-auto" type="submit"
|
||||
>Login <Fa icon={faLockOpen} /></button
|
||||
>{$LL.login.btn_login()} <Fa icon={faLockOpen} /></button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { page } from '$app/stores';
|
||||
import { PUBLIC_VERSION } from '$env/static/public';
|
||||
import PageLoading from '$lib/components/PageLoading.svelte';
|
||||
import LL from '$lib/i18n/i18n-svelte';
|
||||
import { backendUrl, pocketbase } from '$lib/stores/pocketbase';
|
||||
import { settingsPriv, settingsPub } from '$lib/stores/settings';
|
||||
import type { SettingsPrivate, SettingsPublic } from '$lib/types/settings';
|
||||
@@ -18,7 +19,7 @@
|
||||
|
||||
onMount(() => {
|
||||
if (!$pocketbase.authStore.isAdmin) {
|
||||
toast(`You don't have permission to visit ${$page.url.pathname}`, {
|
||||
toast($LL.toasts.no_permission({ url: $page.url.pathname }), {
|
||||
icon: '⛔'
|
||||
});
|
||||
goto('/');
|
||||
@@ -76,7 +77,7 @@
|
||||
.collection('settings_private')
|
||||
.update(settingsPrivClone.id, settingsPrivClone)
|
||||
.then((res) => {
|
||||
toast.success('Saved settings');
|
||||
toast.success($LL.toasts.settings_saved());
|
||||
settingsPriv.set(res as SettingsPrivate);
|
||||
goto('/');
|
||||
})
|
||||
@@ -89,23 +90,21 @@
|
||||
{#if settingsPubClone === undefined || settingsPrivClone === undefined}
|
||||
<PageLoading />
|
||||
{:else}
|
||||
<h1 class="text-3xl font-bold mb-8">Settings</h1>
|
||||
<h1 class="text-3xl font-bold mb-8">{$LL.settings.settings_title()}</h1>
|
||||
<form on:submit|preventDefault={save}>
|
||||
<div class="card w-full bg-base-300 shadow-xl mt-6">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">Ping interval</h2>
|
||||
<h2 class="card-title">{$LL.settings.ping_interval_title()}</h2>
|
||||
<p class="mt-2">
|
||||
Sets the interval in which the devices are pinged. Leave blank to use default value of <span
|
||||
class="badge">@every 3s</span
|
||||
>.
|
||||
<!-- eslint-disable svelte/no-at-html-tags -->
|
||||
{@html $LL.settings.ping_interval_desc1()}
|
||||
</p>
|
||||
<p>
|
||||
Learn more about the correct syntax for cron on
|
||||
<a target="_blank" class="link" href="https://en.wikipedia.org/wiki/Cron">Wikipedia</a>
|
||||
or refer to the
|
||||
<a target="_blank" class="link" href="https://pkg.go.dev/github.com/robfig/cron/v3"
|
||||
>package documentation</a
|
||||
>.
|
||||
<!-- Usage of @html is not a nice way to do this, but it's safe in this case. If someones finds
|
||||
a good solution to avoid @html but still be able to use multiple links in a single sentence,
|
||||
please create a pr/issue. -->
|
||||
<!-- eslint-disable svelte/no-at-html-tags -->
|
||||
{@html $LL.settings.ping_interval_desc2()}
|
||||
</p>
|
||||
<div class="form-control w-full mt-2">
|
||||
<input
|
||||
@@ -115,10 +114,9 @@
|
||||
bind:value={settingsPrivClone.interval}
|
||||
/>
|
||||
</div>
|
||||
<h2 class="card-title mt-2">Lazy ping</h2>
|
||||
<h2 class="card-title mt-2">{$LL.settings.lazy_ping_title()}</h2>
|
||||
<p class="mt-2">
|
||||
When lazy ping is turned on, UpSnap will only ping devices if there is an active user
|
||||
visiting the website. If it's turned off, UpSnap will always ping devices.
|
||||
{$LL.settings.lazy_ping_desc()}
|
||||
</p>
|
||||
<div class="form-control w-fit">
|
||||
<label class="label cursor-pointer gap-2">
|
||||
@@ -127,15 +125,15 @@
|
||||
class="checkbox checkbox-primary"
|
||||
bind:checked={settingsPrivClone.lazy_ping}
|
||||
/>
|
||||
<span class="label-text">Enable</span>
|
||||
<span class="label-text">{$LL.settings.lazy_ping_enable()}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card w-full bg-base-300 shadow-xl mt-6">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">Website title</h2>
|
||||
<p class="my-2">Sets the title of the website and in the browser tab.</p>
|
||||
<h2 class="card-title">{$LL.settings.website_title_title()}</h2>
|
||||
<p class="my-2">{$LL.settings.website_title_desc()}</p>
|
||||
<div class="form-control w-full">
|
||||
<input
|
||||
type="text"
|
||||
@@ -148,12 +146,12 @@
|
||||
</div>
|
||||
<div class="card w-full bg-base-300 shadow-xl mt-6">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">Icon</h2>
|
||||
<h2 class="card-title">{$LL.settings.icon_title()}</h2>
|
||||
<p class="my-2">
|
||||
Set a custom favicon. Supported file types are
|
||||
<span class="badge">.ico</span>, <span class="badge">.png</span>,
|
||||
<span class="badge">.svg</span>, <span class="badge">.gif</span> and
|
||||
<span class="badge">.jpg/.jpeg</span>.
|
||||
{$LL.settings.icon_desc()}
|
||||
<span class="badge">.ico</span> <span class="badge">.png</span>
|
||||
<span class="badge">.svg</span> <span class="badge">.gif</span>
|
||||
<span class="badge">.jpg/.jpeg</span>
|
||||
</p>
|
||||
<div>
|
||||
<img
|
||||
@@ -175,22 +173,23 @@
|
||||
<button
|
||||
class="btn btn-outline btn-error"
|
||||
on:click={() => resetFavicon()}
|
||||
on:keydown={() => resetFavicon()}>Reset</button
|
||||
on:keydown={() => resetFavicon()}>{$LL.buttons.reset()}</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-actions justify-end mt-6">
|
||||
<button class="btn btn-success" type="submit"><Fa icon={faSave} />Save</button>
|
||||
<button class="btn btn-success" type="submit"><Fa icon={faSave} />{$LL.buttons.save()}</button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
<div class="container mx-auto text-center mt-6">
|
||||
{#if PUBLIC_VERSION === ''}
|
||||
UpSnap version: (untracked)
|
||||
{$LL.settings.upsnap_version()}: (untracked)
|
||||
{:else}
|
||||
UpSnap version: <a
|
||||
href="https://github.com/seriousm4x/UpSnap/releases/tag/{PUBLIC_VERSION}"
|
||||
class="link">{PUBLIC_VERSION}</a
|
||||
{$LL.settings.upsnap_version()}:
|
||||
<a href="https://github.com/seriousm4x/UpSnap/releases/tag/{PUBLIC_VERSION}" class="link"
|
||||
>{PUBLIC_VERSION}</a
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import PageLoading from '$lib/components/PageLoading.svelte';
|
||||
import LL from '$lib/i18n/i18n-svelte';
|
||||
import { backendUrl, pocketbase } from '$lib/stores/pocketbase';
|
||||
import type { Device } from '$lib/types/device';
|
||||
import type { Permission } from '$lib/types/permission';
|
||||
import type { User } from '$lib/types/user';
|
||||
import { faPlus, faSave, faTrash } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faPlus, faRetweet, faSave, faTrash } from '@fortawesome/free-solid-svg-icons';
|
||||
import { onMount } from 'svelte';
|
||||
import Fa from 'svelte-fa';
|
||||
import toast from 'svelte-french-toast';
|
||||
@@ -33,7 +34,7 @@
|
||||
|
||||
onMount(() => {
|
||||
if (!$pocketbase.authStore.isAdmin) {
|
||||
toast(`You don't have permission to visit ${$page.url.pathname}`, {
|
||||
toast($LL.toasts.no_permission({ url: $page.url.pathname }), {
|
||||
icon: '⛔'
|
||||
});
|
||||
goto('/');
|
||||
@@ -58,7 +59,7 @@
|
||||
.collection('users')
|
||||
.create(newUser)
|
||||
.then((data) => {
|
||||
toast.success(`User ${data.username} created`);
|
||||
toast.success($LL.toasts.user_created({ username: data.username }));
|
||||
newUser.username = '';
|
||||
newUser.password = '';
|
||||
newUser.passwordConfirm = '';
|
||||
@@ -74,14 +75,14 @@
|
||||
.collection('users')
|
||||
.delete(user.id)
|
||||
.then(async () => {
|
||||
toast.success(`User ${user.username} deleted`);
|
||||
toast.success($LL.toasts.user_deleted({ username: user.username }));
|
||||
let permission = permissions.find((perm) => perm.user === user.id);
|
||||
if (permission?.id !== undefined) {
|
||||
await $pocketbase
|
||||
.collection('permissions')
|
||||
.delete(permission.id)
|
||||
.then(() => {
|
||||
toast.success(`Permissions for ${user.username} deleted`);
|
||||
toast.success($LL.toasts.permissions_deleted({ username: user.username }));
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.error(err.message);
|
||||
@@ -130,7 +131,7 @@
|
||||
// if (i > -1) {
|
||||
// permissions[i] = data as Permission;
|
||||
// }
|
||||
toast.success(`Permissions for ${user.username} created`);
|
||||
toast.success($LL.toasts.permissions_created({ username: user.username }));
|
||||
reload();
|
||||
})
|
||||
.catch((err) => {
|
||||
@@ -142,7 +143,7 @@
|
||||
.collection('permissions')
|
||||
.update(permission.id, permission)
|
||||
.then(() => {
|
||||
toast.success(`Permissions for ${user.username} updated`);
|
||||
toast.success($LL.toasts.permissions_updated({ username: user.username }));
|
||||
reload();
|
||||
})
|
||||
.catch((err) => {
|
||||
@@ -179,7 +180,7 @@
|
||||
{#await Promise.all([getUsersPromise, getPermissionsPromise, getDevicesPromise])}
|
||||
<PageLoading />
|
||||
{:then}
|
||||
<h1 class="text-3xl font-bold mb-8">Users</h1>
|
||||
<h1 class="text-3xl font-bold mb-8">{$LL.users.page_title()}</h1>
|
||||
{#each users as user, index}
|
||||
<form on:submit|preventDefault={() => save(user)}>
|
||||
<div class="card w-full bg-base-300 shadow-xl mt-6">
|
||||
@@ -203,37 +204,37 @@
|
||||
bind:checked={permission.create}
|
||||
class="checkbox checked:checkbox-primary"
|
||||
/>
|
||||
<span class="label-text font-bold"
|
||||
>Allow {user.username} to create new devices and edit device groups?</span
|
||||
>
|
||||
{$LL.users.allow_create_devices({ username: user.username })}
|
||||
</label>
|
||||
</div>
|
||||
{/each}
|
||||
<div class="collapse collapse-arrow bg-base-200">
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-xl font-medium">Device permissions</div>
|
||||
<div class="collapse-title text-xl font-medium">{$LL.users.device_permissions()}</div>
|
||||
<div class="collapse-content">
|
||||
{#if devices.length === 0}
|
||||
<p>No devices here. <a href="/device/new" class="link">Create new device</a></p>
|
||||
<p>
|
||||
{$LL.home.message_no_devices()}
|
||||
<a href="/device/new" class="link">{$LL.users.create_new_device()}</a>
|
||||
</p>
|
||||
{:else}
|
||||
<div class="grid grid-cols-5 gap-4 justify-items-center">
|
||||
<div class="font-bold" />
|
||||
<div class="font-bold">Read</div>
|
||||
<div class="font-bold">Update</div>
|
||||
<div class="font-bold">Delete</div>
|
||||
<div class="font-bold">Power</div>
|
||||
<div class="grid grid-cols-4 md:grid-cols-5 gap-4 justify-items-center">
|
||||
<div class="font-bold md:col-start-2">{$LL.users.read()}</div>
|
||||
<div class="font-bold">{$LL.users.update()}</div>
|
||||
<div class="font-bold">{$LL.users.delete()}</div>
|
||||
<div class="font-bold">{$LL.users.power()}</div>
|
||||
{#each devices as device}
|
||||
<hr class="col-span-full w-full border-b-1 opacity-30 border-neutral" />
|
||||
{#each permissions.filter((perm) => perm.user === user.id) as permission}
|
||||
<div
|
||||
class="flex flex-row flex-wrap gap-2 place-self-start break-all col-span-full sm:col-span-1"
|
||||
class="flex flex-row flex-wrap gap-2 place-self-start break-all col-span-full md:col-span-1"
|
||||
>
|
||||
<span class="font-bold">{device.name}</span>
|
||||
<span class="badge hidden sm:block">{device.ip}</span>
|
||||
<span class="badge hidden md:block">{device.ip}</span>
|
||||
</div>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checked:checkbox-primary col-start-2"
|
||||
class="checkbox checked:checkbox-primary md:col-start-2"
|
||||
bind:group={permission.read}
|
||||
value={device.id}
|
||||
/>
|
||||
@@ -258,32 +259,48 @@
|
||||
{/each}
|
||||
{/each}
|
||||
<button
|
||||
class="btn btn-sm btn-neutral col-start-2"
|
||||
class="btn btn-sm btn-neutral md:col-start-2"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
toggleAllPermissions(user, 'read');
|
||||
}}>Toggle</button
|
||||
}}
|
||||
><span class="hidden md:block">{$LL.users.toggle()}</span><Fa
|
||||
icon={faRetweet}
|
||||
size="1.5x"
|
||||
/></button
|
||||
>
|
||||
<button
|
||||
class=" btn btn-sm btn-neutral"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
toggleAllPermissions(user, 'update');
|
||||
}}>Toggle</button
|
||||
}}
|
||||
><span class="hidden md:block">{$LL.users.toggle()}</span><Fa
|
||||
icon={faRetweet}
|
||||
size="1.5x"
|
||||
/></button
|
||||
>
|
||||
<button
|
||||
class=" btn btn-sm btn-neutral"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
toggleAllPermissions(user, 'delete');
|
||||
}}>Toggle</button
|
||||
}}
|
||||
><span class="hidden md:block">{$LL.users.toggle()}</span><Fa
|
||||
icon={faRetweet}
|
||||
size="1.5x"
|
||||
/></button
|
||||
>
|
||||
<button
|
||||
class=" btn btn-sm btn-neutral"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
toggleAllPermissions(user, 'power');
|
||||
}}>Toggle</button
|
||||
}}
|
||||
><span class="hidden md:block">{$LL.users.toggle()}</span><Fa
|
||||
icon={faRetweet}
|
||||
size="1.5x"
|
||||
/></button
|
||||
>
|
||||
</div>
|
||||
<div class="mt-4 flex flex-row flex-wrap gap-4 justify-end"></div>
|
||||
@@ -294,9 +311,11 @@
|
||||
<button
|
||||
class="join-item btn btn-error"
|
||||
type="button"
|
||||
on:click={() => deleteModal.showModal()}><Fa icon={faTrash} />Delete</button
|
||||
on:click={() => deleteModal.showModal()}
|
||||
><Fa icon={faTrash} />{$LL.buttons.delete()}</button
|
||||
>
|
||||
<button class="join-item btn btn-success" type="submit"><Fa icon={faSave} />Save</button
|
||||
<button class="join-item btn btn-success" type="submit"
|
||||
><Fa icon={faSave} />{$LL.buttons.save()}</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
@@ -304,31 +323,33 @@
|
||||
</form>
|
||||
<dialog class="modal" bind:this={deleteModal}>
|
||||
<form method="dialog" class="modal-box">
|
||||
<h3 class="font-bold text-lg">Confirm delete</h3>
|
||||
<p class="py-4">Are you sure you want to delete <strong>{user.username}</strong>?</p>
|
||||
<h3 class="font-bold text-lg">{$LL.users.confirm_delete_title()}</h3>
|
||||
<p class="py-4">{$LL.users.confirm_delete_desc({ username: user.username })}</p>
|
||||
<div class="modal-action">
|
||||
<button class="btn">Cancle</button>
|
||||
<button class="btn btn-error" on:click={() => deleteUser(user)}>Delete</button>
|
||||
<button class="btn">{$LL.buttons.cancle()}</button>
|
||||
<button class="btn btn-error" on:click={() => deleteUser(user)}
|
||||
>{$LL.buttons.delete()}</button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
</dialog>
|
||||
{/each}
|
||||
<div class="card w-full bg-base-300 shadow-xl mt-6">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">Create new user</h2>
|
||||
<h2 class="card-title">{$LL.users.create_new_user()}</h2>
|
||||
<form on:submit|preventDefault={createUser}>
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
<div class="form-control w-full max-w-xs">
|
||||
<label class="label" for="username">
|
||||
<div class="label-text">
|
||||
<span>Username</span>
|
||||
<span>{$LL.users.username()}</span>
|
||||
<span class="text-error">*</span>
|
||||
</div>
|
||||
</label>
|
||||
<input
|
||||
id="username"
|
||||
type="text"
|
||||
placeholder="Username"
|
||||
placeholder={$LL.users.username()}
|
||||
class="input input-bordered w-full max-w-xs"
|
||||
required
|
||||
bind:value={newUser.username}
|
||||
@@ -337,14 +358,14 @@
|
||||
<div class="form-control w-full max-w-xs">
|
||||
<label class="label" for="password">
|
||||
<div class="label-text">
|
||||
<span>Password</span>
|
||||
<span>{$LL.users.password()}</span>
|
||||
<span class="text-error">*</span>
|
||||
</div>
|
||||
</label>
|
||||
<input
|
||||
id="password"
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
placeholder={$LL.users.password()}
|
||||
class="input input-bordered w-full max-w-xs"
|
||||
minlength="5"
|
||||
maxlength="72"
|
||||
@@ -355,14 +376,14 @@
|
||||
<div class="form-control w-full max-w-xs">
|
||||
<label class="label" for="passwordConfirm">
|
||||
<div class="label-text">
|
||||
<span>Password confirm</span>
|
||||
<span>{$LL.users.password_confirm()}</span>
|
||||
<span class="text-error">*</span>
|
||||
</div>
|
||||
</label>
|
||||
<input
|
||||
id="passwordConfirm"
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
placeholder={$LL.users.password_confirm()}
|
||||
class="input input-bordered w-full max-w-xs"
|
||||
minlength="5"
|
||||
maxlength="72"
|
||||
@@ -371,9 +392,11 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span class="badge text-error mt-4 self-center">* required field</span>
|
||||
<span class="badge text-error mt-4 self-center">* {$LL.users.required_field()}</span>
|
||||
<div class="card-actions justify-end">
|
||||
<button type="submit" class="btn btn-success mt-2"><Fa icon={faPlus} />Add</button>
|
||||
<button type="submit" class="btn btn-success mt-2"
|
||||
><Fa icon={faPlus} />{$LL.buttons.add()}</button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { toggleVisibility } from '$lib/helpers/forms';
|
||||
import LL from '$lib/i18n/i18n-svelte';
|
||||
import { pocketbase } from '$lib/stores/pocketbase';
|
||||
import { settingsPub } from '$lib/stores/settings';
|
||||
import { faArrowRight, faEye } from '@fortawesome/free-solid-svg-icons';
|
||||
@@ -45,7 +46,7 @@
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.data?.data?.passwordConfirm?.message) {
|
||||
toast.error("Passwords don't match");
|
||||
toast.error($LL.toasts.passwords_missmatch());
|
||||
} else if (err.data?.data?.email?.message) {
|
||||
toast.error(err.data.data.email.message);
|
||||
} else {
|
||||
@@ -61,20 +62,22 @@
|
||||
{#if $settingsPub?.setup_completed}
|
||||
<figure class="w-72 mx-auto pt-6"><img src="/gopher.svg" alt="Gopher" /></figure>
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">I didn't expect you here! 🧐</h2>
|
||||
<p>You are already done with the setup! Nothing to do.</p>
|
||||
<h2 class="card-title">{$LL.welcome.not_expected_title()}</h2>
|
||||
<p>{$LL.welcome.not_expected_desc()}</p>
|
||||
<div class="card-actions justify-end">
|
||||
<button class="btn btn-primary" on:click={() => goto('/')}>Take me back</button>
|
||||
<button class="btn btn-primary" on:click={() => goto('/')}
|
||||
>{$LL.welcome.not_expected_back()}</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{:else if stepsCompleted === 0}
|
||||
<figure class="w-44 mx-auto pt-6"><img src="/gopher.svg" alt="Gopher" /></figure>
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">Welcome to UpSnap 🥳</h2>
|
||||
<p>Please complete the following steps to finish the setup.</p>
|
||||
<h2 class="card-title">{$LL.welcome.step1_page_title()}</h2>
|
||||
<p>{$LL.welcome.step1_setup_desc()}</p>
|
||||
<div class="card-actions justify-end">
|
||||
<button class="btn btn-primary" on:click={() => (stepsCompleted = 1)}
|
||||
>Next <Fa icon={faArrowRight} /></button
|
||||
>{$LL.welcome.step1_setup_btn_next()} <Fa icon={faArrowRight} /></button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
@@ -82,11 +85,11 @@
|
||||
<div class="card-body">
|
||||
<div class="flex flex-row gap-4">
|
||||
<figure class="w-16"><img src="/gopher.svg" alt="Gopher" /></figure>
|
||||
<h2 class="card-title">Create an admin account</h2>
|
||||
<h2 class="card-title">{$LL.welcome.step2_page_title()}</h2>
|
||||
</div>
|
||||
<form class="form-control w-full" on:submit|preventDefault={register}>
|
||||
<label class="label" for="email">
|
||||
<span class="label-text">Email:</span>
|
||||
<span class="label-text">{$LL.welcome.step2_label_email()}</span>
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
@@ -96,8 +99,8 @@
|
||||
bind:value={form.email}
|
||||
/>
|
||||
<label class="label" for="password">
|
||||
<span class="label-text">Password:</span>
|
||||
<span class="label-text-alt">min. 10 characters</span>
|
||||
<span class="label-text">{$LL.welcome.step2_label_password()}</span>
|
||||
<span class="label-text-alt">{$LL.welcome.step2_label_min_chars()}</span>
|
||||
</label>
|
||||
<label class="relative block">
|
||||
<div
|
||||
@@ -120,7 +123,7 @@
|
||||
/>
|
||||
</label>
|
||||
<label class="label" for="passwordConfirm">
|
||||
<span class="label-text">Password confirm:</span>
|
||||
<span class="label-text">{$LL.welcome.step2_label_password_confirm()}</span>
|
||||
</label>
|
||||
<label class="relative block">
|
||||
<div
|
||||
@@ -144,7 +147,7 @@
|
||||
</label>
|
||||
<div class="card-actions justify-end mt-4">
|
||||
<button class="btn btn-primary" type="submit"
|
||||
>Create <Fa icon={faArrowRight} /></button
|
||||
>{$LL.welcome.step2_btn_create()} <Fa icon={faArrowRight} /></button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
@@ -152,19 +155,21 @@
|
||||
{:else if stepsCompleted === 2}
|
||||
<figure class="w-72 mx-auto pt-6"><img src="/gopher.svg" alt="Gopher" /></figure>
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">You are all set! 🎉</h2>
|
||||
<p>Go ahead and add some devices to your dashboard.</p>
|
||||
<h2 class="card-title">{$LL.welcome.step3_page_title()}</h2>
|
||||
<p>{$LL.welcome.step3_page_desc()}</p>
|
||||
<div class="card-actions justify-end">
|
||||
<button class="btn btn-success" on:click={() => goto('/')}>Lets go!</button>
|
||||
<button class="btn btn-success" on:click={() => goto('/')}
|
||||
>{$LL.welcome.step3_btn_done()}</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if !$settingsPub?.setup_completed}
|
||||
<ul class="steps steps-horizontal">
|
||||
<li class="step step-primary">Welcome</li>
|
||||
<li class="step" class:step-primary={stepsCompleted > 0}>Create account</li>
|
||||
<li class="step" class:step-primary={stepsCompleted > 1}>Done</li>
|
||||
<li class="step step-primary">{$LL.welcome.progress_step1()}</li>
|
||||
<li class="step" class:step-primary={stepsCompleted > 0}>{$LL.welcome.progress_step2()}</li>
|
||||
<li class="step" class:step-primary={stepsCompleted > 1}>{$LL.welcome.progress_step3()}</li>
|
||||
</ul>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user