support custom tips in login page
This commit is contained in:
@@ -242,6 +242,15 @@ enable_import = true
|
|||||||
# Maximum allowed import file size (1 - 4294967295 bytes)
|
# Maximum allowed import file size (1 - 4294967295 bytes)
|
||||||
max_import_file_size = 10485760
|
max_import_file_size = 10485760
|
||||||
|
|
||||||
|
[tip]
|
||||||
|
# Set to true to display custom tips in login page
|
||||||
|
enable_tips_in_login_page = false
|
||||||
|
|
||||||
|
# The custom tips displayed in login page, it supports multi-language configuration
|
||||||
|
# Add an underscore and a language tag after the setting key to configure the notification content in that language, the same below
|
||||||
|
# For example, login_page_tips_content_zh_hans means the notification content in Simplified Chinese
|
||||||
|
login_page_tips_content =
|
||||||
|
|
||||||
[notification]
|
[notification]
|
||||||
# Set to true to display custom notification in home page every time users register
|
# Set to true to display custom notification in home page every time users register
|
||||||
enable_notification_after_register = false
|
enable_notification_after_register = false
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ func (a *ServerSettingsApi) ServerSettingsJavascriptHandler(c *core.WebContext)
|
|||||||
a.appendBooleanSetting(builder, "s", config.EnableScheduledTransaction)
|
a.appendBooleanSetting(builder, "s", config.EnableScheduledTransaction)
|
||||||
a.appendBooleanSetting(builder, "e", config.EnableDataExport)
|
a.appendBooleanSetting(builder, "e", config.EnableDataExport)
|
||||||
a.appendBooleanSetting(builder, "i", config.EnableDataImport)
|
a.appendBooleanSetting(builder, "i", config.EnableDataImport)
|
||||||
|
|
||||||
|
if config.LoginPageTips.Enabled {
|
||||||
|
a.appendMultiLanguageTipSetting(builder, "lpt", config.LoginPageTips)
|
||||||
|
}
|
||||||
|
|
||||||
a.appendStringSetting(builder, "m", config.MapProvider)
|
a.appendStringSetting(builder, "m", config.MapProvider)
|
||||||
|
|
||||||
if config.EnableMapDataFetchProxy &&
|
if config.EnableMapDataFetchProxy &&
|
||||||
@@ -118,6 +123,26 @@ func (a *ServerSettingsApi) appendStringSetting(builder *strings.Builder, key st
|
|||||||
builder.WriteString(";\n")
|
builder.WriteString(";\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *ServerSettingsApi) appendMultiLanguageTipSetting(builder *strings.Builder, key string, value settings.TipConfig) {
|
||||||
|
builder.WriteString(ezbookkeepingServerSettingsGlobalVariableFullName)
|
||||||
|
builder.WriteString("[")
|
||||||
|
a.appendEncodedString(builder, key)
|
||||||
|
builder.WriteString("]={\n")
|
||||||
|
|
||||||
|
builder.WriteString("'default'")
|
||||||
|
builder.WriteRune(':')
|
||||||
|
a.appendEncodedString(builder, value.DefaultContent)
|
||||||
|
|
||||||
|
for languageTag, content := range value.MultiLanguageContent {
|
||||||
|
builder.WriteString(",\n")
|
||||||
|
a.appendEncodedString(builder, languageTag)
|
||||||
|
builder.WriteRune(':')
|
||||||
|
a.appendEncodedString(builder, content)
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.WriteString("\n};\n")
|
||||||
|
}
|
||||||
|
|
||||||
func (a *ServerSettingsApi) appendBooleanSetting(builder *strings.Builder, key string, value bool) {
|
func (a *ServerSettingsApi) appendBooleanSetting(builder *strings.Builder, key string, value bool) {
|
||||||
builder.WriteString(ezbookkeepingServerSettingsGlobalVariableFullName)
|
builder.WriteString(ezbookkeepingServerSettingsGlobalVariableFullName)
|
||||||
builder.WriteString("[")
|
builder.WriteString("[")
|
||||||
|
|||||||
@@ -181,6 +181,13 @@ type MinIOConfig struct {
|
|||||||
RootPath string
|
RootPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TipConfig represents a tip setting config
|
||||||
|
type TipConfig struct {
|
||||||
|
Enabled bool
|
||||||
|
DefaultContent string
|
||||||
|
MultiLanguageContent map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
// NotificationConfig represents a notification setting config
|
// NotificationConfig represents a notification setting config
|
||||||
type NotificationConfig struct {
|
type NotificationConfig struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
@@ -289,6 +296,9 @@ type Config struct {
|
|||||||
EnableDataImport bool
|
EnableDataImport bool
|
||||||
MaxImportFileSize uint32
|
MaxImportFileSize uint32
|
||||||
|
|
||||||
|
// Tip
|
||||||
|
LoginPageTips TipConfig
|
||||||
|
|
||||||
// Notification
|
// Notification
|
||||||
AfterRegisterNotification NotificationConfig
|
AfterRegisterNotification NotificationConfig
|
||||||
AfterLoginNotification NotificationConfig
|
AfterLoginNotification NotificationConfig
|
||||||
@@ -408,6 +418,12 @@ func LoadConfiguration(configFilePath string) (*Config, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = loadTipConfiguration(config, cfgFile, "tip")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
err = loadNotificationConfiguration(config, cfgFile, "notification")
|
err = loadNotificationConfiguration(config, cfgFile, "notification")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -780,6 +796,12 @@ func loadDataConfiguration(config *Config, configFile *ini.File, sectionName str
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadTipConfiguration(config *Config, configFile *ini.File, sectionName string) error {
|
||||||
|
config.LoginPageTips = getTipConfiguration(configFile, sectionName, "enable_tips_in_login_page", "login_page_tips_content")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func loadNotificationConfiguration(config *Config, configFile *ini.File, sectionName string) error {
|
func loadNotificationConfiguration(config *Config, configFile *ini.File, sectionName string) error {
|
||||||
config.AfterRegisterNotification = getNotificationConfiguration(configFile, sectionName, "enable_notification_after_register", "after_register_notification_content")
|
config.AfterRegisterNotification = getNotificationConfiguration(configFile, sectionName, "enable_notification_after_register", "after_register_notification_content")
|
||||||
config.AfterLoginNotification = getNotificationConfiguration(configFile, sectionName, "enable_notification_after_login", "after_login_notification_content")
|
config.AfterLoginNotification = getNotificationConfiguration(configFile, sectionName, "enable_notification_after_login", "after_login_notification_content")
|
||||||
@@ -908,6 +930,27 @@ func getFinalPath(workingPath, p string) (string, error) {
|
|||||||
return p, err
|
return p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTipConfiguration(configFile *ini.File, sectionName string, enableKey string, contentKey string) TipConfig {
|
||||||
|
config := TipConfig{
|
||||||
|
Enabled: getConfigItemBoolValue(configFile, sectionName, enableKey, false),
|
||||||
|
DefaultContent: getConfigItemStringValue(configFile, sectionName, contentKey, ""),
|
||||||
|
MultiLanguageContent: make(map[string]string),
|
||||||
|
}
|
||||||
|
|
||||||
|
for languageTag := range locales.AllLanguages {
|
||||||
|
multiLanguageContentKey := strings.ToLower(languageTag)
|
||||||
|
multiLanguageContentKey = strings.Replace(multiLanguageContentKey, "-", "_", -1)
|
||||||
|
multiLanguageContentKey = contentKey + "_" + multiLanguageContentKey
|
||||||
|
content := getConfigItemStringValue(configFile, sectionName, multiLanguageContentKey, "")
|
||||||
|
|
||||||
|
if content != "" {
|
||||||
|
config.MultiLanguageContent[languageTag] = content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
func getNotificationConfiguration(configFile *ini.File, sectionName string, enableKey string, contentKey string) NotificationConfig {
|
func getNotificationConfiguration(configFile *ini.File, sectionName string, enableKey string, contentKey string) NotificationConfig {
|
||||||
config := NotificationConfig{
|
config := NotificationConfig{
|
||||||
Enabled: getConfigItemBoolValue(configFile, sectionName, enableKey, false),
|
Enabled: getConfigItemBoolValue(configFile, sectionName, enableKey, false),
|
||||||
|
|||||||
@@ -1435,6 +1435,20 @@ function getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccoun
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getServerTipContent(tipConfig, i18nGlobal) {
|
||||||
|
if (!tipConfig) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentLanguage = getCurrentLanguageTag(i18nGlobal);
|
||||||
|
|
||||||
|
if (tipConfig[currentLanguage]) {
|
||||||
|
return tipConfig[currentLanguage];
|
||||||
|
}
|
||||||
|
|
||||||
|
return tipConfig.default || '';
|
||||||
|
}
|
||||||
|
|
||||||
function joinMultiText(textArray, translateFn) {
|
function joinMultiText(textArray, translateFn) {
|
||||||
if (!textArray || !textArray.length) {
|
if (!textArray || !textArray.length) {
|
||||||
return '';
|
return '';
|
||||||
@@ -1707,6 +1721,7 @@ export function i18nFunctions(i18nGlobal) {
|
|||||||
getAllSupportedImportFileTypes: () => getAllSupportedImportFileTypes(i18nGlobal, i18nGlobal.t),
|
getAllSupportedImportFileTypes: () => getAllSupportedImportFileTypes(i18nGlobal, i18nGlobal.t),
|
||||||
getEnableDisableOptions: () => getEnableDisableOptions(i18nGlobal.t),
|
getEnableDisableOptions: () => getEnableDisableOptions(i18nGlobal.t),
|
||||||
getCategorizedAccountsWithDisplayBalance: (allVisibleAccounts, showAccountBalance, defaultCurrency, settingsStore, userStore, exchangeRatesStore) => getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccountBalance, defaultCurrency, userStore, settingsStore, exchangeRatesStore, i18nGlobal.t),
|
getCategorizedAccountsWithDisplayBalance: (allVisibleAccounts, showAccountBalance, defaultCurrency, settingsStore, userStore, exchangeRatesStore) => getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccountBalance, defaultCurrency, userStore, settingsStore, exchangeRatesStore, i18nGlobal.t),
|
||||||
|
getServerTipContent: (tipConfig) => getServerTipContent(tipConfig, i18nGlobal),
|
||||||
joinMultiText: (textArray) => joinMultiText(textArray, i18nGlobal.t),
|
joinMultiText: (textArray) => joinMultiText(textArray, i18nGlobal.t),
|
||||||
setLanguage: (locale, force) => setLanguage(i18nGlobal, locale, force),
|
setLanguage: (locale, force) => setLanguage(i18nGlobal, locale, force),
|
||||||
setTimeZone: (timezone) => setTimeZone(timezone),
|
setTimeZone: (timezone) => setTimeZone(timezone),
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ export function isDataImportingEnabled() {
|
|||||||
return getServerSetting('i') === 1;
|
return getServerSetting('i') === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getLoginPageTips() {
|
||||||
|
return getServerSetting('lpt');
|
||||||
|
}
|
||||||
|
|
||||||
export function getMapProvider() {
|
export function getMapProvider() {
|
||||||
return getServerSetting('m');
|
return getServerSetting('m');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
<v-card-text>
|
<v-card-text>
|
||||||
<h4 class="text-h4 mb-2">{{ $t('Welcome to ezBookkeeping') }}</h4>
|
<h4 class="text-h4 mb-2">{{ $t('Welcome to ezBookkeeping') }}</h4>
|
||||||
<p class="mb-0">{{ $t('Please log in with your ezBookkeeping account') }}</p>
|
<p class="mb-0">{{ $t('Please log in with your ezBookkeeping account') }}</p>
|
||||||
|
<p class="mt-1 mb-0" v-if="tips">{{ tips }}</p>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
|
||||||
<v-card-text class="pb-0 mb-6">
|
<v-card-text class="pb-0 mb-6">
|
||||||
@@ -179,7 +180,8 @@ import apiConstants from '@/consts/api.js';
|
|||||||
import {
|
import {
|
||||||
isUserRegistrationEnabled,
|
isUserRegistrationEnabled,
|
||||||
isUserForgetPasswordEnabled,
|
isUserForgetPasswordEnabled,
|
||||||
isUserVerifyEmailEnabled
|
isUserVerifyEmailEnabled,
|
||||||
|
getLoginPageTips
|
||||||
} from '@/lib/server_settings.js';
|
} from '@/lib/server_settings.js';
|
||||||
import { setExpenseAndIncomeAmountColor } from '@/lib/ui.js';
|
import { setExpenseAndIncomeAmountColor } from '@/lib/ui.js';
|
||||||
|
|
||||||
@@ -224,6 +226,9 @@ export default {
|
|||||||
isUserForgetPasswordEnabled() {
|
isUserForgetPasswordEnabled() {
|
||||||
return isUserForgetPasswordEnabled();
|
return isUserForgetPasswordEnabled();
|
||||||
},
|
},
|
||||||
|
tips() {
|
||||||
|
return this.$locale.getServerTipContent(getLoginPageTips());
|
||||||
|
},
|
||||||
inputIsEmpty() {
|
inputIsEmpty() {
|
||||||
return !this.username || !this.password;
|
return !this.username || !this.password;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
<f7-block class="login-page-tile margin-vertical-half">{{ $t('global.app.title') }}</f7-block>
|
<f7-block class="login-page-tile margin-vertical-half">{{ $t('global.app.title') }}</f7-block>
|
||||||
</f7-login-screen-title>
|
</f7-login-screen-title>
|
||||||
|
|
||||||
|
<f7-list inset v-if="tips">
|
||||||
|
<f7-block-footer>{{ tips }}</f7-block-footer>
|
||||||
|
</f7-list>
|
||||||
|
|
||||||
<f7-list form dividers class="margin-bottom-half">
|
<f7-list form dividers class="margin-bottom-half">
|
||||||
<f7-list-input
|
<f7-list-input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -188,7 +192,8 @@ import apiConstants from '@/consts/api.js';
|
|||||||
import {
|
import {
|
||||||
isUserRegistrationEnabled,
|
isUserRegistrationEnabled,
|
||||||
isUserForgetPasswordEnabled,
|
isUserForgetPasswordEnabled,
|
||||||
isUserVerifyEmailEnabled
|
isUserVerifyEmailEnabled,
|
||||||
|
getLoginPageTips
|
||||||
} from '@/lib/server_settings.js';
|
} from '@/lib/server_settings.js';
|
||||||
import { getDesktopVersionPath } from '@/lib/version.js';
|
import { getDesktopVersionPath } from '@/lib/version.js';
|
||||||
import { setExpenseAndIncomeAmountColor } from '@/lib/ui.js';
|
import { setExpenseAndIncomeAmountColor } from '@/lib/ui.js';
|
||||||
@@ -239,6 +244,9 @@ export default {
|
|||||||
isUserForgetPasswordEnabled() {
|
isUserForgetPasswordEnabled() {
|
||||||
return isUserForgetPasswordEnabled();
|
return isUserForgetPasswordEnabled();
|
||||||
},
|
},
|
||||||
|
tips() {
|
||||||
|
return this.$locale.getServerTipContent(getLoginPageTips());
|
||||||
|
},
|
||||||
inputIsEmpty() {
|
inputIsEmpty() {
|
||||||
return !this.username || !this.password;
|
return !this.username || !this.password;
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user