Ver código fonte

feat: inspect configurations #69

0xJacky 2 anos atrás
pai
commit
5373062a4a

+ 4 - 0
frontend/src/api/ngx.ts

@@ -15,6 +15,10 @@ const ngx = {
 
     reload() {
         return http.post('/nginx/reload')
+    },
+
+    test() {
+        return http.post('/nginx/test')
     }
 }
 

+ 27 - 13
frontend/src/language/en/app.po

@@ -105,9 +105,9 @@ msgstr "Auto-renewal disabled for %{name}"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "Auto-renewal enabled for %{name}"
 
-#: src/views/config/Config.vue:16 src/views/config/Config.vue:17
-#: src/views/config/Config.vue:27 src/views/config/Config.vue:5
-#: src/views/config/ConfigEdit.vue:64 src/views/domain/DomainEdit.vue:222
+#: src/views/config/Config.vue:18 src/views/config/Config.vue:19
+#: src/views/config/Config.vue:29 src/views/config/Config.vue:7
+#: src/views/config/ConfigEdit.vue:72 src/views/domain/DomainEdit.vue:222
 #: src/views/nginx_log/NginxLog.vue:173
 msgid "Back"
 msgstr "Back"
@@ -185,11 +185,15 @@ msgstr "Comments"
 msgid "Config Templates"
 msgstr "Configurations"
 
+#: src/views/config/InspectConfig.vue:3
+msgid "Configuration file is test successful"
+msgstr ""
+
 #: src/views/domain/DomainAdd.vue:11
 msgid "Configuration Name"
 msgstr "Configuration Name"
 
-#: src/views/config/Config.vue:2
+#: src/views/config/Config.vue:4
 msgid "Configurations"
 msgstr "Configurations"
 
@@ -338,7 +342,7 @@ msgstr ""
 msgid "Edit %{n}"
 msgstr "Edit %{n}"
 
-#: src/routes/index.ts:81 src/views/config/ConfigEdit.vue:2
+#: src/routes/index.ts:81 src/views/config/ConfigEdit.vue:4
 msgid "Edit Configuration"
 msgstr "Edit Configuration"
 
@@ -379,6 +383,10 @@ msgstr "Enabled successfully"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "Encrypt website with Let's Encrypt"
 
+#: src/views/config/InspectConfig.vue:17
+msgid "Error"
+msgstr ""
+
 #: src/routes/index.ts:115 src/views/domain/ngx_conf/LogEntry.vue:68
 msgid "Error Logs"
 msgstr ""
@@ -431,16 +439,16 @@ msgstr ""
 msgid "Finished"
 msgstr "Finished"
 
-#: src/views/config/ConfigEdit.vue:67
+#: src/views/config/ConfigEdit.vue:75
 msgid "Format Code"
 msgstr ""
 
-#: src/views/config/ConfigEdit.vue:52
+#: src/views/config/ConfigEdit.vue:57
 #, fuzzy
 msgid "Format error %{msg}"
 msgstr "Save error %{msg}"
 
-#: src/views/config/ConfigEdit.vue:50
+#: src/views/config/ConfigEdit.vue:55
 #, fuzzy
 msgid "Format successfully"
 msgstr "Saved successfully"
@@ -477,6 +485,11 @@ msgstr ""
 msgid "Initialing core upgrader"
 msgstr ""
 
+#: src/views/config/InspectConfig.vue:2
+#, fuzzy
+msgid "Inspect Configurations"
+msgstr "Edit Configuration"
+
 #: src/routes/index.ts:155 src/views/other/Install.vue:128
 msgid "Install"
 msgstr "Install"
@@ -778,7 +791,7 @@ msgstr ""
 msgid "Run Mode"
 msgstr "Advance Mode"
 
-#: src/views/config/ConfigEdit.vue:70 src/views/domain/DomainEdit.vue:225
+#: src/views/config/ConfigEdit.vue:78 src/views/domain/DomainEdit.vue:225
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:33
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:34
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:40
@@ -794,7 +807,7 @@ msgstr "Save"
 msgid "Save Directive"
 msgstr "Save Directive"
 
-#: src/views/config/ConfigEdit.vue:43 src/views/domain/DomainAdd.vue:55
+#: src/views/config/ConfigEdit.vue:46 src/views/domain/DomainAdd.vue:55
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:37
 msgid "Save error %{msg}"
 msgstr "Save error %{msg}"
@@ -810,7 +823,7 @@ msgstr "Saved successfully"
 msgid "Save Successfully"
 msgstr "Saved successfully"
 
-#: src/views/config/ConfigEdit.vue:41 src/views/domain/DomainAdd.vue:44
+#: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:44
 #: src/views/domain/DomainEdit.vue:125
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:35
 msgid "Saved successfully"
@@ -828,7 +841,7 @@ msgstr "Send"
 #: src/components/StdDataDisplay/StdTable.vue:168
 #: src/components/StdDataDisplay/StdTable.vue:343
 #: src/components/StdDataDisplay/StdTable.vue:463
-#: src/layouts/HeaderLayout.vue:26 src/views/config/ConfigEdit.vue:29
+#: src/layouts/HeaderLayout.vue:26 src/views/config/ConfigEdit.vue:32
 #: src/views/domain/DomainEdit.vue:87 src/views/domain/DomainList.vue:83
 #: src/views/other/Install.vue:71 src/views/preference/Preference.vue:41
 msgid "Server error"
@@ -995,7 +1008,8 @@ msgstr ""
 msgid "View"
 msgstr ""
 
-#: src/views/domain/cert/IssueCert.vue:26 src/views/domain/DomainAdd.vue:22
+#: src/views/config/InspectConfig.vue:6 src/views/domain/cert/IssueCert.vue:26
+#: src/views/domain/DomainAdd.vue:22
 msgid "Warning"
 msgstr "Warning"
 

+ 27 - 14
frontend/src/language/messages.pot

@@ -104,11 +104,11 @@ msgstr ""
 msgid "Auto-renewal enabled for %{name}"
 msgstr ""
 
-#: src/views/config/Config.vue:16
-#: src/views/config/Config.vue:17
-#: src/views/config/Config.vue:27
-#: src/views/config/Config.vue:5
-#: src/views/config/ConfigEdit.vue:64
+#: src/views/config/Config.vue:18
+#: src/views/config/Config.vue:19
+#: src/views/config/Config.vue:29
+#: src/views/config/Config.vue:7
+#: src/views/config/ConfigEdit.vue:72
 #: src/views/domain/DomainEdit.vue:222
 #: src/views/nginx_log/NginxLog.vue:173
 msgid "Back"
@@ -187,11 +187,15 @@ msgstr ""
 msgid "Config Templates"
 msgstr ""
 
+#: src/views/config/InspectConfig.vue:3
+msgid "Configuration file is test successful"
+msgstr ""
+
 #: src/views/domain/DomainAdd.vue:11
 msgid "Configuration Name"
 msgstr ""
 
-#: src/views/config/Config.vue:2
+#: src/views/config/Config.vue:4
 msgid "Configurations"
 msgstr ""
 
@@ -350,7 +354,7 @@ msgid "Edit %{n}"
 msgstr ""
 
 #: src/routes/index.ts:81
-#: src/views/config/ConfigEdit.vue:2
+#: src/views/config/ConfigEdit.vue:4
 msgid "Edit Configuration"
 msgstr ""
 
@@ -397,6 +401,10 @@ msgstr ""
 msgid "Encrypt website with Let's Encrypt"
 msgstr ""
 
+#: src/views/config/InspectConfig.vue:17
+msgid "Error"
+msgstr ""
+
 #: src/routes/index.ts:115
 #: src/views/domain/ngx_conf/LogEntry.vue:68
 msgid "Error Logs"
@@ -456,15 +464,15 @@ msgstr ""
 msgid "Finished"
 msgstr ""
 
-#: src/views/config/ConfigEdit.vue:67
+#: src/views/config/ConfigEdit.vue:75
 msgid "Format Code"
 msgstr ""
 
-#: src/views/config/ConfigEdit.vue:52
+#: src/views/config/ConfigEdit.vue:57
 msgid "Format error %{msg}"
 msgstr ""
 
-#: src/views/config/ConfigEdit.vue:50
+#: src/views/config/ConfigEdit.vue:55
 msgid "Format successfully"
 msgstr ""
 
@@ -500,6 +508,10 @@ msgstr ""
 msgid "Initialing core upgrader"
 msgstr ""
 
+#: src/views/config/InspectConfig.vue:2
+msgid "Inspect Configurations"
+msgstr ""
+
 #: src/routes/index.ts:155
 #: src/views/other/Install.vue:128
 msgid "Install"
@@ -812,7 +824,7 @@ msgstr ""
 msgid "Run Mode"
 msgstr ""
 
-#: src/views/config/ConfigEdit.vue:70
+#: src/views/config/ConfigEdit.vue:78
 #: src/views/domain/DomainEdit.vue:225
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:33
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:34
@@ -829,7 +841,7 @@ msgstr ""
 msgid "Save Directive"
 msgstr ""
 
-#: src/views/config/ConfigEdit.vue:43
+#: src/views/config/ConfigEdit.vue:46
 #: src/views/domain/DomainAdd.vue:55
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:37
 msgid "Save error %{msg}"
@@ -844,7 +856,7 @@ msgstr ""
 msgid "Save Successfully"
 msgstr ""
 
-#: src/views/config/ConfigEdit.vue:41
+#: src/views/config/ConfigEdit.vue:44
 #: src/views/domain/DomainAdd.vue:44
 #: src/views/domain/DomainEdit.vue:125
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:35
@@ -865,7 +877,7 @@ msgstr ""
 #: src/components/StdDataDisplay/StdTable.vue:343
 #: src/components/StdDataDisplay/StdTable.vue:463
 #: src/layouts/HeaderLayout.vue:26
-#: src/views/config/ConfigEdit.vue:29
+#: src/views/config/ConfigEdit.vue:32
 #: src/views/domain/DomainEdit.vue:87
 #: src/views/domain/DomainList.vue:83
 #: src/views/other/Install.vue:71
@@ -1026,6 +1038,7 @@ msgstr ""
 msgid "View"
 msgstr ""
 
+#: src/views/config/InspectConfig.vue:6
 #: src/views/domain/cert/IssueCert.vue:26
 #: src/views/domain/DomainAdd.vue:22
 msgid "Warning"

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
frontend/src/language/translations.json


BIN
frontend/src/language/zh_CN/app.mo


+ 27 - 14
frontend/src/language/zh_CN/app.po

@@ -106,9 +106,9 @@ msgstr "成功关闭 %{name} 自动续签"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "成功启用 %{name} 自动续签"
 
-#: src/views/config/Config.vue:16 src/views/config/Config.vue:17
-#: src/views/config/Config.vue:27 src/views/config/Config.vue:5
-#: src/views/config/ConfigEdit.vue:64 src/views/domain/DomainEdit.vue:222
+#: src/views/config/Config.vue:18 src/views/config/Config.vue:19
+#: src/views/config/Config.vue:29 src/views/config/Config.vue:7
+#: src/views/config/ConfigEdit.vue:72 src/views/domain/DomainEdit.vue:222
 #: src/views/nginx_log/NginxLog.vue:173
 msgid "Back"
 msgstr "返回"
@@ -181,11 +181,15 @@ msgstr "注释"
 msgid "Config Templates"
 msgstr "配置"
 
+#: src/views/config/InspectConfig.vue:3
+msgid "Configuration file is test successful"
+msgstr "配置文件测试成功"
+
 #: src/views/domain/DomainAdd.vue:11
 msgid "Configuration Name"
 msgstr "配置名称"
 
-#: src/views/config/Config.vue:2
+#: src/views/config/Config.vue:4
 msgid "Configurations"
 msgstr "配置"
 
@@ -334,7 +338,7 @@ msgstr "下载最新版本"
 msgid "Edit %{n}"
 msgstr "编辑 %{n}"
 
-#: src/routes/index.ts:81 src/views/config/ConfigEdit.vue:2
+#: src/routes/index.ts:81 src/views/config/ConfigEdit.vue:4
 msgid "Edit Configuration"
 msgstr "编辑配置"
 
@@ -375,6 +379,10 @@ msgstr "启用成功"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "用 Let's Encrypt 对网站进行加密"
 
+#: src/views/config/InspectConfig.vue:17
+msgid "Error"
+msgstr "错误"
+
 #: src/routes/index.ts:115 src/views/domain/ngx_conf/LogEntry.vue:68
 msgid "Error Logs"
 msgstr "错误日志"
@@ -427,17 +435,17 @@ msgstr "过滤"
 msgid "Finished"
 msgstr "完成"
 
-#: src/views/config/ConfigEdit.vue:67
+#: src/views/config/ConfigEdit.vue:75
 msgid "Format Code"
 msgstr "代码格式化"
 
-#: src/views/config/ConfigEdit.vue:52
+#: src/views/config/ConfigEdit.vue:57
 msgid "Format error %{msg}"
 msgstr "保存错误 %{msg}"
 
-#: src/views/config/ConfigEdit.vue:50
+#: src/views/config/ConfigEdit.vue:55
 msgid "Format successfully"
-msgstr "保存成功"
+msgstr "格式化成功"
 
 #: src/components/StdDataEntry/components/StdPassword.vue:42
 msgid "Generate"
@@ -471,6 +479,10 @@ msgstr "初始化核心升级程序错误"
 msgid "Initialing core upgrader"
 msgstr "初始化核心升级器"
 
+#: src/views/config/InspectConfig.vue:2
+msgid "Inspect Configurations"
+msgstr "检查配置"
+
 #: src/routes/index.ts:155 src/views/other/Install.vue:128
 msgid "Install"
 msgstr "安装"
@@ -762,7 +774,7 @@ msgstr "重置"
 msgid "Run Mode"
 msgstr "运行模式"
 
-#: src/views/config/ConfigEdit.vue:70 src/views/domain/DomainEdit.vue:225
+#: src/views/config/ConfigEdit.vue:78 src/views/domain/DomainEdit.vue:225
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:33
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:34
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:40
@@ -778,7 +790,7 @@ msgstr "保存"
 msgid "Save Directive"
 msgstr "保存指令"
 
-#: src/views/config/ConfigEdit.vue:43 src/views/domain/DomainAdd.vue:55
+#: src/views/config/ConfigEdit.vue:46 src/views/domain/DomainAdd.vue:55
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:37
 msgid "Save error %{msg}"
 msgstr "保存错误 %{msg}"
@@ -792,7 +804,7 @@ msgstr "保存成功"
 msgid "Save Successfully"
 msgstr "保存成功"
 
-#: src/views/config/ConfigEdit.vue:41 src/views/domain/DomainAdd.vue:44
+#: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:44
 #: src/views/domain/DomainEdit.vue:125
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:35
 msgid "Saved successfully"
@@ -810,7 +822,7 @@ msgstr "上传"
 #: src/components/StdDataDisplay/StdTable.vue:168
 #: src/components/StdDataDisplay/StdTable.vue:343
 #: src/components/StdDataDisplay/StdTable.vue:463
-#: src/layouts/HeaderLayout.vue:26 src/views/config/ConfigEdit.vue:29
+#: src/layouts/HeaderLayout.vue:26 src/views/config/ConfigEdit.vue:32
 #: src/views/domain/DomainEdit.vue:87 src/views/domain/DomainList.vue:83
 #: src/views/other/Install.vue:71 src/views/preference/Preference.vue:41
 msgid "Server error"
@@ -965,7 +977,8 @@ msgstr "使用 HTTP01 challenge provider"
 msgid "View"
 msgstr "查看"
 
-#: src/views/domain/cert/IssueCert.vue:26 src/views/domain/DomainAdd.vue:22
+#: src/views/config/InspectConfig.vue:6 src/views/domain/cert/IssueCert.vue:26
+#: src/views/domain/DomainAdd.vue:22
 msgid "Warning"
 msgstr "警告"
 

BIN
frontend/src/language/zh_TW/app.mo


+ 26 - 13
frontend/src/language/zh_TW/app.po

@@ -107,9 +107,9 @@ msgstr "已關閉 %{name} 自動續簽"
 msgid "Auto-renewal enabled for %{name}"
 msgstr "已啟用 %{name} 自動續簽"
 
-#: src/views/config/Config.vue:16 src/views/config/Config.vue:17
-#: src/views/config/Config.vue:27 src/views/config/Config.vue:5
-#: src/views/config/ConfigEdit.vue:64 src/views/domain/DomainEdit.vue:222
+#: src/views/config/Config.vue:18 src/views/config/Config.vue:19
+#: src/views/config/Config.vue:29 src/views/config/Config.vue:7
+#: src/views/config/ConfigEdit.vue:72 src/views/domain/DomainEdit.vue:222
 #: src/views/nginx_log/NginxLog.vue:173
 msgid "Back"
 msgstr "返回"
@@ -182,11 +182,15 @@ msgstr "註釋"
 msgid "Config Templates"
 msgstr "配置模板"
 
+#: src/views/config/InspectConfig.vue:3
+msgid "Configuration file is test successful"
+msgstr "配置文件測試成功"
+
 #: src/views/domain/DomainAdd.vue:11
 msgid "Configuration Name"
 msgstr "配置名稱"
 
-#: src/views/config/Config.vue:2
+#: src/views/config/Config.vue:4
 msgid "Configurations"
 msgstr "配置"
 
@@ -335,7 +339,7 @@ msgstr "正在下載最新版本"
 msgid "Edit %{n}"
 msgstr "編輯 %{n}"
 
-#: src/routes/index.ts:81 src/views/config/ConfigEdit.vue:2
+#: src/routes/index.ts:81 src/views/config/ConfigEdit.vue:4
 msgid "Edit Configuration"
 msgstr "編輯配置"
 
@@ -376,6 +380,10 @@ msgstr "啟用成功"
 msgid "Encrypt website with Let's Encrypt"
 msgstr "用 Let's Encrypt 對網站進行加密"
 
+#: src/views/config/InspectConfig.vue:17
+msgid "Error"
+msgstr "錯誤"
+
 #: src/routes/index.ts:115 src/views/domain/ngx_conf/LogEntry.vue:68
 msgid "Error Logs"
 msgstr "錯誤日志"
@@ -428,15 +436,15 @@ msgstr "篩選"
 msgid "Finished"
 msgstr "完成"
 
-#: src/views/config/ConfigEdit.vue:67
+#: src/views/config/ConfigEdit.vue:75
 msgid "Format Code"
 msgstr "格式化代碼"
 
-#: src/views/config/ConfigEdit.vue:52
+#: src/views/config/ConfigEdit.vue:57
 msgid "Format error %{msg}"
 msgstr "格式錯誤 %{msg}"
 
-#: src/views/config/ConfigEdit.vue:50
+#: src/views/config/ConfigEdit.vue:55
 msgid "Format successfully"
 msgstr "格式化成功"
 
@@ -472,6 +480,10 @@ msgstr "初始核心升級程序錯誤"
 msgid "Initialing core upgrader"
 msgstr "正在初始化核心升級程序"
 
+#: src/views/config/InspectConfig.vue:2
+msgid "Inspect Configurations"
+msgstr "檢查配置"
+
 #: src/routes/index.ts:155 src/views/other/Install.vue:128
 msgid "Install"
 msgstr "安裝"
@@ -763,7 +775,7 @@ msgstr "重設"
 msgid "Run Mode"
 msgstr "高階模式"
 
-#: src/views/config/ConfigEdit.vue:70 src/views/domain/DomainEdit.vue:225
+#: src/views/config/ConfigEdit.vue:78 src/views/domain/DomainEdit.vue:225
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:33
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:34
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:40
@@ -779,7 +791,7 @@ msgstr "儲存"
 msgid "Save Directive"
 msgstr "儲存指令"
 
-#: src/views/config/ConfigEdit.vue:43 src/views/domain/DomainAdd.vue:55
+#: src/views/config/ConfigEdit.vue:46 src/views/domain/DomainAdd.vue:55
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:37
 msgid "Save error %{msg}"
 msgstr "儲存錯誤 %{msg}"
@@ -793,7 +805,7 @@ msgstr "保存成功"
 msgid "Save Successfully"
 msgstr "保存成功"
 
-#: src/views/config/ConfigEdit.vue:41 src/views/domain/DomainAdd.vue:44
+#: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:44
 #: src/views/domain/DomainEdit.vue:125
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:35
 msgid "Saved successfully"
@@ -811,7 +823,7 @@ msgstr "上傳"
 #: src/components/StdDataDisplay/StdTable.vue:168
 #: src/components/StdDataDisplay/StdTable.vue:343
 #: src/components/StdDataDisplay/StdTable.vue:463
-#: src/layouts/HeaderLayout.vue:26 src/views/config/ConfigEdit.vue:29
+#: src/layouts/HeaderLayout.vue:26 src/views/config/ConfigEdit.vue:32
 #: src/views/domain/DomainEdit.vue:87 src/views/domain/DomainList.vue:83
 #: src/views/other/Install.vue:71 src/views/preference/Preference.vue:41
 msgid "Server error"
@@ -967,7 +979,8 @@ msgstr "使用 HTTP01 挑戰提供者"
 msgid "View"
 msgstr "查看"
 
-#: src/views/domain/cert/IssueCert.vue:26 src/views/domain/DomainAdd.vue:22
+#: src/views/config/InspectConfig.vue:6 src/views/domain/cert/IssueCert.vue:26
+#: src/views/domain/DomainAdd.vue:22
 msgid "Warning"
 msgstr "警告"
 

+ 8 - 1
frontend/src/layouts/HeaderLayout.vue

@@ -6,6 +6,7 @@ import auth from '@/api/auth'
 import {HomeOutlined, LogoutOutlined, MenuUnfoldOutlined, ReloadOutlined} from '@ant-design/icons-vue'
 import {useRouter} from 'vue-router'
 import ngx from '@/api/ngx'
+import logLevel from '@/views/config/constants'
 
 const {$gettext} = gettext
 
@@ -21,7 +22,13 @@ function logout() {
 
 function reload_nginx() {
     ngx.reload().then(r => {
-        message.success($gettext('Nginx reloaded successfully'))
+        if (r.level < logLevel.Warn) {
+            message.success($gettext('Nginx reloaded successfully'))
+        } else if (r.level === logLevel.Warn) {
+            message.warn(r.message)
+        } else {
+            message.error(r.message)
+        }
     }).catch(e => {
         message.error($gettext('Server error') + ' ' + e?.message)
     })

+ 21 - 1
frontend/src/lib/helper/index.ts

@@ -41,8 +41,28 @@ const urlJoin = (...args: string[]) =>
         .replace(/\?/g, '&')
         .replace('&', '?')
 
+function createEnum(definition: any) {
+    const strToValueMap: any = {}
+    const numToDescMap: any = {}
+    for (const enumName of Object.keys(definition)) {
+        const [value, desc] = definition[enumName]
+        strToValueMap[enumName] = value
+        numToDescMap[value] = desc
+    }
+    return {
+        ...strToValueMap,
+        getDesc(enumName: any) {
+            return (definition[enumName] && definition[enumName][1]) || ''
+        },
+        getDescFromValue(value: any) {
+            return numToDescMap[value] || ''
+        }
+    }
+}
+
 export {
     bytesToSize,
     downloadCsv,
-    urlJoin
+    urlJoin,
+    createEnum
 }

+ 1 - 1
frontend/src/version.json

@@ -1 +1 @@
-{"version":"1.7.2","build_id":73,"total_build":143}
+{"version":"1.7.3","build_id":75,"total_build":145}

+ 9 - 0
frontend/src/views/config/Config.vue

@@ -13,6 +13,7 @@ import configColumns from '@/views/config/config'
 import {useRoute} from 'vue-router'
 import FooterToolBar from '@/components/FooterToolbar/FooterToolBar.vue'
 import router from '@/routes'
+import InspectConfig from '@/views/config/InspectConfig.vue'
 
 const table = ref(null)
 const route = useRoute()
@@ -34,9 +35,17 @@ const update = ref(1)
 watch(get_params, () => {
     update.value++
 })
+
+const inspect_config = ref()
+
+watch(route, () => {
+    inspect_config.value?.test()
+})
 </script>
 
 <template>
+    <inspect-config ref="inspect_config"/>
+
     <a-card :title="$gettext('Configurations')">
         <std-table
             :key="update"

+ 9 - 6
frontend/src/views/config/ConfigEdit.vue

@@ -7,10 +7,13 @@ import config from '@/api/config'
 import {message} from 'ant-design-vue'
 import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
 import ngx from '@/api/ngx'
+import InspectConfig from '@/views/config/InspectConfig.vue'
 
 const {$gettext, interpolate} = gettext
 const route = useRoute()
 
+const inspect_config = ref()
+
 const name = computed(() => {
     const n = route.params.name
     if (typeof n === 'string') {
@@ -41,6 +44,8 @@ function save() {
         message.success($gettext('Saved successfully'))
     }).catch(r => {
         message.error(interpolate($gettext('Save error %{msg}'), {msg: r.message ?? ''}))
+    }).finally(() => {
+        inspect_config.value.test()
     })
 }
 
@@ -52,10 +57,13 @@ function format_code() {
         message.error(interpolate($gettext('Format error %{msg}'), {msg: r.message ?? ''}))
     })
 }
+
 </script>
 
 
 <template>
+    <inspect-config ref="inspect_config"/>
+
     <a-card :title="$gettext('Edit Configuration')">
         <code-editor v-model:content="configText"/>
         <footer-tool-bar>
@@ -75,10 +83,5 @@ function format_code() {
 </template>
 
 <style lang="less" scoped>
-.ant-card {
-    margin: 10px;
-    @media (max-width: 512px) {
-        margin: 10px 0;
-    }
-}
+
 </style>

+ 64 - 0
frontend/src/views/config/InspectConfig.vue

@@ -0,0 +1,64 @@
+<script setup lang="ts">
+import ngx from '@/api/ngx'
+import {useGettext} from 'vue3-gettext'
+import {ref} from 'vue'
+import logLevel from '@/views/config/constants'
+import Template from '@/views/template/Template.vue'
+
+const {$gettext} = useGettext()
+
+const data = ref({
+    level: 0,
+    message: ''
+})
+
+test()
+
+function test() {
+    ngx.test().then(r => {
+        data.value = r
+    })
+}
+
+defineExpose({
+    test
+})
+</script>
+
+<template>
+    <a-card class="inspect-container" :title="$gettext('Inspect Configurations')">
+        <a-alert :message="$gettext('Configuration file is test successful')" type="success"
+                 show-icon v-if="data?.level<logLevel.Debug"/>
+        <a-alert
+            :message="$gettext('Warning')"
+            type="warning"
+            show-icon
+            v-else-if="data?.level===logLevel.Warn"
+        >
+            <template #description>
+                {{ data.message }}
+            </template>
+        </a-alert>
+
+        <a-alert
+            :message="$gettext('Error')"
+            type="error"
+            show-icon
+            v-else-if="data?.level>logLevel.Warn"
+        >
+            <template #description>
+                {{ data.message }}
+            </template>
+        </a-alert>
+    </a-card>
+</template>
+
+<style lang="less" scoped>
+.inspect-container {
+    margin-bottom: 20px;
+}
+
+:deep(.ant-alert-description) {
+    white-space: pre-line;
+}
+</style>

+ 17 - 0
frontend/src/views/config/constants.ts

@@ -0,0 +1,17 @@
+import {createEnum} from '@/lib/helper'
+
+// refer to https://nginx.org/en/docs/ngx_core_module.html#error_log
+// nginx log level: debug, info, notice, warn, error, crit, alert, or emerg
+
+const logLevel = createEnum({
+    Debug: [0, 'debug'],
+    Info: [1, 'info'],
+    Notice: [2, 'notice'],
+    Warn: [3, 'warn'],
+    Error: [4, 'error'],
+    Crit: [5, 'crit'],
+    Alert: [6, 'alert'],
+    Emerg: [7, 'emerg']
+})
+
+export default logLevel

+ 1 - 1
frontend/version.json

@@ -1 +1 @@
-{"version":"1.7.2","build_id":73,"total_build":143}
+{"version":"1.7.3","build_id":75,"total_build":145}

+ 8 - 9
server/api/config.go

@@ -1,13 +1,12 @@
 package api
 
 import (
-    "github.com/0xJacky/Nginx-UI/server/pkg/config_list"
-    "github.com/0xJacky/Nginx-UI/server/pkg/nginx"
-    "github.com/gin-gonic/gin"
-    "log"
-    "net/http"
-    "os"
-    "strings"
+	"github.com/0xJacky/Nginx-UI/server/pkg/config_list"
+	"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
+	"github.com/gin-gonic/gin"
+	"log"
+	"net/http"
+	"os"
 )
 
 func GetConfigs(c *gin.Context) {
@@ -126,7 +125,7 @@ func AddConfig(c *gin.Context) {
 
 	output := nginx.Reload()
 
-	if output != "" && strings.Contains(output, "error") {
+	if nginx.GetLogLevel(output) >= nginx.Warn {
 		c.JSON(http.StatusInternalServerError, gin.H{
 			"message": output,
 		})
@@ -172,7 +171,7 @@ func EditConfig(c *gin.Context) {
 
 	output := nginx.Reload()
 
-	if output != "" && strings.Contains(output, "error") {
+	if nginx.GetLogLevel(output) >= nginx.Warn {
 		c.JSON(http.StatusInternalServerError, gin.H{
 			"message": output,
 		})

+ 13 - 11
server/api/domain.go

@@ -203,17 +203,18 @@ func EditDomain(c *gin.Context) {
 	enabledConfigFilePath = nginx.GetConfPath("sites-enabled", name)
 	if _, err = os.Stat(enabledConfigFilePath); err == nil {
 		// Test nginx configuration
-		err = nginx.TestConf()
-		if err != nil {
+		output := nginx.TestConf()
+		if nginx.GetLogLevel(output) >= nginx.Warn {
 			c.JSON(http.StatusInternalServerError, gin.H{
-				"message": err.Error(),
+				"message": output,
 				"error":   "nginx_config_syntax_error",
 			})
 			return
 		}
-		output := nginx.Reload()
 
-		if output != "" && strings.Contains(output, "error") {
+		output = nginx.Reload()
+
+		if nginx.GetLogLevel(output) >= nginx.Warn {
 			c.JSON(http.StatusInternalServerError, gin.H{
 				"message": output,
 			})
@@ -245,18 +246,19 @@ func EnableDomain(c *gin.Context) {
 	}
 
 	// Test nginx config, if not pass then rollback.
-	err = nginx.TestConf()
-	if err != nil {
+	output := nginx.TestConf()
+
+	if nginx.GetLogLevel(output) >= nginx.Warn {
 		_ = os.Remove(enabledConfigFilePath)
 		c.JSON(http.StatusInternalServerError, gin.H{
-			"message": err.Error(),
+			"message": output,
 		})
 		return
 	}
 
-	output := nginx.Reload()
+	output = nginx.Reload()
 
-	if output != "" && strings.Contains(output, "error") {
+	if nginx.GetLogLevel(output) >= nginx.Warn {
 		c.JSON(http.StatusInternalServerError, gin.H{
 			"message": output,
 		})
@@ -295,7 +297,7 @@ func DisableDomain(c *gin.Context) {
 
 	output := nginx.Reload()
 
-	if output != "" {
+	if nginx.GetLogLevel(output) >= nginx.Warn {
 		c.JSON(http.StatusInternalServerError, gin.H{
 			"message": output,
 		})

+ 43 - 41
server/api/ngx.go

@@ -1,65 +1,67 @@
 package api
 
 import (
-	"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
-	"github.com/gin-gonic/gin"
-	"net/http"
-	"strings"
+    "github.com/0xJacky/Nginx-UI/server/pkg/nginx"
+    "github.com/gin-gonic/gin"
+    "net/http"
 )
 
 func BuildNginxConfig(c *gin.Context) {
-	var ngxConf nginx.NgxConfig
-	if !BindAndValid(c, &ngxConf) {
-		return
-	}
-	c.Set("maybe_error", "nginx_config_syntax_error")
-	c.JSON(http.StatusOK, gin.H{
-		"content": ngxConf.BuildConfig(),
-	})
+    var ngxConf nginx.NgxConfig
+    if !BindAndValid(c, &ngxConf) {
+        return
+    }
+    c.Set("maybe_error", "nginx_config_syntax_error")
+    c.JSON(http.StatusOK, gin.H{
+        "content": ngxConf.BuildConfig(),
+    })
 }
 
 func TokenizeNginxConfig(c *gin.Context) {
-	var json struct {
-		Content string `json:"content" binding:"required"`
-	}
+    var json struct {
+        Content string `json:"content" binding:"required"`
+    }
 
-	if !BindAndValid(c, &json) {
-		return
-	}
+    if !BindAndValid(c, &json) {
+        return
+    }
 
-	c.Set("maybe_error", "nginx_config_syntax_error")
-	ngxConfig := nginx.ParseNgxConfigByContent(json.Content)
+    c.Set("maybe_error", "nginx_config_syntax_error")
+    ngxConfig := nginx.ParseNgxConfigByContent(json.Content)
 
-	c.JSON(http.StatusOK, ngxConfig)
+    c.JSON(http.StatusOK, ngxConfig)
 
 }
 
 func FormatNginxConfig(c *gin.Context) {
-	var json struct {
-		Content string `json:"content" binding:"required"`
-	}
+    var json struct {
+        Content string `json:"content" binding:"required"`
+    }
 
-	if !BindAndValid(c, &json) {
-		return
-	}
+    if !BindAndValid(c, &json) {
+        return
+    }
 
-	c.Set("maybe_error", "nginx_config_syntax_error")
-	c.JSON(http.StatusOK, gin.H{
-		"content": nginx.FmtCode(json.Content),
-	})
+    c.Set("maybe_error", "nginx_config_syntax_error")
+    c.JSON(http.StatusOK, gin.H{
+        "content": nginx.FmtCode(json.Content),
+    })
 }
 
 func ReloadNginx(c *gin.Context) {
-	output := nginx.Reload()
+    output := nginx.Reload()
 
-	if output != "" && strings.Contains(output, "error") {
-		c.JSON(http.StatusInternalServerError, gin.H{
-			"message": output,
-		})
-		return
-	}
+    c.JSON(http.StatusOK, gin.H{
+        "message": output,
+        "level":   nginx.GetLogLevel(output),
+    })
+}
+
+func TestNginx(c *gin.Context) {
+    output := nginx.TestConf()
 
-	c.JSON(http.StatusOK, gin.H{
-		"message": "ok",
-	})
+    c.JSON(http.StatusOK, gin.H{
+        "message": output,
+        "level":   nginx.GetLogLevel(output),
+    })
 }

+ 30 - 0
server/pkg/nginx/log.go

@@ -0,0 +1,30 @@
+package nginx
+
+import "strings"
+
+// refer to https://nginx.org/en/docs/ngx_core_module.html#error_log
+// nginx log level: debug, info, notice, warn, error, crit, alert, or emerg
+
+const (
+	Debug = iota
+	Info
+	Notice
+	Warn
+	Error
+	Crit
+	Alert
+	Emerg
+)
+
+var logLevel = [...]string{
+	"debug", "info", "notice", "warn", "error", "crit", "alert", "emerg",
+}
+
+func GetLogLevel(output string) int {
+	for k, v := range logLevel {
+		if strings.Contains(output, v) {
+			return k
+		}
+	}
+	return -1
+}

+ 6 - 16
server/pkg/nginx/nginx.go

@@ -1,40 +1,30 @@
 package nginx
 
 import (
-	"errors"
 	"github.com/0xJacky/Nginx-UI/server/settings"
 	"log"
 	"os/exec"
 	"path/filepath"
 	"regexp"
-	"strings"
 )
 
-func TestConf() error {
+func TestConf() string {
 	out, err := exec.Command("nginx", "-t").CombinedOutput()
 	if err != nil {
-		log.Println(err)
+		log.Println("[error] nginx.TestConf", err)
 	}
-	output := string(out)
-	if strings.Contains(output, "failed") {
-		return errors.New(output)
-	}
-	return nil
+
+	return string(out)
 }
 
 func Reload() string {
 	out, err := exec.Command("nginx", "-s", "reload").CombinedOutput()
 
 	if err != nil {
-		log.Println(err)
-		return err.Error()
+		log.Println("[error] nginx.Reload", err)
 	}
 
-	output := string(out)
-	if strings.Contains(output, "failed") {
-		return output
-	}
-	return ""
+	return string(out)
 }
 
 func GetConfPath(dir ...string) string {

+ 2 - 0
server/router/routers.go

@@ -64,6 +64,8 @@ func InitRouter() *gin.Engine {
 			g.POST("ngx/format_code", api.FormatNginxConfig)
 			// nginx reload
 			g.POST("nginx/reload", api.ReloadNginx)
+			// nginx test
+			g.POST("nginx/test", api.TestNginx)
 
 			g.POST("domain/:name/enable", api.EnableDomain)
 			g.POST("domain/:name/disable", api.DisableDomain)

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff