feat: duplicate site #80

This commit is contained in:
0xJacky 2023-02-13 19:36:40 +08:00
parent 566a5c725e
commit a3dfc7af4a
No known key found for this signature in database
GPG key ID: B6E4A6E4A561BAF0
3 changed files with 432 additions and 338 deletions

View file

@ -10,6 +10,7 @@ import domain from '@/api/domain'
import {Badge, message} from 'ant-design-vue' import {Badge, message} from 'ant-design-vue'
import {h, ref} from 'vue' import {h, ref} from 'vue'
import {input} from '@/components/StdDataEntry' import {input} from '@/components/StdDataEntry'
import SiteDuplicate from '@/views/domain/SiteDuplicate.vue'
const columns = [{ const columns = [{
title: () => $gettext('Name'), title: () => $gettext('Name'),
@ -25,7 +26,7 @@ const columns = [{
dataIndex: 'enabled', dataIndex: 'enabled',
customRender: (args: customRender) => { customRender: (args: customRender) => {
const template: any = [] const template: any = []
const {text, column} = args const {text} = args
if (text === true || text > 0) { if (text === true || text > 0) {
template.push(<Badge status="success"/>) template.push(<Badge status="success"/>)
template.push($gettext('Enabled')) template.push($gettext('Enabled'))
@ -83,6 +84,15 @@ function destroy(site_name: any) {
message.error(e?.message ?? $gettext('Server error')) message.error(e?.message ?? $gettext('Server error'))
}) })
} }
const show_duplicator = ref(false)
const target = ref('')
function handle_click_duplicate(name: string) {
show_duplicator.value = true
target.value = name
}
</script> </script>
<template> <template>
@ -99,25 +109,30 @@ function destroy(site_name: any) {
> >
<template #actions="{record}"> <template #actions="{record}">
<a-divider type="vertical"/> <a-divider type="vertical"/>
<a v-if="record.enabled" @click="disable(record.name)"> <a-button type="link" size="small" v-if="record.enabled" @click="disable(record.name)">
{{ $gettext('Disabled') }} {{ $gettext('Disabled') }}
</a> </a-button>
<a v-else @click="enable(record.name)"> <a-button type="link" size="small" v-else @click="enable(record.name)">
{{ $gettext('Enabled') }} {{ $gettext('Enabled') }}
</a> </a-button>
<template v-if="!record.enabled"> <a-divider type="vertical"/>
<a-button type="link" size="small" @click="handle_click_duplicate(record.name)">
{{ $gettext('Duplicate') }}
</a-button>
<a-divider type="vertical"/> <a-divider type="vertical"/>
<a-popconfirm <a-popconfirm
:cancelText="$gettext('No')" :cancelText="$gettext('No')"
:okText="$gettext('OK')" :okText="$gettext('OK')"
:title="$gettext('Are you sure you want to delete?')" :title="$gettext('Are you sure you want to delete?')"
@confirm="destroy(record['name'])"> @confirm="destroy(record['name'])">
<a v-translate>Delete</a> <a-button type="link" size="small" :disabled="record.enabled">
{{ $gettext('Delete') }}
</a-button>
</a-popconfirm> </a-popconfirm>
</template> </template>
</template>
</std-table> </std-table>
</a-card> </a-card>
<site-duplicate v-model:visible="show_duplicator" :name="target" @duplicated="table.get_list()"/>
</template> </template>
<style scoped> <style scoped>

View file

@ -0,0 +1,79 @@
<script setup lang="ts">
import {computed, nextTick, reactive, ref, watch} from 'vue'
import {useGettext} from 'vue3-gettext'
import {Form, message} from 'ant-design-vue'
import gettext from '@/gettext'
import domain from '@/api/domain'
const {$gettext} = useGettext()
const props = defineProps(['visible', 'name'])
const emit = defineEmits(['update:visible', 'duplicated'])
const show = computed({
get() {
return props.visible
},
set(v) {
emit('update:visible', v)
}
})
const modelRef = reactive({name: ''})
const rulesRef = reactive({
name: [
{
required: true,
message: () => $gettext('Please input name, ' +
'this will be used as the filename of the new configuration!')
}
]
})
const {validate, validateInfos, clearValidate} = Form.useForm(modelRef, rulesRef)
const loading = ref(false)
function onSubmit() {
validate().then(async () => {
loading.value = true
domain.duplicate(props.name, {name: modelRef.name}).then(() => {
message.success($gettext('Duplicated successfully'))
show.value = false
emit('duplicated')
}).catch((e: any) => {
message.error($gettext(e?.message ?? 'Server error'))
})
loading.value = false
})
}
watch(() => props.visible, (v) => {
if (v) {
modelRef.name = ''
nextTick(() => clearValidate())
}
})
watch(() => gettext.current, () => {
clearValidate()
})
</script>
<template>
<a-modal :title="$gettext('Duplicate')" v-model:visible="show" @ok="onSubmit"
:confirm-loading="loading">
<a-form layout="vertical">
<a-form-item :label="$gettext('Name')" v-bind="validateInfos.name">
<a-input v-model:value="modelRef.name"/>
</a-form-item>
</a-form>
</a-modal>
</template>
<style lang="less" scoped>
</style>

View file

@ -405,7 +405,7 @@ func DuplicateSite(c *gin.Context) {
name := c.Param("name") name := c.Param("name")
var json struct { var json struct {
Name string `json:"name"` Name string `json:"name" binding:"required"`
} }
if !BindAndValid(c, &json) { if !BindAndValid(c, &json) {
@ -417,7 +417,7 @@ func DuplicateSite(c *gin.Context) {
if helper.FileExists(dst) { if helper.FileExists(dst) {
c.JSON(http.StatusNotAcceptable, gin.H{ c.JSON(http.StatusNotAcceptable, gin.H{
"message": "file exists", "message": "File exists",
}) })
return return
} }