Browse Source

add modal and button for import/export db

Hamidreza Ghavami 1 year ago
parent
commit
c8baf5ceee
2 changed files with 95 additions and 12 deletions
  1. 2 1
      web/html/common/text_modal.html
  2. 93 11
      web/html/xui/index.html

+ 2 - 1
web/html/common/text_modal.html

@@ -4,7 +4,8 @@
          :class="siderDrawer.isDarkTheme ? darkClass : ''"
          :ok-button-props="{attrs:{id:'txt-modal-ok-btn'}}">
     <a-button v-if="!ObjectUtil.isEmpty(txtModal.fileName)" type="primary" style="margin-bottom: 10px;"
-              :href="'data:application/text;charset=utf-8,' + encodeURIComponent(txtModal.content)" :download="txtModal.fileName">
+              :href="'data:application/text;charset=utf-8,' + encodeURIComponent(txtModal.content)"
+              :download="txtModal.fileName">
         {{ i18n "download" }} [[ txtModal.fileName ]]
     </a-button>
     <a-input type="textarea" v-model="txtModal.content"

+ 93 - 11
web/html/xui/index.html

@@ -111,9 +111,9 @@
                     <a-col :sm="24" :md="12">
                         <a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
                             {{ i18n "menu.link" }}:
-                            <a-tag color="blue" style="cursor: pointer;" @click="openLogs(20)">Log Reports</a-tag>
-                            <a-tag color="blue" style="cursor: pointer;" @click="openConfig">Config</a-tag>
-                            <a-tag color="blue" style="cursor: pointer;" @click="getBackup">Backup</a-tag>
+                            <a-tag color="blue" style="cursor: pointer;" @click="openLogs(20)">{{ i18n "pages.index.logs" }}</a-tag>
+                            <a-tag color="blue" style="cursor: pointer;" @click="openConfig">{{ i18n "pages.index.config" }}</a-tag>
+                            <a-tag color="blue" style="cursor: pointer;" @click="openBackup">{{ i18n "pages.index.backup" }}</a-tag>
                         </a-card>
                     </a-col>
                     <a-col :sm="24" :md="12">
@@ -188,6 +188,7 @@
             </transition>
         </a-layout-content>
     </a-layout>
+
     <a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}'
              :closable="true" @ok="() => versionModal.visible = false"
              :class="siderDrawer.isDarkTheme ? darkClass : ''"
@@ -201,6 +202,7 @@
             </a-tag>
         </template>
     </a-modal>
+
     <a-modal id="log-modal" v-model="logModal.visible" title="X-UI logs"
              :closable="true" @ok="() => logModal.visible = false" @cancel="() => logModal.visible = false"
              :class="siderDrawer.isDarkTheme ? darkClass : ''"
@@ -227,10 +229,28 @@
                     {{ i18n "download" }} x-ui.log
                 </a-button>
             </a-form-item>
-       </a-form>
+        </a-form>
         <a-input type="textarea" v-model="logModal.logs" disabled="true"
                 :autosize="{ minRows: 10, maxRows: 22}"></a-input>
     </a-modal>
+
+    <a-modal id="backup-modal" v-model="backupModal.visible" :title="backupModal.title"
+            :closable="true" :class="siderDrawer.isDarkTheme ? darkClass : ''"
+            @ok="() => backupModal.hide()" @cancel="() => backupModal.hide()">
+        <p style="color: inherit; font-size: 16px; padding: 4px 2px;">
+            <a-icon type="warning" style="color: inherit; font-size: 20px;"></a-icon>
+            [[ backupModal.description ]]
+        </p>
+        <a-space direction="horizontal" align="center" style="margin-bottom: 10px;">
+            <a-button type="primary" @click="exportDatabase()">
+                [[ backupModal.exportText ]]
+            </a-button>
+            <a-button type="primary" @click="importDatabase()">
+                [[ backupModal.importText ]]
+            </a-button>
+        </a-space>
+    </a-modal>
+
 </a-layout>
 {{template "js" .}}
 {{template "textModal"}}
@@ -339,6 +359,29 @@
         },
     };
 
+    const backupModal = {
+        visible: false,
+        title: '',
+        description: '',
+        exportText: '',
+        importText: '',
+        show({
+            title = '{{ i18n "pages.index.backupTitle" }}',
+            description = '{{ i18n "pages.index.backupDescription" }}',
+            exportText = '{{ i18n "pages.index.exportDatabase" }}',
+            importText = '{{ i18n "pages.index.importDatabase" }}',
+        }) {
+            this.title = title;
+            this.description = description;
+            this.exportText = exportText;
+            this.importText = importText;
+            this.visible = true;
+        },
+        hide() {
+            this.visible = false;
+        },
+    };
+
     const app = new Vue({
         delimiters: ['[[', ']]'],
         el: '#app',
@@ -347,6 +390,7 @@
             status: new Status(),
             versionModal,
             logModal,
+            backupModal,
             spinning: false,
             loadingTip: '{{ i18n "loading"}}',
         },
@@ -388,7 +432,6 @@
                     },
                 });
             },
-	        //here add stop xray function
             async stopXrayService() {
                 this.loading(true);
                 const msg = await HttpUtil.post('server/stopXrayService');
@@ -397,7 +440,6 @@
                     return;
                 }
             },
-            //here add restart xray function
             async restartXrayService() {
                 this.loading(true);
                 const msg = await HttpUtil.post('server/restartXrayService');
@@ -413,20 +455,60 @@
                 if (!msg.success) {
                     return;
                 }
-                logModal.show(msg.obj,rows);
+                logModal.show(msg.obj, rows);
             },
-            async openConfig(){
+            async openConfig() {
                 this.loading(true);
                 const msg = await HttpUtil.post('server/getConfigJson');
                 this.loading(false);
                 if (!msg.success) {
                     return;
                 }
-                txtModal.show('config.json',JSON.stringify(msg.obj, null, 2),'config.json');
+                txtModal.show('config.json', JSON.stringify(msg.obj, null, 2), 'config.json');
             },
-            getBackup(){
+            openBackup() {
+                backupModal.show({
+                    title: '{{ i18n "pages.index.backupTitle" }}',
+                    description: '{{ i18n "pages.index.backupDescription" }}',
+                    exportText: '{{ i18n "pages.index.exportDatabase" }}',
+                    importText: '{{ i18n "pages.index.importDatabase" }}',
+                });
+            },
+            exportDatabase() {
                 window.location = basePath + 'server/getDb';
-            }
+            },
+            importDatabase() {
+                const fileInput = document.createElement('input');
+                fileInput.type = 'file';
+                fileInput.accept = '.db';
+                fileInput.addEventListener('change', async (event) => {
+                    const dbFile = event.target.files[0];
+                    if (dbFile) {
+                        const formData = new FormData();
+                        formData.append('db', dbFile);
+                        backupModal.hide();
+                        this.loading(true);
+                        const uploadMsg = await HttpUtil.post('server/importDB', formData, {
+                            headers: {
+                                'Content-Type': 'multipart/form-data',
+                            }
+                        });
+                        this.loading(false);
+                        if (!uploadMsg.success) {
+                            return;
+                        }
+                        this.loading(true);
+                        const restartMsg = await HttpUtil.post("/xui/setting/restartPanel");
+                        this.loading(false);
+                        if (restartMsg.success) {
+                            this.loading(true);
+                            await PromiseUtil.sleep(5000);
+                            location.reload();
+                        }
+                    }
+                });
+                fileInput.click();
+            },
         },
         async mounted() {
             while (true) {