mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
feat: reload cluster node settings from settings file #169
This commit is contained in:
parent
29f1b7db89
commit
e0366f949f
13 changed files with 110 additions and 34 deletions
|
@ -3,9 +3,11 @@ package cluster
|
|||
import (
|
||||
"github.com/0xJacky/Nginx-UI/api"
|
||||
"github.com/0xJacky/Nginx-UI/internal/analytic"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cluster"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cosy"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/spf13/cast"
|
||||
"net/http"
|
||||
|
@ -75,3 +77,19 @@ func DeleteEnvironment(c *gin.Context) {
|
|||
|
||||
c.JSON(http.StatusNoContent, nil)
|
||||
}
|
||||
|
||||
func LoadEnvironmentFromSettings(c *gin.Context) {
|
||||
err := settings.ReloadCluster()
|
||||
if err != nil {
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
cluster.RegisterPredefinedNodes()
|
||||
|
||||
go analytic.RestartRetrieveNodesStatus()
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "ok",
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import "github.com/gin-gonic/gin"
|
|||
func InitRouter(r *gin.RouterGroup) {
|
||||
// Environment
|
||||
r.GET("environments", GetEnvironmentList)
|
||||
r.POST("environments/load_from_settings", LoadEnvironmentFromSettings)
|
||||
envGroup := r.Group("environment")
|
||||
{
|
||||
envGroup.GET("/:id", GetEnvironment)
|
||||
|
|
|
@ -10,6 +10,7 @@ import en_US from 'ant-design-vue/es/locale/en_US'
|
|||
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import gettext from '@/gettext'
|
||||
import loadTranslations from '@/api/translations'
|
||||
|
||||
const media = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
|
||||
|
@ -49,6 +50,8 @@ const lang = computed(() => {
|
|||
|
||||
const settings = useSettingsStore()
|
||||
const is_theme_dark = computed(() => settings.theme === 'dark')
|
||||
|
||||
loadTranslations()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import http from '@/lib/http'
|
||||
import type { ModelBase } from '@/api/curd'
|
||||
import Curd from '@/api/curd'
|
||||
|
||||
|
@ -14,6 +15,17 @@ export interface Node {
|
|||
token: string
|
||||
response_at?: Date
|
||||
}
|
||||
const environment: Curd<Environment> = new Curd('/environment')
|
||||
|
||||
class EnvironmentCurd extends Curd<Environment> {
|
||||
constructor() {
|
||||
super('/environment')
|
||||
}
|
||||
|
||||
load_from_settings() {
|
||||
return http.post(`${this.plural}/load_from_settings`)
|
||||
}
|
||||
}
|
||||
|
||||
const environment: EnvironmentCurd = new EnvironmentCurd()
|
||||
|
||||
export default environment
|
||||
|
|
19
app/src/api/translations.ts
Normal file
19
app/src/api/translations.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import gettext from '@/gettext'
|
||||
|
||||
export default async function loadTranslations() {
|
||||
const route = useRoute()
|
||||
|
||||
if (gettext.current !== 'en') {
|
||||
await fetch(`${import.meta.env.VITE_API_ROOT}/translation/${gettext.current}`).then(async r => {
|
||||
gettext.translations[gettext.current] = await r.json()
|
||||
})
|
||||
|
||||
if (route?.meta?.name)
|
||||
document.title = `${route.meta.name?.()} | Nginx UI`
|
||||
}
|
||||
|
||||
watch(route, () => {
|
||||
if (route?.meta?.name)
|
||||
document.title = `${route.meta.name?.()} | Nginx UI`
|
||||
})
|
||||
}
|
|
@ -1,32 +1,27 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { watch } from 'vue'
|
||||
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import http from '@/lib/http'
|
||||
import gettext from '@/gettext'
|
||||
import loadTranslations from '@/api/translations'
|
||||
|
||||
const settings = useSettingsStore()
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const current = ref(gettext.current)
|
||||
const current = computed({
|
||||
get() {
|
||||
return gettext.current
|
||||
},
|
||||
set(v) {
|
||||
gettext.current = v
|
||||
},
|
||||
})
|
||||
|
||||
const languageAvailable = gettext.available
|
||||
|
||||
async function init() {
|
||||
if (current.value !== 'en') {
|
||||
await http.get(`/translation/${current.value}`).then(r => {
|
||||
gettext.translations[current.value] = r
|
||||
})
|
||||
|
||||
document.title = `${route.meta.name?.()} | Nginx UI`
|
||||
}
|
||||
}
|
||||
|
||||
init()
|
||||
|
||||
watch(current, v => {
|
||||
init()
|
||||
loadTranslations()
|
||||
settings.set_language(v)
|
||||
gettext.current = v
|
||||
|
||||
|
@ -34,7 +29,6 @@ watch(current, v => {
|
|||
|
||||
document.title = `${name()} | Nginx UI`
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="tsx">
|
||||
import { h } from 'vue'
|
||||
import { Badge, Tag } from 'ant-design-vue'
|
||||
import { Badge, Tag, message } from 'ant-design-vue'
|
||||
import type { customRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import environment from '@/api/environment'
|
||||
|
@ -130,14 +130,28 @@ const columns: Column[] = [{
|
|||
dataIndex: 'action',
|
||||
}]
|
||||
|
||||
const curd = ref()
|
||||
function load_from_settings() {
|
||||
environment.load_from_settings().then(() => {
|
||||
curd.value.get_list()
|
||||
message.success($gettext('Load successfully'))
|
||||
}).catch(e => {
|
||||
message.error(`${$gettext('Server error')} ${e?.message}`)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<StdCurd
|
||||
ref="curd"
|
||||
:title="$gettext('Environment')"
|
||||
:api="environment"
|
||||
:columns="columns"
|
||||
/>
|
||||
>
|
||||
<template #extra>
|
||||
<a @click="load_from_settings">{{ $gettext('Load from settings') }}</a>
|
||||
</template>
|
||||
</StdCurd>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -5,8 +5,6 @@ const route = useRoute()
|
|||
const info = computed(() => {
|
||||
if (typeof route.meta.error === 'function')
|
||||
return route.meta.error()
|
||||
else if (typeof route.meta.error === 'string')
|
||||
return route.meta.error
|
||||
else
|
||||
return $gettext('File Not Found')
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package kernal
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
|
@ -10,7 +10,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
func registerPredefinedClusterNodes() {
|
||||
func RegisterPredefinedNodes() {
|
||||
if len(settings.ClusterSettings.Node) == 0 {
|
||||
return
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package kernal
|
||||
package cluster
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
|
@ -3,6 +3,7 @@ package kernal
|
|||
import (
|
||||
"github.com/0xJacky/Nginx-UI/internal/analytic"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cert"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cluster"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logger"
|
||||
"github.com/0xJacky/Nginx-UI/internal/logrotate"
|
||||
"github.com/0xJacky/Nginx-UI/internal/validation"
|
||||
|
@ -44,7 +45,7 @@ func InitAfterDatabase() {
|
|||
registerPredefinedUser,
|
||||
cert.InitRegister,
|
||||
InitCronJobs,
|
||||
registerPredefinedClusterNodes,
|
||||
cluster.RegisterPredefinedNodes,
|
||||
analytic.RetrieveNodesStatus,
|
||||
}
|
||||
|
||||
|
|
|
@ -7,3 +7,13 @@ type Cluster struct {
|
|||
var ClusterSettings = Cluster{
|
||||
Node: []string{},
|
||||
}
|
||||
|
||||
func ReloadCluster() (err error) {
|
||||
err = load()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return mapTo("cluster", &ClusterSettings)
|
||||
}
|
||||
|
|
|
@ -39,13 +39,18 @@ func Init(confPath string) {
|
|||
Setup()
|
||||
}
|
||||
|
||||
func Setup() {
|
||||
var err error
|
||||
func load() (err error) {
|
||||
Conf, err = ini.LoadSources(ini.LoadOptions{
|
||||
Loose: true,
|
||||
AllowShadows: true,
|
||||
}, ConfPath)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func Setup() {
|
||||
err := load()
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("settings.Setup: %v\n", err)
|
||||
}
|
||||
|
@ -72,7 +77,11 @@ func Setup() {
|
|||
|
||||
func MapTo() {
|
||||
for k, v := range sections {
|
||||
mapTo(k, v)
|
||||
err := mapTo(k, v)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Cfg.MapTo %s err: %v", k, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,11 +110,8 @@ func ProtectedFill(targetSettings interface{}, newSettings interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
func mapTo(section string, v interface{}) {
|
||||
err := Conf.Section(section).MapTo(v)
|
||||
if err != nil {
|
||||
log.Fatalf("Cfg.MapTo %s err: %v", section, err)
|
||||
}
|
||||
func mapTo(section string, v interface{}) error {
|
||||
return Conf.Section(section).MapTo(v)
|
||||
}
|
||||
|
||||
func reflectFrom(section string, v interface{}) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue