github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/static_source/admin/src/views/Dashboard/editor/TabSettings.vue (about) 1 <script setup lang="ts"> 2 import {computed, nextTick, PropType, reactive, ref, unref, watch} from 'vue' 3 import {Form} from '@/components/Form' 4 import {ElButton, ElCol, ElDivider, ElMessage, ElPopconfirm, ElRow} from 'element-plus' 5 import {useI18n} from '@/hooks/web/useI18n' 6 import {useForm} from '@/hooks/web/useForm' 7 import {useValidator} from '@/hooks/web/useValidator' 8 import {FormSchema} from '@/types/form' 9 import {ApiArea, ApiDashboard} from "@/api/stub"; 10 import {copyToClipboard} from "@/utils/clipboard"; 11 import {JsonViewer} from "@/components/JsonViewer"; 12 import {Core, eventBus} from "@/views/Dashboard/core"; 13 import {useRouter} from "vue-router"; 14 import {Dialog} from '@/components/Dialog' 15 16 const {register, elFormRef, methods} = useForm() 17 const {required} = useValidator() 18 const {t} = useI18n() 19 const dialogSource = ref({}) 20 const dialogVisible = ref(false) 21 const {setValues, setSchema} = methods 22 const {currentRoute, addRoute, push} = useRouter() 23 24 interface DashboardForm { 25 name?: string; 26 description?: string; 27 enabled?: boolean; 28 area?: ApiArea; 29 areaId?: number; 30 } 31 32 const props = defineProps({ 33 core: { 34 type: Object as PropType<Nullable<Core>>, 35 default: () => null 36 }, 37 }) 38 39 const currentCore = computed(() => props.core as Core) 40 41 const rules = { 42 name: [required()], 43 } 44 45 const schema = reactive<FormSchema[]>([ 46 { 47 field: 'name', 48 label: t('dashboard.name'), 49 component: 'Input', 50 colProps: { 51 span: 24 52 }, 53 componentProps: { 54 placeholder: t('dashboard.name') 55 } 56 }, 57 { 58 field: 'description', 59 label: t('dashboard.description'), 60 component: 'Input', 61 colProps: { 62 span: 24 63 }, 64 componentProps: { 65 placeholder: t('dashboard.description') 66 } 67 }, 68 // { 69 // field: 'enabled', 70 // label: t('dashboard.enabled'), 71 // component: 'Switch', 72 // value: false, 73 // colProps: { 74 // span: 24 75 // }, 76 // }, 77 { 78 field: 'area', 79 label: t('dashboard.area'), 80 value: null, 81 component: 'Area', 82 colProps: { 83 span: 24 84 }, 85 componentProps: { 86 placeholder: t('dashboard.area'), 87 } 88 }, 89 ]) 90 91 watch( 92 () => props.core?.current, 93 (val?: ApiDashboard) => { 94 if (!val) return 95 setValues({ 96 name: val.name, 97 description: val.description, 98 enabled: val.enabled, 99 area: val.area, 100 areaId: val.areaId, 101 }) 102 }, 103 { 104 deep: false, 105 immediate: true 106 } 107 ) 108 109 const prepareForExport = async () => { 110 return "" 111 } 112 113 const copy = async () => { 114 const body = await prepareForExport() 115 copyToClipboard(JSON.stringify(body, null, 2)) 116 } 117 118 119 const exportDashbord = () => { 120 dialogSource.value = currentCore.value.serialize() 121 dialogVisible.value = true 122 } 123 124 const updateBoard = async () => { 125 const formRef = unref(elFormRef) 126 await formRef?.validate(async (isValid) => { 127 if (isValid) { 128 const {getFormData} = methods 129 const formData = await getFormData<DashboardForm>() 130 const board = currentCore.value.current; 131 board.areaId = formData.area?.id 132 board.area = formData.area 133 board.name = formData.name 134 board.description = formData.description 135 board.enabled = formData.enabled 136 nextTick() 137 const res = await currentCore.value?.update() 138 .catch(() => { 139 }) 140 .finally(() => { 141 // fetchDashboard() 142 }) 143 ElMessage({ 144 title: t('Success'), 145 message: t('message.updatedSuccessfully'), 146 type: 'success', 147 duration: 2000 148 }); 149 } 150 }) 151 152 } 153 154 const fetchDashboard = () => { 155 eventBus.emit('fetchDashboard') 156 } 157 158 const cancel = () => { 159 push(`/dashboards`) 160 } 161 162 const removeBoard = async () => { 163 if (!currentCore.value) return; 164 await currentCore.value.removeBoard() 165 .catch(() => { 166 }) 167 .finally(() => { 168 }) 169 cancel() 170 } 171 172 </script> 173 174 <template> 175 176 <ElRow class="mb-10px"> 177 <ElCol> 178 <ElDivider content-position="left">{{ $t('dashboard.mainTab') }}</ElDivider> 179 </ElCol> 180 </ElRow> 181 182 <Form 183 :schema="schema" 184 :rules="rules" 185 label-position="top" 186 @register="register" 187 class="mb-10px" 188 /> 189 190 191 <ElRow class="mb-10px"> 192 <ElCol> 193 <ElDivider class="mb-10px" content-position="left">{{ $t('main.actions') }}</ElDivider> 194 </ElCol> 195 </ElRow> 196 197 198 <div class="text-right"> 199 200 <ElButton type="primary" @click.prevent.stop='exportDashbord' plain> 201 <Icon icon="uil:file-export" class="mr-5px"/> 202 {{ $t('main.export') }} 203 </ElButton> 204 205 206 <ElButton type="primary" @click.prevent.stop="updateBoard" plain> 207 {{ $t('main.update') }} 208 </ElButton> 209 210 211 <ElButton @click.prevent.stop="fetchDashboard" plain>{{ 212 $t('main.loadFromServer') 213 }} 214 </ElButton> 215 216 <ElPopconfirm 217 :confirm-button-text="$t('main.ok')" 218 :cancel-button-text="$t('main.no')" 219 width="250" 220 style="margin-left: 10px;" 221 :title="$t('main.are_you_sure_to_do_want_this?')" 222 @confirm="removeBoard" 223 > 224 <template #reference> 225 <ElButton type="danger" plain> 226 <Icon icon="ep:delete" class="mr-5px"/> 227 {{ t('main.remove') }} 228 </ElButton> 229 </template> 230 </ElPopconfirm> 231 232 </div> 233 234 <!-- export dialog --> 235 <Dialog v-model="dialogVisible" :title="t('main.dialogExportTitle')" :maxHeight="400" width="80%"> 236 <JsonViewer v-model="dialogSource"/> 237 <template #footer> 238 <ElButton @click="copy()">{{ t('setting.copy') }}</ElButton> 239 <ElButton @click="dialogVisible = false">{{ t('main.closeDialog') }}</ElButton> 240 </template> 241 </Dialog> 242 <!-- /export dialog --> 243 244 </template>