Explorar o código

[frontend-next] Refactored manage sites

0xJacky %!s(int64=2) %!d(string=hai) anos
pai
achega
2f91918f54

+ 4 - 0
frontend-next/components.d.ts

@@ -7,6 +7,7 @@ export {}
 
 declare module '@vue/runtime-core' {
   export interface GlobalComponents {
+    AAlert: typeof import('ant-design-vue/es')['Alert']
     ABreadcrumb: typeof import('ant-design-vue/es')['Breadcrumb']
     ABreadcrumbItem: typeof import('ant-design-vue/es')['BreadcrumbItem']
     AButton: typeof import('ant-design-vue/es')['Button']
@@ -32,11 +33,14 @@ declare module '@vue/runtime-core' {
     APagination: typeof import('ant-design-vue/es')['Pagination']
     APopconfirm: typeof import('ant-design-vue/es')['Popconfirm']
     AreaChart: typeof import('./src/components/Chart/AreaChart.vue')['default']
+    AResult: typeof import('ant-design-vue/es')['Result']
     ARow: typeof import('ant-design-vue/es')['Row']
     ASelect: typeof import('ant-design-vue/es')['Select']
     ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
     ASpace: typeof import('ant-design-vue/es')['Space']
     AStatistic: typeof import('ant-design-vue/es')['Statistic']
+    AStep: typeof import('ant-design-vue/es')['Step']
+    ASteps: typeof import('ant-design-vue/es')['Steps']
     ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
     ASwitch: typeof import('ant-design-vue/es')['Switch']
     ATable: typeof import('ant-design-vue/es')['Table']

+ 1 - 1
frontend-next/src/routes/index.ts

@@ -52,7 +52,7 @@ export const routes = [
                 }, {
                     path: 'add',
                     name: () => $gettext('Add Site'),
-                    // component: () => import('@/views/domain/DomainAdd.vue'),
+                    component: () => import('@/views/domain/DomainAdd.vue'),
                 }, {
                     path: ':name',
                     name: () => $gettext('Edit Site'),

+ 97 - 88
frontend-next/src/views/domain/DomainAdd.vue

@@ -1,3 +1,86 @@
+<script setup lang="ts">
+import DirectiveEditor from '@/views/domain/ngx_conf/directive/DirectiveEditor.vue'
+import LocationEditor from '@/views/domain/ngx_conf/LocationEditor.vue'
+import NgxConfigEditor from '@/views/domain/ngx_conf/NgxConfigEditor.vue'
+import {useGettext} from 'vue3-gettext'
+import domain from '@/api/domain'
+import ngx from '@/api/ngx'
+import {computed, reactive, ref} from 'vue'
+import {message} from 'ant-design-vue'
+import {useRouter} from 'vue-router'
+
+const {$gettext, interpolate} = useGettext()
+
+const config = reactive({name: ''})
+let ngx_config = reactive({
+    servers: [{
+        directives: [],
+        locations: []
+    }]
+})
+
+const error = reactive({})
+
+const current_step = ref(0)
+
+const enabled = ref(true)
+
+const auto_cert = ref(false)
+
+const update = ref(0)
+
+init()
+
+function init() {
+    domain.get_template().then(r => {
+        Object.assign(ngx_config, r.tokenized)
+    })
+}
+
+function save() {
+    ngx.build_config(ngx_config).then(r => {
+        domain.save(config.name, {content: r.content, enabled: true}).then(() => {
+            message.success($gettext('Saved successfully'))
+
+            domain.enable(config.name).then(() => {
+                message.success($gettext('Enabled successfully'))
+                current_step.value++
+                window.scroll({top: 0, left: 0, behavior: 'smooth'})
+            }).catch(r => {
+                message.error(r.message ?? $gettext('Enable failed'), 10)
+            })
+
+        }).catch(r => {
+            message.error(interpolate($gettext('Save error %{msg}'), {msg: r.message ?? ''}), 10)
+        })
+    })
+}
+
+const router = useRouter()
+
+function goto_modify() {
+    router.push('/domain/' + config.name)
+}
+
+function create_another() {
+    router.go(0)
+}
+
+const has_server_name = computed(() => {
+    const servers = ngx_config.servers
+    for (const server_key in servers) {
+        for (const k in servers[server_key].directives) {
+            const v = servers[server_key].directives[k]
+            if (v.directive === 'server_name' && v.params.trim() !== '') {
+                return true
+            }
+        }
+    }
+
+    return false
+})
+</script>
+
 <template>
     <a-card :title="$gettext('Add Site')">
         <div class="domain-add-container">
@@ -8,24 +91,25 @@
             </a-steps>
 
             <template v-if="current_step===0">
-                <a-form-item :label="$gettext('Configuration Name')">
-                    <a-input v-model="config.name"/>
-                </a-form-item>
+                <a-form layout="vertical">
+                    <a-form-item :label="$gettext('Configuration Name')">
+                        <a-input v-model:value="config.name"/>
+                    </a-form-item>
+                </a-form>
 
-                <directive-editor :ngx_directives="ngx_config.servers[0].directives"/>
 
+                <directive-editor :ngx_directives="ngx_config.servers[0].directives"/>
+                <br/>
                 <location-editor :locations="ngx_config.servers[0].locations"/>
-
+                <br/>
                 <a-alert
                     v-if="!has_server_name"
                     :message="$gettext('Warning')"
                     type="warning"
                     show-icon
                 >
-                    <template slot="description">
-                    <span v-translate>
-                        server_name parameter is required
-                    </span>
+                    <template #description>
+                        <span v-translate>server_name parameter is required</span>
                     </template>
                 </a-alert>
                 <br/>
@@ -34,12 +118,14 @@
             <template v-else-if="current_step===1">
 
                 <ngx-config-editor
-                    ref="ngx_config"
+                    ref="ngx-config-editor"
                     :ngx_config="ngx_config"
-                    v-model="auto_cert"
+                    v-model:auto_cert="auto_cert"
                     :enabled="enabled"
                 />
 
+                <br/>
+
             </template>
 
             <a-space v-if="current_step<2">
@@ -51,7 +137,6 @@
                     <translate>Next</translate>
                 </a-button>
             </a-space>
-
             <a-result
                 v-else-if="current_step===2"
                 status="success"
@@ -71,82 +156,6 @@
     </a-card>
 </template>
 
-<script>
-import DirectiveEditor from '@/views/domain/ngx_conf/directive/DirectiveEditor'
-import LocationEditor from '@/views/domain/ngx_conf/LocationEditor'
-import $gettext, {$interpolate} from '@/lib/translate/gettext'
-import NgxConfigEditor from '@/views/domain/ngx_conf/NgxConfigEditor'
-
-export default {
-    name: 'DomainAdd',
-    components: {NgxConfigEditor, LocationEditor, DirectiveEditor},
-    data() {
-        return {
-            config: {},
-            ngx_config: {
-                servers: [{}]
-            },
-            error: {},
-            current_step: 0,
-            enabled: true,
-            auto_cert: false
-        }
-    },
-    created() {
-        this.init()
-    },
-    methods: {
-        init() {
-            this.$api.domain.get_template().then(r => {
-                this.ngx_config = r.tokenized
-            })
-        },
-        save() {
-            this.$api.ngx.build_config(this.ngx_config).then(r => {
-                this.$api.domain.save(this.config.name, {content: r.content, enabled: true}).then(() => {
-                    this.$message.success($gettext('Saved successfully'))
-
-                    this.$api.domain.enable(this.config.name).then(() => {
-                        this.$message.success($gettext('Enabled successfully'))
-                        this.current_step++
-                    }).catch(r => {
-                        this.$message.error(r.message ?? $gettext('Enable failed'), 10)
-                    })
-
-                }).catch(r => {
-                    this.$message.error($interpolate($gettext('Save error %{msg}'), {msg: r.message ?? ''}), 10)
-                })
-            })
-        },
-        goto_modify() {
-            this.$router.push('/domain/' + this.config.name)
-        },
-        create_another() {
-            this.current_step = 0
-            this.config = {}
-            this.ngx_config = {
-                servers: [{}]
-            }
-        },
-    },
-    computed: {
-        has_server_name() {
-            const servers = this.ngx_config.servers
-            for (const server_key in servers) {
-                for (const k in servers[server_key].directives) {
-                    const v = servers[server_key].directives[k]
-                    if (v.directive === 'server_name' && v.params.trim() !== '') {
-                        return true
-                    }
-                }
-            }
-
-            return false
-        }
-    }
-}
-</script>
-
 <style lang="less" scoped>
 .ant-steps {
     padding: 10px 0 20px 0;

+ 1 - 1
frontend-next/src/views/domain/DomainEdit.vue

@@ -140,7 +140,7 @@ function disable() {
 
                 <div class="domain-edit-container" key="basic" v-else>
                     <a-form-item :label="$gettext('Enabled')">
-                        <a-switch v-model="enabled" @change="checked=>{checked?enable():disable()}"/>
+                        <a-switch v-model:checked="enabled" @change="checked=>{checked?enable():disable()}"/>
                     </a-form-item>
                     <ngx-config-editor
                         ref="ngx_config_editor"

+ 21 - 0
frontend-next/src/views/domain/DomainList.vue

@@ -68,6 +68,16 @@ function disable(name: any) {
         message.error(interpolate($gettext('Failed to disable %{msg}'), {msg: r.message ?? ''}))
     })
 }
+
+function destroy(site_name: any) {
+    domain.destroy(site_name).then(() => {
+        const t: Table | null = table.value
+        t!.get_list()
+        message.success(interpolate($gettext('Delete site: %{site_name}'), {site_name: site_name}))
+    }).catch((e: any) => {
+        message.error(e?.message ?? $gettext('Server error'))
+    })
+}
 </script>
 
 <template>
@@ -81,8 +91,19 @@ function disable(name: any) {
             @clickEdit="r => this.$router.push({
                 path: '/domain/' + r
             })"
+            :deletable="false"
         >
             <template #actions="{record}">
+                <template v-if="!record.enabled">
+                    <a-divider type="vertical"/>
+                    <a-popconfirm
+                        :cancelText="$gettext('No')"
+                        :okText="$gettext('OK')"
+                        :title="$gettext('Are you sure you want to delete ?')"
+                        @confirm="destroy(record['name'])">
+                        <a v-translate>Delete</a>
+                    </a-popconfirm>
+                </template>
                 <a-divider type="vertical"/>
                 <a v-if="record.enabled" @click="disable(record.name)">
                     {{ $gettext('Disabled') }}

+ 37 - 28
frontend-next/src/views/domain/ngx_conf/LocationEditor.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import CodeEditor from '@/components/CodeEditor'
 import {useGettext} from 'vue3-gettext'
-import {reactive} from 'vue'
+import {reactive, ref} from 'vue'
 
 const {$gettext} = useGettext()
 
@@ -9,25 +9,30 @@ const {locations} = defineProps<{
     locations?: any[]
 }>()
 
-let location = reactive({})
+let location = reactive({
+    comments: '',
+    path: '',
+    content: '',
+})
 
+const adding = ref(false)
 
 function add() {
     adding.value = true
-    location = reactive({})
+    location = reactive({
+        comments: '',
+        path: '',
+        content: '',
+    })
 }
 
 function save() {
-    this.adding = false
-    if (this.locations) {
-        this.locations.push(this.location)
-    } else {
-        this.locations = [this.location]
-    }
+    adding.value = false
+    locations.push(this.location)
 }
 
 function remove(index) {
-    this.locations.splice(index, 1)
+    locations.splice(index, 1)
 }
 </script>
 
@@ -36,27 +41,31 @@ function remove(index) {
     <a-empty v-if="!locations"/>
     <a-card v-for="(v,k) in locations" :key="k"
             :title="$gettext('Location')" size="small">
-        <a-form-item :label="$gettext('Comments')" v-if="v.comments">
-            <p style="white-space: pre-wrap;">{{ v.comments }}</p>
-        </a-form-item>
-        <a-form-item :label="$gettext('Path')">
-            <a-input addon-before="location" v-model="v.path"/>
-        </a-form-item>
-        <a-form-item :label="$gettext('Content')">
-            <code-editor v-model:content="v.content" default-height="200px"/>
-        </a-form-item>
+        <a-form layout="vertical">
+            <a-form-item :label="$gettext('Comments')">
+                <a-textarea v-model:value="v.comments"/>
+            </a-form-item>
+            <a-form-item :label="$gettext('Path')">
+                <a-input addon-before="location" v-model:value="v.path"/>
+            </a-form-item>
+            <a-form-item :label="$gettext('Content')">
+                <code-editor v-model:content="v.content" default-height="200px"/>
+            </a-form-item>
+        </a-form>
     </a-card>
 
     <a-modal :title="$gettext('Add Location')" v-model:visible="adding" @ok="save">
-        <a-form-item :label="$gettext('Comments')">
-            <a-textarea v-model="location.comments"></a-textarea>
-        </a-form-item>
-        <a-form-item :label="$gettext('Path')">
-            <a-input addon-before="location" v-model="location.path"/>
-        </a-form-item>
-        <a-form-item :label="$gettext('Content')">
-            <vue-itextarea v-model:content="location.content" default-height="200px"/>
-        </a-form-item>
+        <a-form layout="vertical">
+            <a-form-item :label="$gettext('Comments')">
+                <a-textarea v-model:value="location.comments"/>
+            </a-form-item>
+            <a-form-item :label="$gettext('Path')">
+                <a-input addon-before="location" v-model:value="location.path"/>
+            </a-form-item>
+            <a-form-item :label="$gettext('Content')">
+                <code-editor v-model:content="location.content" default-height="200px"/>
+            </a-form-item>
+        </a-form>
     </a-modal>
 
     <div>

+ 2 - 1
frontend-next/src/views/domain/ngx_conf/NgxConfigEditor.vue

@@ -19,6 +19,7 @@ const name = ref(route.params.name)
 const init_ssl_status = ref(false)
 
 function update_cert_info() {
+    // TODO
     // if (name.value && this.$refs['cert-info' + this.current_server_index]) {
     //     this.$refs['cert-info' + this.current_server_index].get()
     // }
@@ -153,7 +154,7 @@ const current_support_ssl = computed(() => {
                     </template>
 
                     <directive-editor :ngx_directives="v.directives"/>
-
+                    <br/>
                     <location-editor :locations="v.locations"/>
                 </div>
 

+ 1 - 1
frontend-next/src/views/domain/ngx_conf/directive/DirectiveEditor.vue

@@ -61,7 +61,7 @@ function onSave(idx: number) {
                 <div class="extra-content">
                     <a-form layout="vertical">
                         <a-form-item :label="$gettext('Comments')">
-                            <a-textarea v-model="directive.comments"/>
+                            <a-textarea v-model:value="directive.comments"/>
                         </a-form-item>
                     </a-form>
                     <directive-add :ngx_directives="ngx_directives" :idx="index" @save="onSave(index)"/>

+ 1 - 1
frontend-next/version.json

@@ -1 +1 @@
-{"version":"1.5.0","build_id":8,"total_build":78}
+{"version":"1.5.0","build_id":9,"total_build":79}