Jelajahi Sumber

feat: check if the site exists before add/rename

0xJacky 2 tahun lalu
induk
melakukan
566a5c725e

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

@@ -21,6 +21,10 @@ class Domain extends Curd {
     remove_auto_cert(domain: string) {
         return http.delete('auto_cert/' + domain)
     }
+
+    duplicate(name: string, data: any) {
+        return http.post(this.baseUrl + '/' + name + '/duplicate', data)
+    }
 }
 
 const domain = new Domain('/domain')

+ 28 - 27
frontend/src/components/StdDataDisplay/StdTable.vue

@@ -359,7 +359,7 @@ async function export_csv() {
     })
 
     downloadCsv(header, data,
-            `${$gettext('Export')}-${dayjs().format('YYYYMMDDHHmmss')}.csv`)
+        `${$gettext('Export')}-${dayjs().format('YYYYMMDDHHmmss')}.csv`)
 }
 
 const hasSelectedRow = computed(() => {
@@ -418,7 +418,7 @@ function initSortable() {
             const level: number = newRow.level
 
             let currentRowIndex: number[] = [...rows_key_index_map.value?.
-                    [Number(table.children[Number(newIndex) + direction].dataset.rowKey)]]
+                [Number(table.children[Number(newIndex) + direction].dataset.rowKey)]]
             let currentRow: any = getTargetData(data_source.value, currentRowIndex)
             // Reset parent
             currentRow.parent = newRow.parent = null
@@ -451,7 +451,7 @@ function initSortable() {
                 processChanges(getTargetData(data_source.value, rowIndex))
             }
             console.log('Change row id', newRow.id, 'order', newRow.id, '=>', currentRow.id, ', direction: ', direction,
-                    ', changes IDs:', changeIds)
+                ', changes IDs:', changeIds)
 
             props.api!.update_order({
                 target_id: newRow.id,
@@ -472,10 +472,10 @@ function initSortable() {
 <template>
     <div class="std-table">
         <std-data-entry
-                v-if="!disable_search && searchColumns.length"
-                :data-list="searchColumns"
-                v-model:data-source="params"
-                layout="inline"
+            v-if="!disable_search && searchColumns.length"
+            :data-list="searchColumns"
+            v-model:data-source="params"
+            layout="inline"
         >
             <template #action>
                 <a-space class="action-btn">
@@ -492,39 +492,40 @@ function initSortable() {
             </template>
         </std-data-entry>
         <a-table
-                :columns="pithyColumns"
-                :data-source="data_source"
-                :loading="loading"
-                :pagination="false"
-                :row-key="rowKey"
-                :rowSelection="rowSelection"
-                @change="stdChange"
-                :scroll="{ x: scrollX }"
-                :size="size"
-                id="std-table"
-                @expandedRowsChange="expandedTable"
-                :expandedRowKeys="expand_keys_list"
+            :columns="pithyColumns"
+            :data-source="data_source"
+            :loading="loading"
+            :pagination="false"
+            :row-key="rowKey"
+            :rowSelection="rowSelection"
+            @change="stdChange"
+            :scroll="{ x: scrollX }"
+            :size="size"
+            id="std-table"
+            @expandedRowsChange="expandedTable"
+            :expandedRowKeys="expand_keys_list"
         >
             <template
-                    v-slot:bodyCell="{text, record, index, column}"
+                v-slot:bodyCell="{text, record, index, column}"
             >
                 <template v-if="column.handle === true">
                     <span class="ant-table-drag-icon"><HolderOutlined/></span>
                     {{ text }}
                 </template>
                 <template v-if="column.dataIndex === 'action'">
-                    <a v-if="props.editable" @click="$emit('clickEdit', record[props.rowKey], record)">
+                    <a-button type="link" size="small" v-if="props.editable"
+                              @click="$emit('clickEdit', record[props.rowKey], record)">
                         {{ props.edit_text || $gettext('Modify') }}
-                    </a>
+                    </a-button>
                     <slot name="actions" :record="record"/>
                     <template v-if="props.deletable">
                         <a-divider type="vertical"/>
                         <a-popconfirm
-                                :cancelText="$gettext('No')"
-                                :okText="$gettext('OK')"
-                                :title="$gettext('Are you sure you want to delete?')"
-                                @confirm="destroy(record[rowKey])">
-                            <a v-translate>Delete</a>
+                            :cancelText="$gettext('No')"
+                            :okText="$gettext('OK')"
+                            :title="$gettext('Are you sure you want to delete?')"
+                            @confirm="destroy(record[rowKey])">
+                            <a-button type="link" size="small" v-translate>Delete</a-button>
                         </a-popconfirm>
                     </template>
                 </template>

+ 3 - 1
frontend/src/language/constants.ts

@@ -26,5 +26,7 @@ export const msg = [
     $gettext('Download latest release error'),
     $gettext('Performing core upgrade'),
     $gettext('Perform core upgrade error'),
-    $gettext('Upgraded successfully')
+    $gettext('Upgraded successfully'),
+    
+    $gettext('File exists')
 ]

+ 89 - 42
frontend/src/language/en/app.po

@@ -55,8 +55,8 @@ msgstr "Advance Mode"
 msgid "Arch"
 msgstr ""
 
-#: src/components/StdDataDisplay/StdTable.vue:54
-#: src/views/domain/DomainList.vue:26
+#: src/components/StdDataDisplay/StdTable.vue:55
+#: src/views/domain/DomainList.vue:29
 #, fuzzy
 msgid "Are you sure you want to delete?"
 msgstr "Are you sure you want to remove this directive?"
@@ -107,7 +107,7 @@ msgstr "Auto-renewal enabled for %{name}"
 
 #: 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/config/ConfigEdit.vue:72 src/views/domain/DomainEdit.vue:225
 #: src/views/nginx_log/NginxLog.vue:173
 msgid "Back"
 msgstr "Back"
@@ -211,11 +211,11 @@ msgstr "Content"
 msgid "Core Upgrade"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:64
+#: src/views/dashboard/DashBoard.vue:66
 msgid "CPU Status"
 msgstr "CPU Status"
 
-#: src/views/dashboard/DashBoard.vue:156
+#: src/views/dashboard/DashBoard.vue:22 src/views/dashboard/DashBoard.vue:23
 msgid "CPU:"
 msgstr "CPU:"
 
@@ -258,8 +258,10 @@ msgstr "Dashboard"
 msgid "Database (Optional, default: database)"
 msgstr "Database (Optional, default: database)"
 
-#: src/components/StdDataDisplay/StdTable.vue:527
-#: src/views/domain/DomainList.vue:115
+#: src/components/StdDataDisplay/StdTable.vue:528
+#: src/views/domain/DomainList.vue:19 src/views/domain/DomainList.vue:20
+#: src/views/domain/DomainList.vue:21 src/views/domain/DomainList.vue:28
+#: src/views/domain/DomainList.vue:32
 msgid "Delete"
 msgstr ""
 
@@ -310,18 +312,14 @@ msgstr "Disable auto-renewal failed for %{name}"
 msgid "Disabled"
 msgstr "Disabled"
 
-#: src/views/domain/DomainEdit.vue:143 src/views/domain/DomainList.vue:69
+#: src/views/domain/DomainEdit.vue:146 src/views/domain/DomainList.vue:69
 msgid "Disabled successfully"
 msgstr "Disabled successfully"
 
-#: src/views/dashboard/DashBoard.vue:96
+#: src/views/dashboard/DashBoard.vue:98
 msgid "Disk IO"
 msgstr "Disk IO"
 
-#: src/layouts/HeaderLayout.vue:15
-msgid "Do you want to reload Nginx?"
-msgstr ""
-
 #: src/views/cert/Cert.vue:32
 msgid "Domain"
 msgstr ""
@@ -338,6 +336,11 @@ msgstr ""
 msgid "Downloading latest release"
 msgstr ""
 
+#: src/views/domain/DomainList.vue:14 src/views/domain/DomainList.vue:15
+#: src/views/domain/DomainList.vue:16 src/views/domain/DomainList.vue:23
+msgid "Duplicate"
+msgstr ""
+
 #: src/views/domain/DomainEdit.vue:4 src/views/domain/DomainEdit.vue:5
 msgid "Edit %{n}"
 msgstr "Edit %{n}"
@@ -374,7 +377,7 @@ msgstr "Enable TLS"
 msgid "Enabled"
 msgstr "Enabled"
 
-#: src/views/domain/DomainAdd.vue:47 src/views/domain/DomainEdit.vue:134
+#: src/views/domain/DomainAdd.vue:47 src/views/domain/DomainEdit.vue:137
 #: src/views/domain/DomainList.vue:59
 msgid "Enabled successfully"
 msgstr "Enabled successfully"
@@ -407,11 +410,11 @@ msgstr "Expiration Date: %{date}"
 msgid "Export"
 msgstr ""
 
-#: src/views/domain/DomainEdit.vue:146 src/views/domain/DomainList.vue:73
+#: src/views/domain/DomainEdit.vue:149 src/views/domain/DomainList.vue:73
 msgid "Failed to disable %{msg}"
 msgstr "Failed to disable %{msg}"
 
-#: src/views/domain/DomainEdit.vue:137 src/views/domain/DomainList.vue:63
+#: src/views/domain/DomainEdit.vue:140 src/views/domain/DomainList.vue:63
 msgid "Failed to enable %{msg}"
 msgstr "Failed to enable %{msg}"
 
@@ -427,6 +430,10 @@ msgstr ""
 msgid "File"
 msgstr ""
 
+#: src/language/constants.ts:31
+msgid "File exists"
+msgstr ""
+
 #: src/views/other/Error.vue:3 src/views/other/Error.vue:4
 msgid "File Not Found"
 msgstr "File Not Found"
@@ -526,7 +533,7 @@ msgstr "Leave blank for no change"
 msgid "Light"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:144
+#: src/views/dashboard/DashBoard.vue:154
 msgid "Load Averages:"
 msgstr "Load Averages:"
 
@@ -572,11 +579,11 @@ msgstr "Manage Sites"
 msgid "Manage Users"
 msgstr "Manage Users"
 
-#: src/views/dashboard/DashBoard.vue:32
+#: src/views/dashboard/DashBoard.vue:34
 msgid "Memory"
 msgstr "Memory"
 
-#: src/views/dashboard/DashBoard.vue:29
+#: src/views/dashboard/DashBoard.vue:31
 msgid "Memory and Storage"
 msgstr "Memory and Storage"
 
@@ -606,19 +613,19 @@ msgstr "Single Directive"
 msgid "Name"
 msgstr "Name"
 
-#: src/views/dashboard/DashBoard.vue:74
+#: src/views/dashboard/DashBoard.vue:76
 msgid "Network"
 msgstr "Network"
 
-#: src/views/dashboard/DashBoard.vue:48
+#: src/views/dashboard/DashBoard.vue:50
 msgid "Network Statistics"
 msgstr "Network Statistics"
 
-#: src/views/dashboard/DashBoard.vue:52
+#: src/views/dashboard/DashBoard.vue:54
 msgid "Network Total Receive"
 msgstr "Network Total Receive"
 
-#: src/views/dashboard/DashBoard.vue:56
+#: src/views/dashboard/DashBoard.vue:58
 msgid "Network Total Send"
 msgstr "Network Total Send"
 
@@ -639,6 +646,12 @@ msgstr ""
 msgid "Nginx Configuration Parse Error"
 msgstr "Configuration Name"
 
+#: src/components/NginxControl/NginxControl.vue:4
+#: src/components/NginxControl/NginxControl.vue:5
+#: src/components/NginxControl/NginxControl.vue:9
+msgid "Nginx Control"
+msgstr ""
+
 #: src/views/preference/Preference.vue:36
 msgid "Nginx Error Log Path"
 msgstr ""
@@ -647,13 +660,18 @@ msgstr ""
 msgid "Nginx Log"
 msgstr ""
 
-#: src/layouts/HeaderLayout.vue:24
+#: src/components/NginxControl/NginxControl.vue:26
 #, fuzzy
 msgid "Nginx reloaded successfully"
 msgstr "Saved successfully"
 
-#: src/components/StdDataDisplay/StdTable.vue:52
-#: src/layouts/HeaderLayout.vue:17 src/views/domain/DomainList.vue:24
+#: src/components/NginxControl/NginxControl.vue:43
+#, fuzzy
+msgid "Nginx restarted successfully"
+msgstr "Saved successfully"
+
+#: src/components/StdDataDisplay/StdTable.vue:53
+#: src/views/domain/DomainList.vue:27
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:22
 #: src/views/domain/ngx_conf/LocationEditor.vue:26
 msgid "No"
@@ -677,9 +695,9 @@ msgstr ""
 
 #: src/components/StdDataDisplay/StdBatchEdit.vue:8
 #: src/components/StdDataDisplay/StdCurd.vue:28
-#: src/components/StdDataDisplay/StdTable.vue:53
+#: src/components/StdDataDisplay/StdTable.vue:54
 #: src/components/StdDataEntry/components/StdSelector.vue:12
-#: src/views/domain/DomainList.vue:25
+#: src/views/domain/DomainList.vue:28
 msgid "OK"
 msgstr ""
 
@@ -689,7 +707,7 @@ msgstr ""
 msgid "OS"
 msgstr "OS:"
 
-#: src/views/dashboard/DashBoard.vue:150
+#: src/views/dashboard/DashBoard.vue:160
 msgid "OS:"
 msgstr "OS:"
 
@@ -751,11 +769,11 @@ msgstr ""
 msgid "Project Team"
 msgstr "Project Team"
 
-#: src/views/dashboard/DashBoard.vue:107
+#: src/views/dashboard/DashBoard.vue:109
 msgid "Reads"
 msgstr "Reads"
 
-#: src/views/dashboard/DashBoard.vue:20 src/views/dashboard/DashBoard.vue:78
+#: src/views/dashboard/DashBoard.vue:20 src/views/dashboard/DashBoard.vue:80
 msgid "Receive"
 msgstr "Receive"
 
@@ -776,6 +794,16 @@ msgstr "Install"
 msgid "Release Note"
 msgstr ""
 
+#: src/components/NginxControl/NginxControl.vue:12
+#: src/components/NginxControl/NginxControl.vue:13
+#: src/components/NginxControl/NginxControl.vue:17
+msgid "Reload"
+msgstr ""
+
+#: src/components/NginxControl/NginxControl.vue:11
+msgid "Reloading"
+msgstr ""
+
 #: src/language/constants.ts:19
 msgid "Reloading nginx"
 msgstr ""
@@ -786,12 +814,26 @@ msgstr ""
 msgid "Reset"
 msgstr ""
 
+#: src/components/NginxControl/NginxControl.vue:11
+#: src/components/NginxControl/NginxControl.vue:12
+#: src/components/NginxControl/NginxControl.vue:16
+msgid "Restart"
+msgstr ""
+
+#: src/components/NginxControl/NginxControl.vue:12
+msgid "Restarting"
+msgstr ""
+
 #: src/views/preference/Preference.vue:8
 #, fuzzy
 msgid "Run Mode"
 msgstr "Advance Mode"
 
-#: src/views/config/ConfigEdit.vue:78 src/views/domain/DomainEdit.vue:225
+#: src/components/NginxControl/NginxControl.vue:10
+msgid "Running"
+msgstr ""
+
+#: src/views/config/ConfigEdit.vue:78 src/views/domain/DomainEdit.vue:228
 #: 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
@@ -824,7 +866,7 @@ msgid "Save Successfully"
 msgstr "Saved successfully"
 
 #: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:44
-#: src/views/domain/DomainEdit.vue:125
+#: src/views/domain/DomainEdit.vue:128
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:35
 msgid "Saved successfully"
 msgstr "Saved successfully"
@@ -833,17 +875,19 @@ msgstr "Saved successfully"
 msgid "Selector"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:21 src/views/dashboard/DashBoard.vue:85
+#: src/views/dashboard/DashBoard.vue:21 src/views/dashboard/DashBoard.vue:87
 msgid "Send"
 msgstr "Send"
 
+#: src/components/NginxControl/NginxControl.vue:33
+#: src/components/NginxControl/NginxControl.vue:50
 #: src/components/StdDataDisplay/StdBatchEdit.vue:43
 #: 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: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
+#: 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"
 msgstr "Server error"
 
@@ -897,7 +941,11 @@ msgstr "Certificate Status"
 msgid "Status"
 msgstr "Status"
 
-#: src/views/dashboard/DashBoard.vue:41
+#: src/components/NginxControl/NginxControl.vue:13
+msgid "Stopped"
+msgstr ""
+
+#: src/views/dashboard/DashBoard.vue:43
 msgid "Storage"
 msgstr "Storage"
 
@@ -905,7 +953,7 @@ msgstr "Storage"
 msgid "Subject Name: %{name}"
 msgstr "Subject Name: %{name}"
 
-#: src/views/dashboard/DashBoard.vue:36
+#: src/views/dashboard/DashBoard.vue:38
 msgid "Swap"
 msgstr "Swap"
 
@@ -986,7 +1034,7 @@ msgstr "Saved successfully"
 msgid "Upgrading Nginx UI, please wait..."
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:140
+#: src/views/dashboard/DashBoard.vue:150
 msgid "Uptime:"
 msgstr "Uptime:"
 
@@ -1013,7 +1061,7 @@ msgstr ""
 msgid "Warning"
 msgstr "Warning"
 
-#: src/views/dashboard/DashBoard.vue:100 src/views/dashboard/DashBoard.vue:22
+#: src/views/dashboard/DashBoard.vue:102 src/views/dashboard/DashBoard.vue:22
 #: src/views/dashboard/DashBoard.vue:23
 msgid "Writes"
 msgstr "Writes"
@@ -1026,7 +1074,6 @@ msgstr ""
 msgid "Writing certificate to disk"
 msgstr ""
 
-#: src/layouts/HeaderLayout.vue:16
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:21
 #: src/views/domain/ngx_conf/LocationEditor.vue:25
 msgid "Yes"

+ 90 - 41
frontend/src/language/messages.pot

@@ -55,8 +55,8 @@ msgstr ""
 msgid "Arch"
 msgstr ""
 
-#: src/components/StdDataDisplay/StdTable.vue:54
-#: src/views/domain/DomainList.vue:26
+#: src/components/StdDataDisplay/StdTable.vue:55
+#: src/views/domain/DomainList.vue:29
 msgid "Are you sure you want to delete?"
 msgstr ""
 
@@ -109,7 +109,7 @@ msgstr ""
 #: 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/domain/DomainEdit.vue:225
 #: src/views/nginx_log/NginxLog.vue:173
 msgid "Back"
 msgstr ""
@@ -213,11 +213,12 @@ msgstr ""
 msgid "Core Upgrade"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:64
+#: src/views/dashboard/DashBoard.vue:66
 msgid "CPU Status"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:156
+#: src/views/dashboard/DashBoard.vue:22
+#: src/views/dashboard/DashBoard.vue:23
 msgid "CPU:"
 msgstr ""
 
@@ -262,8 +263,12 @@ msgstr ""
 msgid "Database (Optional, default: database)"
 msgstr ""
 
-#: src/components/StdDataDisplay/StdTable.vue:527
-#: src/views/domain/DomainList.vue:115
+#: src/components/StdDataDisplay/StdTable.vue:528
+#: src/views/domain/DomainList.vue:19
+#: src/views/domain/DomainList.vue:20
+#: src/views/domain/DomainList.vue:21
+#: src/views/domain/DomainList.vue:28
+#: src/views/domain/DomainList.vue:32
 msgid "Delete"
 msgstr ""
 
@@ -319,19 +324,15 @@ msgstr ""
 msgid "Disabled"
 msgstr ""
 
-#: src/views/domain/DomainEdit.vue:143
+#: src/views/domain/DomainEdit.vue:146
 #: src/views/domain/DomainList.vue:69
 msgid "Disabled successfully"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:96
+#: src/views/dashboard/DashBoard.vue:98
 msgid "Disk IO"
 msgstr ""
 
-#: src/layouts/HeaderLayout.vue:15
-msgid "Do you want to reload Nginx?"
-msgstr ""
-
 #: src/views/cert/Cert.vue:32
 msgid "Domain"
 msgstr ""
@@ -348,6 +349,13 @@ msgstr ""
 msgid "Downloading latest release"
 msgstr ""
 
+#: src/views/domain/DomainList.vue:14
+#: src/views/domain/DomainList.vue:15
+#: src/views/domain/DomainList.vue:16
+#: src/views/domain/DomainList.vue:23
+msgid "Duplicate"
+msgstr ""
+
 #: src/views/domain/DomainEdit.vue:4
 #: src/views/domain/DomainEdit.vue:5
 msgid "Edit %{n}"
@@ -392,7 +400,7 @@ msgid "Enabled"
 msgstr ""
 
 #: src/views/domain/DomainAdd.vue:47
-#: src/views/domain/DomainEdit.vue:134
+#: src/views/domain/DomainEdit.vue:137
 #: src/views/domain/DomainList.vue:59
 msgid "Enabled successfully"
 msgstr ""
@@ -428,12 +436,12 @@ msgstr ""
 msgid "Export"
 msgstr ""
 
-#: src/views/domain/DomainEdit.vue:146
+#: src/views/domain/DomainEdit.vue:149
 #: src/views/domain/DomainList.vue:73
 msgid "Failed to disable %{msg}"
 msgstr ""
 
-#: src/views/domain/DomainEdit.vue:137
+#: src/views/domain/DomainEdit.vue:140
 #: src/views/domain/DomainList.vue:63
 msgid "Failed to enable %{msg}"
 msgstr ""
@@ -450,6 +458,10 @@ msgstr ""
 msgid "File"
 msgstr ""
 
+#: src/language/constants.ts:31
+msgid "File exists"
+msgstr ""
+
 #: src/views/other/Error.vue:3
 #: src/views/other/Error.vue:4
 msgid "File Not Found"
@@ -549,7 +561,7 @@ msgstr ""
 msgid "Light"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:144
+#: src/views/dashboard/DashBoard.vue:154
 msgid "Load Averages:"
 msgstr ""
 
@@ -594,11 +606,11 @@ msgstr ""
 msgid "Manage Users"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:32
+#: src/views/dashboard/DashBoard.vue:34
 msgid "Memory"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:29
+#: src/views/dashboard/DashBoard.vue:31
 msgid "Memory and Storage"
 msgstr ""
 
@@ -628,19 +640,19 @@ msgstr ""
 msgid "Name"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:74
+#: src/views/dashboard/DashBoard.vue:76
 msgid "Network"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:48
+#: src/views/dashboard/DashBoard.vue:50
 msgid "Network Statistics"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:52
+#: src/views/dashboard/DashBoard.vue:54
 msgid "Network Total Receive"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:56
+#: src/views/dashboard/DashBoard.vue:58
 msgid "Network Total Send"
 msgstr ""
 
@@ -660,6 +672,12 @@ msgstr ""
 msgid "Nginx Configuration Parse Error"
 msgstr ""
 
+#: src/components/NginxControl/NginxControl.vue:4
+#: src/components/NginxControl/NginxControl.vue:5
+#: src/components/NginxControl/NginxControl.vue:9
+msgid "Nginx Control"
+msgstr ""
+
 #: src/views/preference/Preference.vue:36
 msgid "Nginx Error Log Path"
 msgstr ""
@@ -669,13 +687,16 @@ msgstr ""
 msgid "Nginx Log"
 msgstr ""
 
-#: src/layouts/HeaderLayout.vue:24
+#: src/components/NginxControl/NginxControl.vue:26
 msgid "Nginx reloaded successfully"
 msgstr ""
 
-#: src/components/StdDataDisplay/StdTable.vue:52
-#: src/layouts/HeaderLayout.vue:17
-#: src/views/domain/DomainList.vue:24
+#: src/components/NginxControl/NginxControl.vue:43
+msgid "Nginx restarted successfully"
+msgstr ""
+
+#: src/components/StdDataDisplay/StdTable.vue:53
+#: src/views/domain/DomainList.vue:27
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:22
 #: src/views/domain/ngx_conf/LocationEditor.vue:26
 msgid "No"
@@ -701,9 +722,9 @@ msgstr ""
 
 #: src/components/StdDataDisplay/StdBatchEdit.vue:8
 #: src/components/StdDataDisplay/StdCurd.vue:28
-#: src/components/StdDataDisplay/StdTable.vue:53
+#: src/components/StdDataDisplay/StdTable.vue:54
 #: src/components/StdDataEntry/components/StdSelector.vue:12
-#: src/views/domain/DomainList.vue:25
+#: src/views/domain/DomainList.vue:28
 msgid "OK"
 msgstr ""
 
@@ -714,7 +735,7 @@ msgstr ""
 msgid "OS"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:150
+#: src/views/dashboard/DashBoard.vue:160
 msgid "OS:"
 msgstr ""
 
@@ -779,12 +800,12 @@ msgstr ""
 msgid "Project Team"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:107
+#: src/views/dashboard/DashBoard.vue:109
 msgid "Reads"
 msgstr ""
 
 #: src/views/dashboard/DashBoard.vue:20
-#: src/views/dashboard/DashBoard.vue:78
+#: src/views/dashboard/DashBoard.vue:80
 msgid "Receive"
 msgstr ""
 
@@ -810,6 +831,16 @@ msgstr ""
 msgid "Release Note"
 msgstr ""
 
+#: src/components/NginxControl/NginxControl.vue:12
+#: src/components/NginxControl/NginxControl.vue:13
+#: src/components/NginxControl/NginxControl.vue:17
+msgid "Reload"
+msgstr ""
+
+#: src/components/NginxControl/NginxControl.vue:11
+msgid "Reloading"
+msgstr ""
+
 #: src/language/constants.ts:19
 msgid "Reloading nginx"
 msgstr ""
@@ -820,12 +851,26 @@ msgstr ""
 msgid "Reset"
 msgstr ""
 
+#: src/components/NginxControl/NginxControl.vue:11
+#: src/components/NginxControl/NginxControl.vue:12
+#: src/components/NginxControl/NginxControl.vue:16
+msgid "Restart"
+msgstr ""
+
+#: src/components/NginxControl/NginxControl.vue:12
+msgid "Restarting"
+msgstr ""
+
 #: src/views/preference/Preference.vue:8
 msgid "Run Mode"
 msgstr ""
 
+#: src/components/NginxControl/NginxControl.vue:10
+msgid "Running"
+msgstr ""
+
 #: src/views/config/ConfigEdit.vue:78
-#: src/views/domain/DomainEdit.vue:225
+#: src/views/domain/DomainEdit.vue:228
 #: 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
@@ -858,7 +903,7 @@ msgstr ""
 
 #: src/views/config/ConfigEdit.vue:44
 #: src/views/domain/DomainAdd.vue:44
-#: src/views/domain/DomainEdit.vue:125
+#: src/views/domain/DomainEdit.vue:128
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:35
 msgid "Saved successfully"
 msgstr ""
@@ -868,15 +913,16 @@ msgid "Selector"
 msgstr ""
 
 #: src/views/dashboard/DashBoard.vue:21
-#: src/views/dashboard/DashBoard.vue:85
+#: src/views/dashboard/DashBoard.vue:87
 msgid "Send"
 msgstr ""
 
+#: src/components/NginxControl/NginxControl.vue:33
+#: src/components/NginxControl/NginxControl.vue:50
 #: src/components/StdDataDisplay/StdBatchEdit.vue:43
 #: 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:32
 #: src/views/domain/DomainEdit.vue:87
 #: src/views/domain/DomainList.vue:83
@@ -931,7 +977,11 @@ msgstr ""
 msgid "Status"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:41
+#: src/components/NginxControl/NginxControl.vue:13
+msgid "Stopped"
+msgstr ""
+
+#: src/views/dashboard/DashBoard.vue:43
 msgid "Storage"
 msgstr ""
 
@@ -939,7 +989,7 @@ msgstr ""
 msgid "Subject Name: %{name}"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:36
+#: src/views/dashboard/DashBoard.vue:38
 msgid "Swap"
 msgstr ""
 
@@ -1015,7 +1065,7 @@ msgstr ""
 msgid "Upgrading Nginx UI, please wait..."
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:140
+#: src/views/dashboard/DashBoard.vue:150
 msgid "Uptime:"
 msgstr ""
 
@@ -1044,7 +1094,7 @@ msgstr ""
 msgid "Warning"
 msgstr ""
 
-#: src/views/dashboard/DashBoard.vue:100
+#: src/views/dashboard/DashBoard.vue:102
 #: src/views/dashboard/DashBoard.vue:22
 #: src/views/dashboard/DashBoard.vue:23
 msgid "Writes"
@@ -1058,7 +1108,6 @@ msgstr ""
 msgid "Writing certificate to disk"
 msgstr ""
 
-#: src/layouts/HeaderLayout.vue:16
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:21
 #: src/views/domain/ngx_conf/LocationEditor.vue:25
 msgid "Yes"

File diff ditekan karena terlalu besar
+ 0 - 0
frontend/src/language/translations.json


TEMPAT SAMPAH
frontend/src/language/zh_CN/app.mo


+ 91 - 45
frontend/src/language/zh_CN/app.po

@@ -58,8 +58,8 @@ msgstr "高级模式"
 msgid "Arch"
 msgstr "架构"
 
-#: src/components/StdDataDisplay/StdTable.vue:54
-#: src/views/domain/DomainList.vue:26
+#: src/components/StdDataDisplay/StdTable.vue:55
+#: src/views/domain/DomainList.vue:29
 msgid "Are you sure you want to delete?"
 msgstr "您确定要删除吗?"
 
@@ -108,7 +108,7 @@ msgstr "成功启用 %{name} 自动续签"
 
 #: 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/config/ConfigEdit.vue:72 src/views/domain/DomainEdit.vue:225
 #: src/views/nginx_log/NginxLog.vue:173
 msgid "Back"
 msgstr "返回"
@@ -207,11 +207,11 @@ msgstr "内容"
 msgid "Core Upgrade"
 msgstr "核心升级"
 
-#: src/views/dashboard/DashBoard.vue:64
+#: src/views/dashboard/DashBoard.vue:66
 msgid "CPU Status"
 msgstr "CPU 状态"
 
-#: src/views/dashboard/DashBoard.vue:156
+#: src/views/dashboard/DashBoard.vue:22 src/views/dashboard/DashBoard.vue:23
 msgid "CPU:"
 msgstr "CPU:"
 
@@ -254,8 +254,10 @@ msgstr "仪表盘"
 msgid "Database (Optional, default: database)"
 msgstr "数据库 (可选,默认: database)"
 
-#: src/components/StdDataDisplay/StdTable.vue:527
-#: src/views/domain/DomainList.vue:115
+#: src/components/StdDataDisplay/StdTable.vue:528
+#: src/views/domain/DomainList.vue:19 src/views/domain/DomainList.vue:20
+#: src/views/domain/DomainList.vue:21 src/views/domain/DomainList.vue:28
+#: src/views/domain/DomainList.vue:32
 msgid "Delete"
 msgstr "删除"
 
@@ -306,18 +308,14 @@ msgstr "关闭 %{name} 自动续签失败"
 msgid "Disabled"
 msgstr "禁用"
 
-#: src/views/domain/DomainEdit.vue:143 src/views/domain/DomainList.vue:69
+#: src/views/domain/DomainEdit.vue:146 src/views/domain/DomainList.vue:69
 msgid "Disabled successfully"
 msgstr "禁用成功"
 
-#: src/views/dashboard/DashBoard.vue:96
+#: src/views/dashboard/DashBoard.vue:98
 msgid "Disk IO"
 msgstr "磁盘 IO"
 
-#: src/layouts/HeaderLayout.vue:15
-msgid "Do you want to reload Nginx?"
-msgstr "你需要重载 Nginx 吗?"
-
 #: src/views/cert/Cert.vue:32
 msgid "Domain"
 msgstr "域名"
@@ -334,6 +332,11 @@ msgstr "下载最新版本错误"
 msgid "Downloading latest release"
 msgstr "下载最新版本"
 
+#: src/views/domain/DomainList.vue:14 src/views/domain/DomainList.vue:15
+#: src/views/domain/DomainList.vue:16 src/views/domain/DomainList.vue:23
+msgid "Duplicate"
+msgstr "复制"
+
 #: src/views/domain/DomainEdit.vue:4 src/views/domain/DomainEdit.vue:5
 msgid "Edit %{n}"
 msgstr "编辑 %{n}"
@@ -370,7 +373,7 @@ msgstr "启用 TLS"
 msgid "Enabled"
 msgstr "启用"
 
-#: src/views/domain/DomainAdd.vue:47 src/views/domain/DomainEdit.vue:134
+#: src/views/domain/DomainAdd.vue:47 src/views/domain/DomainEdit.vue:137
 #: src/views/domain/DomainList.vue:59
 msgid "Enabled successfully"
 msgstr "启用成功"
@@ -403,11 +406,11 @@ msgstr "过期时间: %{date}"
 msgid "Export"
 msgstr "导出"
 
-#: src/views/domain/DomainEdit.vue:146 src/views/domain/DomainList.vue:73
+#: src/views/domain/DomainEdit.vue:149 src/views/domain/DomainList.vue:73
 msgid "Failed to disable %{msg}"
 msgstr "禁用失败 %{msg}"
 
-#: src/views/domain/DomainEdit.vue:137 src/views/domain/DomainList.vue:63
+#: src/views/domain/DomainEdit.vue:140 src/views/domain/DomainList.vue:63
 msgid "Failed to enable %{msg}"
 msgstr "启用失败 %{msg}"
 
@@ -423,6 +426,10 @@ msgstr "保存失败,在配置中检测到语法错误。"
 msgid "File"
 msgstr "文件"
 
+#: src/language/constants.ts:31
+msgid "File exists"
+msgstr "文件已存在"
+
 #: src/views/other/Error.vue:3 src/views/other/Error.vue:4
 msgid "File Not Found"
 msgstr "未找到文件"
@@ -517,7 +524,7 @@ msgstr "留空表示不修改"
 msgid "Light"
 msgstr "浅色"
 
-#: src/views/dashboard/DashBoard.vue:144
+#: src/views/dashboard/DashBoard.vue:154
 msgid "Load Averages:"
 msgstr "系统负载:"
 
@@ -563,11 +570,11 @@ msgstr "网站管理"
 msgid "Manage Users"
 msgstr "用户管理"
 
-#: src/views/dashboard/DashBoard.vue:32
+#: src/views/dashboard/DashBoard.vue:34
 msgid "Memory"
 msgstr "内存"
 
-#: src/views/dashboard/DashBoard.vue:29
+#: src/views/dashboard/DashBoard.vue:31
 msgid "Memory and Storage"
 msgstr "内存与存储"
 
@@ -595,19 +602,19 @@ msgstr "单行指令"
 msgid "Name"
 msgstr "名称"
 
-#: src/views/dashboard/DashBoard.vue:74
+#: src/views/dashboard/DashBoard.vue:76
 msgid "Network"
 msgstr "网络"
 
-#: src/views/dashboard/DashBoard.vue:48
+#: src/views/dashboard/DashBoard.vue:50
 msgid "Network Statistics"
 msgstr "流量统计"
 
-#: src/views/dashboard/DashBoard.vue:52
+#: src/views/dashboard/DashBoard.vue:54
 msgid "Network Total Receive"
 msgstr "下载流量"
 
-#: src/views/dashboard/DashBoard.vue:56
+#: src/views/dashboard/DashBoard.vue:58
 msgid "Network Total Send"
 msgstr "上传流量"
 
@@ -627,6 +634,12 @@ msgstr "Nginx 访问日志路径"
 msgid "Nginx Configuration Parse Error"
 msgstr "Nginx 配置解析错误"
 
+#: src/components/NginxControl/NginxControl.vue:4
+#: src/components/NginxControl/NginxControl.vue:5
+#: src/components/NginxControl/NginxControl.vue:9
+msgid "Nginx Control"
+msgstr "控制 Nginx"
+
 #: src/views/preference/Preference.vue:36
 msgid "Nginx Error Log Path"
 msgstr "Nginx 错误日志路径"
@@ -635,12 +648,16 @@ msgstr "Nginx 错误日志路径"
 msgid "Nginx Log"
 msgstr "Nginx 日志"
 
-#: src/layouts/HeaderLayout.vue:24
+#: src/components/NginxControl/NginxControl.vue:26
 msgid "Nginx reloaded successfully"
 msgstr "Nginx 重载成功"
 
-#: src/components/StdDataDisplay/StdTable.vue:52
-#: src/layouts/HeaderLayout.vue:17 src/views/domain/DomainList.vue:24
+#: src/components/NginxControl/NginxControl.vue:43
+msgid "Nginx restarted successfully"
+msgstr "Nginx 重启成功"
+
+#: src/components/StdDataDisplay/StdTable.vue:53
+#: src/views/domain/DomainList.vue:27
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:22
 #: src/views/domain/ngx_conf/LocationEditor.vue:26
 msgid "No"
@@ -664,9 +681,9 @@ msgstr "正在获取证书"
 
 #: src/components/StdDataDisplay/StdBatchEdit.vue:8
 #: src/components/StdDataDisplay/StdCurd.vue:28
-#: src/components/StdDataDisplay/StdTable.vue:53
+#: src/components/StdDataDisplay/StdTable.vue:54
 #: src/components/StdDataEntry/components/StdSelector.vue:12
-#: src/views/domain/DomainList.vue:25
+#: src/views/domain/DomainList.vue:28
 msgid "OK"
 msgstr "确定"
 
@@ -675,7 +692,7 @@ msgstr "确定"
 msgid "OS"
 msgstr "OS"
 
-#: src/views/dashboard/DashBoard.vue:150
+#: src/views/dashboard/DashBoard.vue:160
 msgid "OS:"
 msgstr "OS:"
 
@@ -736,11 +753,11 @@ msgstr "禁止删除默认用户"
 msgid "Project Team"
 msgstr "项目团队"
 
-#: src/views/dashboard/DashBoard.vue:107
+#: src/views/dashboard/DashBoard.vue:109
 msgid "Reads"
 msgstr "读"
 
-#: src/views/dashboard/DashBoard.vue:20 src/views/dashboard/DashBoard.vue:78
+#: src/views/dashboard/DashBoard.vue:20 src/views/dashboard/DashBoard.vue:80
 msgid "Receive"
 msgstr "下载"
 
@@ -760,6 +777,16 @@ msgstr "重新安装"
 msgid "Release Note"
 msgstr "发行日志"
 
+#: src/components/NginxControl/NginxControl.vue:12
+#: src/components/NginxControl/NginxControl.vue:13
+#: src/components/NginxControl/NginxControl.vue:17
+msgid "Reload"
+msgstr "重载"
+
+#: src/components/NginxControl/NginxControl.vue:11
+msgid "Reloading"
+msgstr "重载中"
+
 #: src/language/constants.ts:19
 msgid "Reloading nginx"
 msgstr "正在重载 Nginx"
@@ -770,11 +797,25 @@ msgstr "正在重载 Nginx"
 msgid "Reset"
 msgstr "重置"
 
+#: src/components/NginxControl/NginxControl.vue:11
+#: src/components/NginxControl/NginxControl.vue:12
+#: src/components/NginxControl/NginxControl.vue:16
+msgid "Restart"
+msgstr "重启"
+
+#: src/components/NginxControl/NginxControl.vue:12
+msgid "Restarting"
+msgstr "重启中"
+
 #: src/views/preference/Preference.vue:8
 msgid "Run Mode"
 msgstr "运行模式"
 
-#: src/views/config/ConfigEdit.vue:78 src/views/domain/DomainEdit.vue:225
+#: src/components/NginxControl/NginxControl.vue:10
+msgid "Running"
+msgstr "运行中"
+
+#: src/views/config/ConfigEdit.vue:78 src/views/domain/DomainEdit.vue:228
 #: 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
@@ -805,7 +846,7 @@ msgid "Save Successfully"
 msgstr "保存成功"
 
 #: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:44
-#: src/views/domain/DomainEdit.vue:125
+#: src/views/domain/DomainEdit.vue:128
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:35
 msgid "Saved successfully"
 msgstr "保存成功"
@@ -814,17 +855,19 @@ msgstr "保存成功"
 msgid "Selector"
 msgstr "选择器"
 
-#: src/views/dashboard/DashBoard.vue:21 src/views/dashboard/DashBoard.vue:85
+#: src/views/dashboard/DashBoard.vue:21 src/views/dashboard/DashBoard.vue:87
 msgid "Send"
 msgstr "上传"
 
+#: src/components/NginxControl/NginxControl.vue:33
+#: src/components/NginxControl/NginxControl.vue:50
 #: src/components/StdDataDisplay/StdBatchEdit.vue:43
 #: 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: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
+#: 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"
 msgstr "服务器错误"
 
@@ -873,7 +916,11 @@ msgstr "SSL证书密钥内容"
 msgid "Status"
 msgstr "状态"
 
-#: src/views/dashboard/DashBoard.vue:41
+#: src/components/NginxControl/NginxControl.vue:13
+msgid "Stopped"
+msgstr "已停止"
+
+#: src/views/dashboard/DashBoard.vue:43
 msgid "Storage"
 msgstr "存储"
 
@@ -881,7 +928,7 @@ msgstr "存储"
 msgid "Subject Name: %{name}"
 msgstr "主体名称: %{name}"
 
-#: src/views/dashboard/DashBoard.vue:36
+#: src/views/dashboard/DashBoard.vue:38
 msgid "Swap"
 msgstr "Swap"
 
@@ -955,7 +1002,7 @@ msgstr "升级成功"
 msgid "Upgrading Nginx UI, please wait..."
 msgstr "正在升级Nginx UI,请等待..."
 
-#: src/views/dashboard/DashBoard.vue:140
+#: src/views/dashboard/DashBoard.vue:150
 msgid "Uptime:"
 msgstr "运行时间:"
 
@@ -982,7 +1029,7 @@ msgstr "查看"
 msgid "Warning"
 msgstr "警告"
 
-#: src/views/dashboard/DashBoard.vue:100 src/views/dashboard/DashBoard.vue:22
+#: src/views/dashboard/DashBoard.vue:102 src/views/dashboard/DashBoard.vue:22
 #: src/views/dashboard/DashBoard.vue:23
 msgid "Writes"
 msgstr "写"
@@ -995,7 +1042,6 @@ msgstr "正在将证书私钥写入磁盘"
 msgid "Writing certificate to disk"
 msgstr "正在将证书写入磁盘"
 
-#: src/layouts/HeaderLayout.vue:16
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:21
 #: src/views/domain/ngx_conf/LocationEditor.vue:25
 msgid "Yes"
@@ -1015,6 +1061,9 @@ msgctxt "Project"
 msgid "License"
 msgstr "开源许可"
 
+#~ msgid "Do you want to reload Nginx?"
+#~ msgstr "你需要重载 Nginx 吗?"
+
 #~ msgid "Are you sure you want to delete ?"
 #~ msgstr "您确定要删除吗?"
 
@@ -1051,9 +1100,6 @@ msgstr "开源许可"
 #~ msgid "No, I'm rethink"
 #~ msgstr "再想想"
 
-#~ msgid "Restore"
-#~ msgstr "反删除"
-
 #~ msgid "Yes, I'm sure"
 #~ msgstr "是的"
 

TEMPAT SAMPAH
frontend/src/language/zh_TW/app.mo


+ 91 - 45
frontend/src/language/zh_TW/app.po

@@ -59,8 +59,8 @@ msgstr "高階模式"
 msgid "Arch"
 msgstr "架搆"
 
-#: src/components/StdDataDisplay/StdTable.vue:54
-#: src/views/domain/DomainList.vue:26
+#: src/components/StdDataDisplay/StdTable.vue:55
+#: src/views/domain/DomainList.vue:29
 msgid "Are you sure you want to delete?"
 msgstr "你確定你要刪除?"
 
@@ -109,7 +109,7 @@ msgstr "已啟用 %{name} 自動續簽"
 
 #: 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/config/ConfigEdit.vue:72 src/views/domain/DomainEdit.vue:225
 #: src/views/nginx_log/NginxLog.vue:173
 msgid "Back"
 msgstr "返回"
@@ -208,11 +208,11 @@ msgstr "內容"
 msgid "Core Upgrade"
 msgstr "核心升級"
 
-#: src/views/dashboard/DashBoard.vue:64
+#: src/views/dashboard/DashBoard.vue:66
 msgid "CPU Status"
 msgstr "中央處理器狀態"
 
-#: src/views/dashboard/DashBoard.vue:156
+#: src/views/dashboard/DashBoard.vue:22 src/views/dashboard/DashBoard.vue:23
 msgid "CPU:"
 msgstr "中央處理器:"
 
@@ -255,8 +255,10 @@ msgstr "儀表盤"
 msgid "Database (Optional, default: database)"
 msgstr "資料庫 (可選,預設: database)"
 
-#: src/components/StdDataDisplay/StdTable.vue:527
-#: src/views/domain/DomainList.vue:115
+#: src/components/StdDataDisplay/StdTable.vue:528
+#: src/views/domain/DomainList.vue:19 src/views/domain/DomainList.vue:20
+#: src/views/domain/DomainList.vue:21 src/views/domain/DomainList.vue:28
+#: src/views/domain/DomainList.vue:32
 msgid "Delete"
 msgstr "刪除"
 
@@ -307,18 +309,14 @@ msgstr "關閉 %{name} 自動續簽失敗"
 msgid "Disabled"
 msgstr "禁用"
 
-#: src/views/domain/DomainEdit.vue:143 src/views/domain/DomainList.vue:69
+#: src/views/domain/DomainEdit.vue:146 src/views/domain/DomainList.vue:69
 msgid "Disabled successfully"
 msgstr "禁用成功"
 
-#: src/views/dashboard/DashBoard.vue:96
+#: src/views/dashboard/DashBoard.vue:98
 msgid "Disk IO"
 msgstr "磁碟 IO"
 
-#: src/layouts/HeaderLayout.vue:15
-msgid "Do you want to reload Nginx?"
-msgstr "你想重載 Nginx 嗎?"
-
 #: src/views/cert/Cert.vue:32
 msgid "Domain"
 msgstr "網域"
@@ -335,6 +333,11 @@ msgstr "下載最新版本錯誤"
 msgid "Downloading latest release"
 msgstr "正在下載最新版本"
 
+#: src/views/domain/DomainList.vue:14 src/views/domain/DomainList.vue:15
+#: src/views/domain/DomainList.vue:16 src/views/domain/DomainList.vue:23
+msgid "Duplicate"
+msgstr "複製"
+
 #: src/views/domain/DomainEdit.vue:4 src/views/domain/DomainEdit.vue:5
 msgid "Edit %{n}"
 msgstr "編輯 %{n}"
@@ -371,7 +374,7 @@ msgstr "啟用 TLS"
 msgid "Enabled"
 msgstr "啟用"
 
-#: src/views/domain/DomainAdd.vue:47 src/views/domain/DomainEdit.vue:134
+#: src/views/domain/DomainAdd.vue:47 src/views/domain/DomainEdit.vue:137
 #: src/views/domain/DomainList.vue:59
 msgid "Enabled successfully"
 msgstr "啟用成功"
@@ -404,11 +407,11 @@ msgstr "過期時間: %{date}"
 msgid "Export"
 msgstr "導出"
 
-#: src/views/domain/DomainEdit.vue:146 src/views/domain/DomainList.vue:73
+#: src/views/domain/DomainEdit.vue:149 src/views/domain/DomainList.vue:73
 msgid "Failed to disable %{msg}"
 msgstr "禁用失敗 %{msg}"
 
-#: src/views/domain/DomainEdit.vue:137 src/views/domain/DomainList.vue:63
+#: src/views/domain/DomainEdit.vue:140 src/views/domain/DomainList.vue:63
 msgid "Failed to enable %{msg}"
 msgstr "啟用失敗 %{msg}"
 
@@ -424,6 +427,10 @@ msgstr "保存失敗,在配置中檢測到語法錯誤。"
 msgid "File"
 msgstr "文件"
 
+#: src/language/constants.ts:31
+msgid "File exists"
+msgstr "文件已存在"
+
 #: src/views/other/Error.vue:3 src/views/other/Error.vue:4
 msgid "File Not Found"
 msgstr "未找到檔案"
@@ -518,7 +525,7 @@ msgstr "留空表示不修改"
 msgid "Light"
 msgstr "淺色"
 
-#: src/views/dashboard/DashBoard.vue:144
+#: src/views/dashboard/DashBoard.vue:154
 msgid "Load Averages:"
 msgstr "系統負載:"
 
@@ -564,11 +571,11 @@ msgstr "網站管理"
 msgid "Manage Users"
 msgstr "使用者管理"
 
-#: src/views/dashboard/DashBoard.vue:32
+#: src/views/dashboard/DashBoard.vue:34
 msgid "Memory"
 msgstr "記憶體"
 
-#: src/views/dashboard/DashBoard.vue:29
+#: src/views/dashboard/DashBoard.vue:31
 msgid "Memory and Storage"
 msgstr "記憶體和存儲"
 
@@ -596,19 +603,19 @@ msgstr "多行指令"
 msgid "Name"
 msgstr "名稱"
 
-#: src/views/dashboard/DashBoard.vue:74
+#: src/views/dashboard/DashBoard.vue:76
 msgid "Network"
 msgstr "網路"
 
-#: src/views/dashboard/DashBoard.vue:48
+#: src/views/dashboard/DashBoard.vue:50
 msgid "Network Statistics"
 msgstr "網路統計"
 
-#: src/views/dashboard/DashBoard.vue:52
+#: src/views/dashboard/DashBoard.vue:54
 msgid "Network Total Receive"
 msgstr "下載流量"
 
-#: src/views/dashboard/DashBoard.vue:56
+#: src/views/dashboard/DashBoard.vue:58
 msgid "Network Total Send"
 msgstr "上傳流量"
 
@@ -628,6 +635,12 @@ msgstr "Nginx 訪問日誌路徑"
 msgid "Nginx Configuration Parse Error"
 msgstr "Nginx 配置解析錯誤"
 
+#: src/components/NginxControl/NginxControl.vue:4
+#: src/components/NginxControl/NginxControl.vue:5
+#: src/components/NginxControl/NginxControl.vue:9
+msgid "Nginx Control"
+msgstr "Nginx 控件"
+
 #: src/views/preference/Preference.vue:36
 msgid "Nginx Error Log Path"
 msgstr "Nginx 錯誤日誌路徑"
@@ -636,12 +649,16 @@ msgstr "Nginx 錯誤日誌路徑"
 msgid "Nginx Log"
 msgstr "Nginx 日誌"
 
-#: src/layouts/HeaderLayout.vue:24
+#: src/components/NginxControl/NginxControl.vue:26
 msgid "Nginx reloaded successfully"
 msgstr "Nginx 重載成功"
 
-#: src/components/StdDataDisplay/StdTable.vue:52
-#: src/layouts/HeaderLayout.vue:17 src/views/domain/DomainList.vue:24
+#: src/components/NginxControl/NginxControl.vue:43
+msgid "Nginx restarted successfully"
+msgstr "Nginx 重啟成功"
+
+#: src/components/StdDataDisplay/StdTable.vue:53
+#: src/views/domain/DomainList.vue:27
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:22
 #: src/views/domain/ngx_conf/LocationEditor.vue:26
 msgid "No"
@@ -665,9 +682,9 @@ msgstr "正在獲取證書"
 
 #: src/components/StdDataDisplay/StdBatchEdit.vue:8
 #: src/components/StdDataDisplay/StdCurd.vue:28
-#: src/components/StdDataDisplay/StdTable.vue:53
+#: src/components/StdDataDisplay/StdTable.vue:54
 #: src/components/StdDataEntry/components/StdSelector.vue:12
-#: src/views/domain/DomainList.vue:25
+#: src/views/domain/DomainList.vue:28
 msgid "OK"
 msgstr "確定"
 
@@ -676,7 +693,7 @@ msgstr "確定"
 msgid "OS"
 msgstr "作業系統"
 
-#: src/views/dashboard/DashBoard.vue:150
+#: src/views/dashboard/DashBoard.vue:160
 msgid "OS:"
 msgstr "作業系統:"
 
@@ -737,11 +754,11 @@ msgstr "禁止刪除默認用戶"
 msgid "Project Team"
 msgstr "專案團隊"
 
-#: src/views/dashboard/DashBoard.vue:107
+#: src/views/dashboard/DashBoard.vue:109
 msgid "Reads"
 msgstr "讀"
 
-#: src/views/dashboard/DashBoard.vue:20 src/views/dashboard/DashBoard.vue:78
+#: src/views/dashboard/DashBoard.vue:20 src/views/dashboard/DashBoard.vue:80
 msgid "Receive"
 msgstr "下載"
 
@@ -761,6 +778,16 @@ msgstr "安裝"
 msgid "Release Note"
 msgstr "發行公告"
 
+#: src/components/NginxControl/NginxControl.vue:12
+#: src/components/NginxControl/NginxControl.vue:13
+#: src/components/NginxControl/NginxControl.vue:17
+msgid "Reload"
+msgstr "重新載入"
+
+#: src/components/NginxControl/NginxControl.vue:11
+msgid "Reloading"
+msgstr "换弹中"
+
 #: src/language/constants.ts:19
 msgid "Reloading nginx"
 msgstr "重载 Nginx"
@@ -771,11 +798,25 @@ msgstr "重载 Nginx"
 msgid "Reset"
 msgstr "重設"
 
+#: src/components/NginxControl/NginxControl.vue:11
+#: src/components/NginxControl/NginxControl.vue:12
+#: src/components/NginxControl/NginxControl.vue:16
+msgid "Restart"
+msgstr "重新啟動"
+
+#: src/components/NginxControl/NginxControl.vue:12
+msgid "Restarting"
+msgstr "重啟"
+
 #: src/views/preference/Preference.vue:8
 msgid "Run Mode"
 msgstr "高階模式"
 
-#: src/views/config/ConfigEdit.vue:78 src/views/domain/DomainEdit.vue:225
+#: src/components/NginxControl/NginxControl.vue:10
+msgid "Running"
+msgstr "運行中"
+
+#: src/views/config/ConfigEdit.vue:78 src/views/domain/DomainEdit.vue:228
 #: 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
@@ -806,7 +847,7 @@ msgid "Save Successfully"
 msgstr "保存成功"
 
 #: src/views/config/ConfigEdit.vue:44 src/views/domain/DomainAdd.vue:44
-#: src/views/domain/DomainEdit.vue:125
+#: src/views/domain/DomainEdit.vue:128
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:35
 msgid "Saved successfully"
 msgstr "儲存成功"
@@ -815,17 +856,19 @@ msgstr "儲存成功"
 msgid "Selector"
 msgstr "選擇器"
 
-#: src/views/dashboard/DashBoard.vue:21 src/views/dashboard/DashBoard.vue:85
+#: src/views/dashboard/DashBoard.vue:21 src/views/dashboard/DashBoard.vue:87
 msgid "Send"
 msgstr "上傳"
 
+#: src/components/NginxControl/NginxControl.vue:33
+#: src/components/NginxControl/NginxControl.vue:50
 #: src/components/StdDataDisplay/StdBatchEdit.vue:43
 #: 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: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
+#: 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"
 msgstr "伺服器錯誤"
 
@@ -874,7 +917,11 @@ msgstr "SSL 證書密鑰內容"
 msgid "Status"
 msgstr "狀態"
 
-#: src/views/dashboard/DashBoard.vue:41
+#: src/components/NginxControl/NginxControl.vue:13
+msgid "Stopped"
+msgstr "已停止"
+
+#: src/views/dashboard/DashBoard.vue:43
 msgid "Storage"
 msgstr "儲存"
 
@@ -882,7 +929,7 @@ msgstr "儲存"
 msgid "Subject Name: %{name}"
 msgstr "主體名稱: %{name}"
 
-#: src/views/dashboard/DashBoard.vue:36
+#: src/views/dashboard/DashBoard.vue:38
 msgid "Swap"
 msgstr "交換空間"
 
@@ -957,7 +1004,7 @@ msgstr "升級成功"
 msgid "Upgrading Nginx UI, please wait..."
 msgstr "正在升級 Nginx UI,請稍候..."
 
-#: src/views/dashboard/DashBoard.vue:140
+#: src/views/dashboard/DashBoard.vue:150
 msgid "Uptime:"
 msgstr "執行時間:"
 
@@ -984,7 +1031,7 @@ msgstr "查看"
 msgid "Warning"
 msgstr "警告"
 
-#: src/views/dashboard/DashBoard.vue:100 src/views/dashboard/DashBoard.vue:22
+#: src/views/dashboard/DashBoard.vue:102 src/views/dashboard/DashBoard.vue:22
 #: src/views/dashboard/DashBoard.vue:23
 msgid "Writes"
 msgstr "寫"
@@ -997,7 +1044,6 @@ msgstr "將證書私鑰寫入磁盤"
 msgid "Writing certificate to disk"
 msgstr "將證書寫入磁盤"
 
-#: src/layouts/HeaderLayout.vue:16
 #: src/views/domain/ngx_conf/directive/DirectiveEditorItem.vue:21
 #: src/views/domain/ngx_conf/LocationEditor.vue:25
 msgid "Yes"
@@ -1017,6 +1063,9 @@ msgctxt "Project"
 msgid "License"
 msgstr "開源軟體授權條款"
 
+#~ msgid "Do you want to reload Nginx?"
+#~ msgstr "你想重載 Nginx 嗎?"
+
 #, fuzzy
 #~ msgid "Are you sure you want to delete ?"
 #~ msgstr "您确定要删除?"
@@ -1045,9 +1094,6 @@ msgstr "開源軟體授權條款"
 #~ msgid "No, I'm rethink"
 #~ msgstr "再想想"
 
-#~ msgid "Restore"
-#~ msgstr "恢復"
-
 #~ msgid "Yes, I'm sure"
 #~ msgstr "是的"
 

+ 3 - 3
frontend/src/views/domain/DomainAdd.vue

@@ -40,7 +40,7 @@ function init() {
 
 function save() {
     ngx.build_config(ngx_config).then(r => {
-        domain.save(config.name, {name: config.name, content: r.content, enabled: true}).then(() => {
+        domain.save(config.name, {name: config.name, content: r.content}).then(() => {
             message.success($gettext('Saved successfully'))
 
             domain.enable(config.name).then(() => {
@@ -48,11 +48,11 @@ function save() {
                 current_step.value++
                 window.scroll({top: 0, left: 0, behavior: 'smooth'})
             }).catch(r => {
-                message.error(r.message ?? $gettext('Enable failed'), 10)
+                message.error(r.message ?? $gettext('Enable failed'), 5)
             })
 
         }).catch(r => {
-            message.error(interpolate($gettext('Save error %{msg}'), {msg: r.message ?? ''}), 10)
+            message.error(interpolate($gettext('Save error %{msg}'), {msg: $gettext(r.message) ?? ''}), 5)
         })
     })
 }

+ 5 - 2
frontend/src/views/domain/DomainEdit.vue

@@ -84,7 +84,7 @@ function handle_parse_error(r: any) {
             configText.value = r.config
         })
     } else {
-        message.error(r.message ?? $gettext('Server error'))
+        message.error($gettext(r?.message ?? 'Server error'))
     }
 
     throw r
@@ -119,7 +119,10 @@ const save = async () => {
         }
     }
 
-    domain.save(name.value, {name: filename.value || name.value, content: configText.value}).then(r => {
+    domain.save(name.value, {
+        name: filename.value || name.value,
+        content: configText.value, overwrite: true
+    }).then(r => {
         handle_response(r)
         router.push('/domain/' + filename.value)
         message.success($gettext('Saved successfully'))

+ 57 - 8
server/api/domain.go

@@ -4,6 +4,7 @@ import (
 	"github.com/0xJacky/Nginx-UI/server/model"
 	"github.com/0xJacky/Nginx-UI/server/pkg/cert"
 	"github.com/0xJacky/Nginx-UI/server/pkg/config_list"
+	"github.com/0xJacky/Nginx-UI/server/pkg/helper"
 	"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
 	"github.com/gin-gonic/gin"
 	"log"
@@ -148,7 +149,7 @@ func GetDomain(c *gin.Context) {
 
 }
 
-func EditDomain(c *gin.Context) {
+func SaveDomain(c *gin.Context) {
 	name := c.Param("name")
 
 	if name == "" {
@@ -159,8 +160,9 @@ func EditDomain(c *gin.Context) {
 	}
 
 	var json struct {
-		Name    string `json:"name" binding:"required"`
-		Content string `json:"content" binding:"required"`
+		Name      string `json:"name" binding:"required"`
+		Content   string `json:"content" binding:"required"`
+		Overwrite bool   `json:"overwrite"`
 	}
 
 	if !BindAndValid(c, &json) {
@@ -169,6 +171,13 @@ func EditDomain(c *gin.Context) {
 
 	path := nginx.GetConfPath("sites-available", name)
 
+	if !json.Overwrite && helper.FileExists(path) {
+		c.JSON(http.StatusNotAcceptable, gin.H{
+			"message": "File exists",
+		})
+		return
+	}
+
 	err := os.WriteFile(path, []byte(json.Content), 0644)
 	if err != nil {
 		ErrHandler(c, err)
@@ -178,10 +187,15 @@ func EditDomain(c *gin.Context) {
 	// rename the config file if needed
 	if name != json.Name {
 		newPath := nginx.GetConfPath("sites-available", json.Name)
+		// check if dst file exists, do not rename
+		if helper.FileExists(newPath) {
+			c.JSON(http.StatusNotAcceptable, gin.H{
+				"message": "File exists",
+			})
+			return
+		}
 		// recreate soft link
-		log.Println(enabledConfigFilePath)
-		if _, err = os.Stat(enabledConfigFilePath); err == nil {
-			log.Println(enabledConfigFilePath)
+		if helper.FileExists(enabledConfigFilePath) {
 			_ = os.Remove(enabledConfigFilePath)
 			enabledConfigFilePath = nginx.GetConfPath("sites-enabled", json.Name)
 			err = os.Symlink(newPath, enabledConfigFilePath)
@@ -191,17 +205,19 @@ func EditDomain(c *gin.Context) {
 				return
 			}
 		}
+
 		err = os.Rename(path, newPath)
 		if err != nil {
 			ErrHandler(c, err)
 			return
 		}
+
 		name = json.Name
 		c.Set("rewriteConfigFileName", name)
 	}
 
 	enabledConfigFilePath = nginx.GetConfPath("sites-enabled", name)
-	if _, err = os.Stat(enabledConfigFilePath); err == nil {
+	if helper.FileExists(enabledConfigFilePath) {
 		// Test nginx configuration
 		output := nginx.TestConf()
 		if nginx.GetLogLevel(output) >= nginx.Warn {
@@ -245,7 +261,7 @@ func EnableDomain(c *gin.Context) {
 		}
 	}
 
-	// Test nginx config, if not pass then rollback.
+	// Test nginx config, if not pass then disable the site.
 	output := nginx.TestConf()
 
 	if nginx.GetLogLevel(output) >= nginx.Warn {
@@ -384,3 +400,36 @@ func RemoveDomainFromAutoCert(c *gin.Context) {
 	}
 	c.JSON(http.StatusOK, nil)
 }
+
+func DuplicateSite(c *gin.Context) {
+	name := c.Param("name")
+
+	var json struct {
+		Name string `json:"name"`
+	}
+
+	if !BindAndValid(c, &json) {
+		return
+	}
+
+	src := nginx.GetConfPath("sites-available", name)
+	dst := nginx.GetConfPath("sites-available", json.Name)
+
+	if helper.FileExists(dst) {
+		c.JSON(http.StatusNotAcceptable, gin.H{
+			"message": "file exists",
+		})
+		return
+	}
+
+	_, err := helper.CopyFile(src, dst)
+
+	if err != nil {
+		ErrHandler(c, err)
+		return
+	}
+
+	c.JSON(http.StatusOK, gin.H{
+		"dst": dst,
+	})
+}

+ 31 - 0
server/pkg/helper/copy.go

@@ -0,0 +1,31 @@
+package helper
+
+import (
+    "io"
+    "os"
+)
+
+func CopyFile(src, dst string) (int64, error) {
+    sourceFileStat, err := os.Stat(src)
+    if err != nil {
+        return 0, err
+    }
+
+    if !sourceFileStat.Mode().IsRegular() {
+        return 0, nil
+    }
+
+    source, err := os.Open(src)
+    if err != nil {
+        return 0, err
+    }
+    defer source.Close()
+
+    destination, err := os.Create(dst)
+    if err != nil {
+        return 0, err
+    }
+    defer destination.Close()
+
+    return io.Copy(destination, source)
+}

+ 11 - 0
server/pkg/helper/file.go

@@ -0,0 +1,11 @@
+package helper
+
+import "os"
+
+func FileExists(filename string) bool {
+	_, err := os.Stat(filename)
+	if os.IsNotExist(err) {
+		return false
+	}
+	return true
+}

+ 3 - 1
server/router/routers.go

@@ -54,7 +54,7 @@ func InitRouter() *gin.Engine {
 			g.GET("domain/:name", api.GetDomain)
 
 			// Modify site configuration directly
-			g.POST("domain/:name", api.EditDomain)
+			g.POST("domain/:name", api.SaveDomain)
 
 			// Transform NgxConf to nginx configuration
 			g.POST("ngx/build_config", api.BuildNginxConfig)
@@ -74,6 +74,8 @@ func InitRouter() *gin.Engine {
 			g.POST("domain/:name/enable", api.EnableDomain)
 			g.POST("domain/:name/disable", api.DisableDomain)
 			g.DELETE("domain/:name", api.DeleteDomain)
+			// duplicate site
+			g.POST("domain/:name/duplicate", api.DuplicateSite)
 
 			g.GET("configs", api.GetConfigs)
 			g.GET("config/*name", api.GetConfig)

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini