Added post addBackend options to force export, or import data directly after.
This commit is contained in:
@@ -237,11 +237,42 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field" v-if="backends.length > 0">
|
||||
<hr>
|
||||
<label class="label has-text-danger" for="force_export">
|
||||
Export current local database state to this backend?
|
||||
</label>
|
||||
<div class="control">
|
||||
<input id="force_export" type="checkbox" class="switch is-success"
|
||||
v-model="forceExport">
|
||||
<label for="force_export">Yes</label>
|
||||
<p class="help">
|
||||
<span class="icon has-text-danger"><i class="fas fa-exclamation-triangle"></i></span>
|
||||
If this is a new backend, you need to get it in sync with your current database,
|
||||
enabling this option will initiate a one time force export the current local database state to the
|
||||
backend. This will override the backend state to be inline with the local database state.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field" v-else>
|
||||
<hr>
|
||||
<label class="label has-text-danger" for="run_import">
|
||||
Export current local database state to this backend?
|
||||
</label>
|
||||
<div class="control">
|
||||
<input id="run_import" type="checkbox" class="switch is-success" v-model="runImport">
|
||||
<label for="run_import">Yes</label>
|
||||
<p class="help">
|
||||
<span class="icon has-text-danger"><i class="fas fa-info-circle"></i></span>
|
||||
Do you want to run a one time import for this backend after adding this backend?
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<div class="card-footer-item" v-if="stage < 5">
|
||||
<div class="card-footer-item" v-if="stage < maxStages">
|
||||
<button class="button is-fullwidth is-primary" type="submit" @click="changeStep()">
|
||||
<span class="icon">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
@@ -265,7 +296,7 @@ import 'assets/css/bulma-switch.css'
|
||||
import request from '~/utils/request'
|
||||
import {awaitElement, explode, notification} from '~/utils/index'
|
||||
|
||||
const emit = defineEmits(['addBackend'])
|
||||
const emit = defineEmits(['addBackend', 'forceExport', 'runImport'])
|
||||
|
||||
const props = defineProps({
|
||||
backends: {
|
||||
@@ -299,12 +330,15 @@ const users = ref([])
|
||||
const supported = ref([])
|
||||
const servers = ref([])
|
||||
|
||||
const maxStages = 5
|
||||
const stage = ref(0)
|
||||
const usersLoading = ref(false)
|
||||
const uuidLoading = ref(false)
|
||||
const serversLoading = ref(false)
|
||||
const exposeToken = ref(false)
|
||||
const error = ref()
|
||||
const forceExport = ref(false)
|
||||
const runImport = ref(false)
|
||||
|
||||
const isLimited = ref(false)
|
||||
const accessTokenResponse = ref({})
|
||||
@@ -593,7 +627,18 @@ const addBackend = async () => {
|
||||
}
|
||||
|
||||
notification('success', 'Information', `Backend ${backend.value.name} added successfully.`)
|
||||
emit('addBackend', backend)
|
||||
|
||||
let event
|
||||
if (true === Boolean(forceExport?.value ?? false)) {
|
||||
event = 'forceExport'
|
||||
} else if (true === Boolean(runImport?.value ?? false)) {
|
||||
event = 'runImport'
|
||||
} else {
|
||||
event = 'addBackend'
|
||||
}
|
||||
|
||||
emit(event, backend)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
</div>
|
||||
|
||||
<div class="column is-12" v-if="toggleForm">
|
||||
<BackendAdd @addBackend="toggleForm = false; loadContent()" :backends="backends"/>
|
||||
<BackendAdd @forceExport="e => handleEvents('forceExport', e)" :backends="backends"
|
||||
@runImport="e => handleEvents('runImport', e)" @addBackend="e => handleEvents('addBackend', e)"/>
|
||||
</div>
|
||||
<template v-else>
|
||||
<div class="column is-12" v-if="backends.length<1">
|
||||
@@ -257,4 +258,21 @@ const updateValue = async (backend, key, newValue) => {
|
||||
|
||||
backends.value[backends.value.findIndex(b => b.name === backend.name)] = await response.json()
|
||||
}
|
||||
|
||||
const handleEvents = async (event, backend) => {
|
||||
switch (event) {
|
||||
case 'forceExport':
|
||||
notification('warning', 'Warning', `We are going to sync '${backend.value.name}' play state to match the current local database.`, 10000)
|
||||
await navigateTo(makeConsoleCommand(`state:export -fi -v -s ${backend.value.name}`, true))
|
||||
break
|
||||
case 'runImport':
|
||||
notification('info', 'Info', `We are going to import '${backend.value.name}' play state to the local database.`, 10000)
|
||||
await navigateTo(makeConsoleCommand(`state:import -v -s ${backend.value.name}`, true))
|
||||
break
|
||||
case 'addBackend':
|
||||
toggleForm.value = false
|
||||
await loadContent()
|
||||
break
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -105,30 +105,22 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
import {useStorage} from '@vueuse/core'
|
||||
import {notification} from '~/utils/index.js'
|
||||
import Message from '~/components/Message.vue'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const fromTask = route.query.task || '';
|
||||
let fromCommand = route.query.cmd || '';
|
||||
if (fromCommand) {
|
||||
// -- decode base64
|
||||
fromCommand = atob(fromCommand);
|
||||
}
|
||||
import {notification} from '~/utils/index'
|
||||
import Message from '~/components/Message'
|
||||
|
||||
useHead({title: `Console`})
|
||||
|
||||
let sse;
|
||||
const route = useRoute()
|
||||
const fromCommand = route.query.cmd || false ? atob(route.query.cmd) : ''
|
||||
|
||||
const response = ref([]);
|
||||
const command = ref(fromCommand);
|
||||
const isLoading = ref(false);
|
||||
const outputConsole = ref();
|
||||
const hasPrefix = computed(() => command.value.startsWith('console') || command.value.startsWith('docker'));
|
||||
const hasPlaceholder = computed(() => command.value && command.value.match(/\[.*\]/));
|
||||
let sse
|
||||
const response = ref([])
|
||||
const command = ref(fromCommand)
|
||||
const isLoading = ref(false)
|
||||
const outputConsole = ref()
|
||||
const hasPrefix = computed(() => command.value.startsWith('console') || command.value.startsWith('docker'))
|
||||
const hasPlaceholder = computed(() => command.value && command.value.match(/\[.*\]/))
|
||||
const show_page_tips = useStorage('show_page_tips', true)
|
||||
|
||||
const RunCommand = async () => {
|
||||
@@ -153,60 +145,47 @@ const RunCommand = async () => {
|
||||
|
||||
response.value = []
|
||||
|
||||
const searchParams = new URLSearchParams();
|
||||
searchParams.append('apikey', api_token.value);
|
||||
searchParams.append('json', btoa(JSON.stringify({command: userCommand})));
|
||||
const searchParams = new URLSearchParams()
|
||||
searchParams.append('apikey', api_token.value)
|
||||
searchParams.append('json', btoa(JSON.stringify({command: userCommand})))
|
||||
|
||||
sse = new EventSource(`${api_url.value}${api_path.value}/system/command/?${searchParams.toString()}`)
|
||||
|
||||
sse = new EventSource(`${api_url.value}${api_path.value}/system/command/?${searchParams.toString()}`);
|
||||
|
||||
isLoading.value = true;
|
||||
isLoading.value = true
|
||||
|
||||
sse.addEventListener('data', async e => {
|
||||
let lines = e.data.split(/\n/g);
|
||||
let lines = e.data.split(/\n/g)
|
||||
for (let x = 0; x < lines.length; x++) {
|
||||
response.value.push(lines[x]);
|
||||
response.value.push(lines[x])
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
sse.addEventListener('close', () => finished());
|
||||
sse.onclose = () => finished();
|
||||
sse.onerror = () => finished();
|
||||
sse.addEventListener('close', () => finished())
|
||||
sse.onclose = () => finished()
|
||||
sse.onerror = () => finished()
|
||||
}
|
||||
|
||||
const finished = () => {
|
||||
if (sse) {
|
||||
sse.close();
|
||||
sse.close()
|
||||
}
|
||||
|
||||
isLoading.value = false;
|
||||
isLoading.value = false
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
const route = useRoute()
|
||||
|
||||
if (route.query?.cmd || route.query?.task) {
|
||||
route.query.cmd = '';
|
||||
route.query.task = '';
|
||||
router.push({path: '/console'});
|
||||
if (route.query?.cmd || route.query?.run) {
|
||||
route.query.cmd = ''
|
||||
route.query.run = ''
|
||||
useRouter().push({path: '/console'})
|
||||
}
|
||||
}
|
||||
|
||||
onUpdated(() => outputConsole.value.scrollTop = outputConsole.value.scrollHeight);
|
||||
onUpdated(() => outputConsole.value.scrollTop = outputConsole.value.scrollHeight)
|
||||
|
||||
onMounted(async () => {
|
||||
if (!fromTask && '' === command.value) {
|
||||
await RunCommand();
|
||||
return
|
||||
if (Boolean(route.query?.run ?? '0') || '' === command.value) {
|
||||
await RunCommand()
|
||||
}
|
||||
|
||||
if (!fromTask) {
|
||||
return
|
||||
}
|
||||
|
||||
const response = await request(`/tasks/${fromTask}`);
|
||||
const json = await response.json();
|
||||
command.value = `${json.command} ${json.args || ''}`;
|
||||
await RunCommand();
|
||||
});
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -180,7 +180,7 @@
|
||||
import 'assets/css/bulma-switch.css'
|
||||
import moment from 'moment'
|
||||
import request from '~/utils/request'
|
||||
import {awaitElement, notification, TOOLTIP_DATE_FORMAT} from '~/utils/index'
|
||||
import {awaitElement, makeConsoleCommand, notification, TOOLTIP_DATE_FORMAT} from '~/utils/index'
|
||||
import cronstrue from 'cronstrue'
|
||||
import Message from '~/components/Message'
|
||||
import {useStorage} from '@vueuse/core'
|
||||
@@ -272,6 +272,6 @@ const confirmRun = async task => {
|
||||
if (!confirm(`Run '${task.name}' via web console now?`)) {
|
||||
return
|
||||
}
|
||||
await navigateTo({path: '/console', query: {task: task.name}})
|
||||
await navigateTo(makeConsoleCommand(`${task.command} ${task.args || ''}`, true));
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -302,8 +302,11 @@ const copyText = (str, showNotification = true) => {
|
||||
notification('success', 'Success', 'Text copied to clipboard.')
|
||||
}
|
||||
|
||||
const makeConsoleCommand = (cmd) => {
|
||||
const makeConsoleCommand = (cmd, run = false) => {
|
||||
const params = new URLSearchParams();
|
||||
if (run) {
|
||||
params.append('run', 'true');
|
||||
}
|
||||
// -- base64 encode the command to prevent XSS
|
||||
params.append('cmd', btoa(cmd));
|
||||
return `/console?${params.toString()}`
|
||||
@@ -311,7 +314,6 @@ const makeConsoleCommand = (cmd) => {
|
||||
|
||||
const stringToRegex = (str) => new RegExp(str.match(/\/(.+)\/.*/)[1], str.match(/\/.+\/(.*)/)[1])
|
||||
|
||||
|
||||
/**
|
||||
* Make history search link.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user