From 9ec96be9598dc2feb39f0e7b71c4ed4546537bca Mon Sep 17 00:00:00 2001 From: Abhinav Raut Date: Sun, 31 Aug 2025 20:08:38 +0530 Subject: [PATCH] rename AppUpdate component with AdminBanner - show banner when app restart is required. - UI changes to admin banner --- cmd/init.go | 5 +- cmd/main.go | 2 + cmd/settings.go | 24 ++++++- frontend/src/App.vue | 6 +- .../src/components/banner/AdminBanner.vue | 63 +++++++++++++++++++ frontend/src/components/update/AppUpdate.vue | 33 ---------- i18n/en.json | 1 + 7 files changed, 96 insertions(+), 38 deletions(-) create mode 100644 frontend/src/components/banner/AdminBanner.vue delete mode 100644 frontend/src/components/update/AppUpdate.vue diff --git a/cmd/init.go b/cmd/init.go index 32cc000..c9351e8 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -385,7 +385,10 @@ func reloadSettings(app *App) error { app.lo.Error("error unmarshalling settings from DB", "error", err) return err } - if err := ko.Load(confmap.Provider(out, "."), nil); err != nil { + app.Lock() + err = ko.Load(confmap.Provider(out, "."), nil) + app.Unlock() + if err != nil { app.lo.Error("error loading settings into koanf", "error", err) return err } diff --git a/cmd/main.go b/cmd/main.go index ea5ffb6..c7571a6 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -97,6 +97,8 @@ type App struct { // Global state that stores data on an available app update. update *AppUpdate + // Flag to indicate if app restart is required for settings to take effect. + restartRequired bool sync.Mutex } diff --git a/cmd/settings.go b/cmd/settings.go index f58383d..5f3034a 100644 --- a/cmd/settings.go +++ b/cmd/settings.go @@ -31,6 +31,8 @@ func handleGetGeneralSettings(r *fastglue.Request) error { settings["app.update"] = app.update // Set app version. settings["app.version"] = versionString + // Set restart required flag. + settings["app.restart_required"] = app.restartRequired return r.SendEnvelope(settings) } @@ -45,6 +47,11 @@ func handleUpdateGeneralSettings(r *fastglue.Request) error { return r.SendErrorEnvelope(fasthttp.StatusBadRequest, app.i18n.T("globals.messages.badRequest"), nil, envelope.InputError) } + // Get current language before update. + app.Lock() + oldLang := ko.String("app.lang") + app.Unlock() + // Remove any trailing slash `/` from the root url. req.RootURL = strings.TrimRight(req.RootURL, "/") @@ -55,6 +62,17 @@ func handleUpdateGeneralSettings(r *fastglue.Request) error { if err := reloadSettings(app); err != nil { return envelope.NewError(envelope.GeneralError, app.i18n.Ts("globals.messages.couldNotReload", "name", app.i18n.T("globals.terms.setting")), nil) } + + // Check if language changed and reload i18n if needed. + app.Lock() + newLang := ko.String("app.lang") + if oldLang != newLang { + app.lo.Info("language changed, reloading i18n", "old_lang", oldLang, "new_lang", newLang) + app.i18n = initI18n(app.fs) + app.lo.Info("reloaded i18n", "old_lang", oldLang, "new_lang", newLang) + } + app.Unlock() + if err := reloadTemplates(app); err != nil { return envelope.NewError(envelope.GeneralError, app.i18n.Ts("globals.messages.couldNotReload", "name", app.i18n.T("globals.terms.setting")), nil) } @@ -117,6 +135,10 @@ func handleUpdateEmailNotificationSettings(r *fastglue.Request) error { return sendErrorEnvelope(r, err) } - // No reload implemented, so user has to restart the app. + // Email notification settings require app restart to take effect. + app.Lock() + app.restartRequired = true + app.Unlock() + return r.SendEnvelope(true) } diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 78ee23d..df4af44 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -88,8 +88,8 @@ @create-conversation="() => (openCreateConversationDialog = true)" >
- - + + @@ -128,7 +128,7 @@ import { useCustomAttributeStore } from '@/stores/customAttributes' import { useIdleDetection } from '@/composables/useIdleDetection' import PageHeader from './components/layout/PageHeader.vue' import ViewForm from '@/features/view/ViewForm.vue' -import AppUpdate from '@/components/update/AppUpdate.vue' +import AdminBanner from '@/components/banner/AdminBanner.vue' import api from '@/api' import { toast as sooner } from 'vue-sonner' import Sidebar from '@/components/sidebar/Sidebar.vue' diff --git a/frontend/src/components/banner/AdminBanner.vue b/frontend/src/components/banner/AdminBanner.vue new file mode 100644 index 0000000..0805b6c --- /dev/null +++ b/frontend/src/components/banner/AdminBanner.vue @@ -0,0 +1,63 @@ + + + diff --git a/frontend/src/components/update/AppUpdate.vue b/frontend/src/components/update/AppUpdate.vue deleted file mode 100644 index 58dfb41..0000000 --- a/frontend/src/components/update/AppUpdate.vue +++ /dev/null @@ -1,33 +0,0 @@ - - - diff --git a/i18n/en.json b/i18n/en.json index 3c875e6..b7fcc97 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -550,6 +550,7 @@ "admin.automation.event.message.incoming": "Incoming message", "admin.automation.invalid": "Make sure you have atleast one action and one rule and their values are not empty.", "admin.notification.restartApp": "Settings updated successfully, Please restart the app for changes to take effect.", + "admin.banner.restartMessage": "Some settings have been changed that require an application restart to take effect.", "admin.template.outgoingEmailTemplates": "Outgoing email templates", "admin.template.emailNotificationTemplates": "Email notification templates", "admin.template.makeSureTemplateHasContent": "Make sure the template has {content} only once.",