Updated ENV web interface as well as the env API endpoint. Did some Facelift sn the Tasks page to be more mobile friendly.
This commit is contained in:
@@ -8,139 +8,168 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
return (function () {
|
return (function () {
|
||||||
// -- Do not forget to update the tasks list if you add a new task.
|
$env = [
|
||||||
$tasks = ['import', 'export', 'push', 'progress', 'backup', 'prune', 'indexes', 'requests'];
|
[
|
||||||
$task_env = [
|
'key' => 'WS_DATA_PATH',
|
||||||
'WS_CRON_{task}' => [
|
|
||||||
'desc' => 'Enable the {task} task.',
|
|
||||||
'type' => 'bool',
|
|
||||||
],
|
|
||||||
'WS_CRON_{task}_AT' => [
|
|
||||||
'desc' => 'The time to run the {task} task.',
|
|
||||||
'type' => 'string',
|
|
||||||
],
|
|
||||||
'WS_CRON_{task}_ARGS' => [
|
|
||||||
'desc' => 'The arguments to pass to the {task} task.',
|
|
||||||
'type' => 'string',
|
|
||||||
],
|
|
||||||
];
|
|
||||||
|
|
||||||
$env = [];
|
|
||||||
|
|
||||||
foreach ($tasks as $task) {
|
|
||||||
foreach ($task_env as $key => $info) {
|
|
||||||
$info['desc'] = r($info['desc'], ['task' => $task]);
|
|
||||||
$env[r($key, ['task' => strtoupper($task)])] = $info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$env = array_replace_recursive($env, [
|
|
||||||
'WS_DATA_PATH' => [
|
|
||||||
'description' => 'Where to store main data. (config, db).',
|
'description' => 'Where to store main data. (config, db).',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
],
|
],
|
||||||
'WS_TMP_DIR' => [
|
[
|
||||||
|
'key' => 'WS_TMP_DIR',
|
||||||
'description' => 'Where to store temp data. (logs, cache)',
|
'description' => 'Where to store temp data. (logs, cache)',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
],
|
],
|
||||||
'WS_TZ' => [
|
[
|
||||||
|
'key' => 'WS_TZ',
|
||||||
'description' => 'Set the Tool timezone.',
|
'description' => 'Set the Tool timezone.',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
],
|
],
|
||||||
'WS_LOGS_CONTEXT' => [
|
[
|
||||||
|
'key' => 'WS_LOGS_CONTEXT',
|
||||||
'description' => 'Enable context in logs.',
|
'description' => 'Enable context in logs.',
|
||||||
'type' => 'bool',
|
'type' => 'bool',
|
||||||
],
|
],
|
||||||
'WS_LOGGER_FILE_ENABLE' => [
|
[
|
||||||
|
'key' => 'WS_LOGGER_FILE_ENABLE',
|
||||||
'description' => 'Enable logging to app.log file',
|
'description' => 'Enable logging to app.log file',
|
||||||
'type' => 'bool',
|
'type' => 'bool',
|
||||||
],
|
],
|
||||||
'WS_LOGGER_FILE_LEVEL' => [
|
[
|
||||||
|
'key' => 'WS_LOGGER_FILE_LEVEL',
|
||||||
'description' => 'Set the log level for the file logger. Default: ERROR',
|
'description' => 'Set the log level for the file logger. Default: ERROR',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
],
|
],
|
||||||
'WS_WEBHOOK_DUMP_REQUEST' => [
|
[
|
||||||
|
'key' => 'WS_WEBHOOK_DUMP_REQUEST',
|
||||||
'description' => 'Dump all requests to webhook endpoint to a json file.',
|
'description' => 'Dump all requests to webhook endpoint to a json file.',
|
||||||
'type' => 'bool',
|
'type' => 'bool',
|
||||||
],
|
],
|
||||||
'WS_TRUST_PROXY' => [
|
[
|
||||||
|
'key' => 'WS_TRUST_PROXY',
|
||||||
'description' => 'Trust the IP from the WS_TRUST_HEADER header.',
|
'description' => 'Trust the IP from the WS_TRUST_HEADER header.',
|
||||||
'type' => 'bool',
|
'type' => 'bool',
|
||||||
],
|
],
|
||||||
'WS_TRUST_HEADER' => [
|
[
|
||||||
|
'key' => 'WS_TRUST_HEADER',
|
||||||
'description' => 'The header with the true user IP.',
|
'description' => 'The header with the true user IP.',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
],
|
],
|
||||||
'WS_LIBRARY_SEGMENT' => [
|
[
|
||||||
|
'key' => 'WS_LIBRARY_SEGMENT',
|
||||||
'description' => 'How many items to request per a request.',
|
'description' => 'How many items to request per a request.',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
],
|
],
|
||||||
'WS_CACHE_URL' => [
|
[
|
||||||
|
'key' => 'WS_CACHE_URL',
|
||||||
'description' => 'The URL to the cache server.',
|
'description' => 'The URL to the cache server.',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'mask' => true,
|
'mask' => true,
|
||||||
],
|
],
|
||||||
'WS_CACHE_NULL' => [
|
[
|
||||||
|
'key' => 'WS_CACHE_NULL',
|
||||||
'description' => 'Enable the null cache. This is useful for testing. Or first time container startup.',
|
'description' => 'Enable the null cache. This is useful for testing. Or first time container startup.',
|
||||||
'type' => 'bool',
|
'type' => 'bool',
|
||||||
],
|
],
|
||||||
'WS_WEBUI_ENABLED' => [
|
[
|
||||||
|
'key' => 'WS_WEBUI_ENABLED',
|
||||||
'description' => 'Enable the web UI.',
|
'description' => 'Enable the web UI.',
|
||||||
'type' => 'bool',
|
'type' => 'bool',
|
||||||
],
|
],
|
||||||
'WS_API_KEY' => [
|
[
|
||||||
|
'key' => 'WS_API_KEY',
|
||||||
'description' => 'The API key to allow access to the API',
|
'description' => 'The API key to allow access to the API',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'mask' => true,
|
'mask' => true,
|
||||||
],
|
],
|
||||||
'WS_LOGS_PRUNE_AFTER' => [
|
[
|
||||||
|
'key' => 'WS_LOGS_PRUNE_AFTER',
|
||||||
'description' => 'Prune logs after this many days.',
|
'description' => 'Prune logs after this many days.',
|
||||||
'type' => 'int',
|
'type' => 'int',
|
||||||
],
|
],
|
||||||
'WS_EXPORT_THRESHOLD' => [
|
[
|
||||||
|
'key' => 'WS_EXPORT_THRESHOLD',
|
||||||
'description' => 'Trigger full export mode if changes exceed this number.',
|
'description' => 'Trigger full export mode if changes exceed this number.',
|
||||||
'type' => 'int',
|
'type' => 'int',
|
||||||
],
|
],
|
||||||
'WS_EPISODES_DISABLE_GUID' => [
|
[
|
||||||
|
'key' => 'WS_EPISODES_DISABLE_GUID',
|
||||||
'description' => 'Disable the GUID field in the episodes.',
|
'description' => 'Disable the GUID field in the episodes.',
|
||||||
'type' => 'bool',
|
'type' => 'bool',
|
||||||
'deprecated' => true,
|
'deprecated' => true,
|
||||||
],
|
],
|
||||||
'WS_BACKENDS_FILE' => [
|
[
|
||||||
|
'key' => 'WS_BACKENDS_FILE',
|
||||||
'description' => 'The full path to the backends file.',
|
'description' => 'The full path to the backends file.',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
],
|
],
|
||||||
'WS_WEBHOOK_LOG_FILE_FORMAT' => [
|
[
|
||||||
|
'key' => 'WS_WEBHOOK_LOG_FILE_FORMAT',
|
||||||
'description' => 'The name format for the webhook log file. Anything inside {} will be replaced with data from the webhook payload.',
|
'description' => 'The name format for the webhook log file. Anything inside {} will be replaced with data from the webhook payload.',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
],
|
],
|
||||||
'WS_CACHE_PREFIX' => [
|
[
|
||||||
|
'key' => 'WS_CACHE_PREFIX',
|
||||||
'description' => 'The prefix for the cache keys.',
|
'description' => 'The prefix for the cache keys.',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
],
|
],
|
||||||
'WS_CACHE_PATH' => [
|
[
|
||||||
|
'key' => 'WS_CACHE_PATH',
|
||||||
'description' => 'The path to the cache directory. This is usually if the cache server is not available.',
|
'description' => 'The path to the cache directory. This is usually if the cache server is not available.',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
],
|
],
|
||||||
'WS_LOGGER_SYSLOG_FACILITY' => [
|
[
|
||||||
|
'key' => 'WS_LOGGER_SYSLOG_FACILITY',
|
||||||
'description' => 'The syslog facility to use.',
|
'description' => 'The syslog facility to use.',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
],
|
],
|
||||||
'WS_LOGGER_SYSLOG_ENABLED' => [
|
[
|
||||||
|
'key' => 'WS_LOGGER_SYSLOG_ENABLED',
|
||||||
'description' => 'Enable logging to syslog.',
|
'description' => 'Enable logging to syslog.',
|
||||||
'type' => 'bool',
|
'type' => 'bool',
|
||||||
],
|
],
|
||||||
'WS_LOGGER_SYSLOG_LEVEL' => [
|
[
|
||||||
|
'key' => 'WS_LOGGER_SYSLOG_LEVEL',
|
||||||
'description' => 'Set the log level for the syslog logger. Default: ERROR',
|
'description' => 'Set the log level for the syslog logger. Default: ERROR',
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
],
|
],
|
||||||
'WS_SECURE_API_ENDPOINTS' => [
|
[
|
||||||
|
'key' => 'WS_SECURE_API_ENDPOINTS',
|
||||||
'description' => 'Disregard the open route policy, and require an API key for all routes.',
|
'description' => 'Disregard the open route policy, and require an API key for all routes.',
|
||||||
'type' => 'bool',
|
'type' => 'bool',
|
||||||
],
|
],
|
||||||
]);
|
];
|
||||||
|
|
||||||
ksort($env);
|
// -- Do not forget to update the tasks list if you add a new task.
|
||||||
|
$tasks = ['import', 'export', 'push', 'progress', 'backup', 'prune', 'indexes', 'requests'];
|
||||||
|
$task_env = [
|
||||||
|
[
|
||||||
|
'key' => 'WS_CRON_{task}',
|
||||||
|
'description' => 'Enable the {task} task.',
|
||||||
|
'type' => 'bool',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'key' => 'WS_CRON_{task}_AT',
|
||||||
|
'description' => 'The time to run the {task} task.',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'key' => 'WS_CRON_{task}_ARGS',
|
||||||
|
'description' => 'The arguments to pass to the {task} task.',
|
||||||
|
'type' => 'string',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($tasks as $task) {
|
||||||
|
foreach ($task_env as $info) {
|
||||||
|
$info['key'] = r($info['key'], ['task' => strtoupper($task)]);
|
||||||
|
$info['description'] = r($info['description'], ['task' => $task]);
|
||||||
|
$env[] = $info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- sort based on the array name key
|
||||||
|
$sorter = array_column($env, 'key');
|
||||||
|
array_multisort($sorter, SORT_ASC, $env);
|
||||||
|
|
||||||
return $env;
|
return $env;
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -162,3 +162,24 @@ hr {
|
|||||||
.vue-notification-wrapper {
|
.vue-notification-wrapper {
|
||||||
padding-top: 0.5em;
|
padding-top: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card.is-danger {
|
||||||
|
border: var(--bulma-control-border-width) solid var(--bulma-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.is-info {
|
||||||
|
border: var(--bulma-control-border-width) solid var(--bulma-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.is-success {
|
||||||
|
border: var(--bulma-control-border-width) solid var(--bulma-success);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.is-warning {
|
||||||
|
border: var(--bulma-control-border-width) solid var(--bulma-warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.is-gray {
|
||||||
|
border: var(--bulma-control-border-width) solid rgba(56, 56, 56, 0.38);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<nav class="navbar is-dark mb-4">
|
<nav class="navbar is-dark mb-4">
|
||||||
<div class="navbar-brand pl-5">
|
<div class="navbar-brand pl-5">
|
||||||
<NuxtLink class="navbar-item" href="/">
|
<NuxtLink class="navbar-item" href="/" @click.native="showMenu=false">
|
||||||
<span class="icon-text">
|
<span class="icon-text">
|
||||||
<span class="icon"><i class="fas fa-home"></i></span>
|
<span class="icon"><i class="fas fa-home"></i></span>
|
||||||
<span>Home</span>
|
<span>Home</span>
|
||||||
@@ -18,49 +18,49 @@
|
|||||||
|
|
||||||
<div class="navbar-menu" :class="{'is-active':showMenu}">
|
<div class="navbar-menu" :class="{'is-active':showMenu}">
|
||||||
<div class="navbar-start">
|
<div class="navbar-start">
|
||||||
<NuxtLink class="navbar-item" href="/backends">
|
<NuxtLink class="navbar-item" href="/backends" @click.native="showMenu=false">
|
||||||
<span class="icon-text">
|
<span class="icon-text">
|
||||||
<span class="icon"><i class="fas fa-server"></i></span>
|
<span class="icon"><i class="fas fa-server"></i></span>
|
||||||
<span>Backends</span>
|
<span>Backends</span>
|
||||||
</span>
|
</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
<NuxtLink class="navbar-item" href="/history">
|
<NuxtLink class="navbar-item" href="/history" @click.native="showMenu=false">
|
||||||
<span class="icon-text">
|
<span class="icon-text">
|
||||||
<span class="icon"><i class="fas fa-history"></i></span>
|
<span class="icon"><i class="fas fa-history"></i></span>
|
||||||
<span>History</span>
|
<span>History</span>
|
||||||
</span>
|
</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
<NuxtLink class="navbar-item" href="/tasks">
|
<NuxtLink class="navbar-item" href="/tasks" @click.native="showMenu=false">
|
||||||
<span class="icon-text">
|
<span class="icon-text">
|
||||||
<span class="icon"><i class="fas fa-tasks"></i></span>
|
<span class="icon"><i class="fas fa-tasks"></i></span>
|
||||||
<span>Tasks</span>
|
<span>Tasks</span>
|
||||||
</span>
|
</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
<NuxtLink class="navbar-item" href="/env">
|
<NuxtLink class="navbar-item" href="/env" @click.native="showMenu=false">
|
||||||
<span class="icon-text">
|
<span class="icon-text">
|
||||||
<span class="icon"><i class="fas fa-cogs"></i></span>
|
<span class="icon"><i class="fas fa-cogs"></i></span>
|
||||||
<span>Env</span>
|
<span>Env</span>
|
||||||
</span>
|
</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
<NuxtLink class="navbar-item" href="/logs">
|
<NuxtLink class="navbar-item" href="/logs" @click.native="showMenu=false">
|
||||||
<span class="icon-text">
|
<span class="icon-text">
|
||||||
<span class="icon"><i class="fas fa-globe"></i></span>
|
<span class="icon"><i class="fas fa-globe"></i></span>
|
||||||
<span>Logs</span>
|
<span>Logs</span>
|
||||||
</span>
|
</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
<NuxtLink class="navbar-item" href="/console">
|
<NuxtLink class="navbar-item" href="/console" @click.native="showMenu=false">
|
||||||
<span class="icon-text">
|
<span class="icon-text">
|
||||||
<span class="icon"><i class="fas fa-terminal"></i></span>
|
<span class="icon"><i class="fas fa-terminal"></i></span>
|
||||||
<span>Console</span>
|
<span>Console</span>
|
||||||
</span>
|
</span>
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|
||||||
<NuxtLink class="navbar-item" href="/report">
|
<NuxtLink class="navbar-item" href="/report" @click.native="showMenu=false">
|
||||||
<span class="icon-text">
|
<span class="icon-text">
|
||||||
<span class="icon"><i class="fas fa-flag"></i></span>
|
<span class="icon"><i class="fas fa-flag"></i></span>
|
||||||
<span>S. Report</span>
|
<span>S. Report</span>
|
||||||
|
|||||||
@@ -31,15 +31,27 @@
|
|||||||
<div class="column is-12" v-if="toggleForm">
|
<div class="column is-12" v-if="toggleForm">
|
||||||
<form id="env_add_form" @submit.prevent="addVariable">
|
<form id="env_add_form" @submit.prevent="addVariable">
|
||||||
<div class="field is-grouped">
|
<div class="field is-grouped">
|
||||||
<div class="control is-expanded">
|
<div class="control has-icons-left">
|
||||||
<input class="input" type="text" placeholder="Key" v-model="form_key">
|
<div class="select is-fullwidth">
|
||||||
<p class="help has-text-danger" v-if="form_key && !form_key.toLowerCase().startsWith('ws_')">
|
<select v-model="form_key" id="form_key" @change="keyChanged">
|
||||||
Key Must start with WS_
|
<option value="" disabled>Select Key</option>
|
||||||
</p>
|
<option v-for="env in envs" :key="env.key" :value="env.key">
|
||||||
|
{{ env.key }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="icon is-small is-left">
|
||||||
|
<i class="fas fa-key"></i>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control is-expanded">
|
<div class="control is-expanded has-icons-left">
|
||||||
<input class="input" type="text" placeholder="Value" v-model="form_value">
|
<input class="input" id="form_value" type="text" placeholder="Value" v-model="form_value">
|
||||||
|
<div class="icon is-small is-left">
|
||||||
|
<i class="fas fa-font"></i>
|
||||||
|
</div>
|
||||||
|
<p class="help" v-html="getHelp(form_key)"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<button class="button is-danger" type="button"
|
<button class="button is-danger" type="button"
|
||||||
v-tooltip="'Cancel'" @click="form_key=null; form_value=null; toggleForm=false">
|
v-tooltip="'Cancel'" @click="form_key=null; form_value=null; toggleForm=false">
|
||||||
@@ -55,7 +67,7 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="column is-12">
|
<div class="column is-12" v-if="envs">
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<table class="table is-fullwidth is-bordered is-striped is-hoverable has-text-centered">
|
<table class="table is-fullwidth is-bordered is-striped is-hoverable has-text-centered">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -66,7 +78,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="env in envs" :key="env.key">
|
<tr v-for="env in filteredRows(envs)" :key="env.key">
|
||||||
<td class="has-text-left">
|
<td class="has-text-left">
|
||||||
{{ env.key }}
|
{{ env.key }}
|
||||||
<div class="is-pulled-right" v-if="env.mask">
|
<div class="is-pulled-right" v-if="env.mask">
|
||||||
@@ -115,14 +127,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import request from "~/utils/request.js";
|
import request from '~/utils/request.js'
|
||||||
import {awaitElement, notification} from "~/utils/index.js";
|
import {awaitElement, notification} from '~/utils/index.js'
|
||||||
|
|
||||||
useHead({title: 'Environment Variables'})
|
useHead({title: 'Environment Variables'})
|
||||||
|
|
||||||
const envs = ref([])
|
const envs = ref([])
|
||||||
const toggleForm = ref(false)
|
const toggleForm = ref(false)
|
||||||
const form_key = ref(null)
|
const form_key = ref('')
|
||||||
const form_value = ref(null)
|
const form_value = ref(null)
|
||||||
const file = ref('.env')
|
const file = ref('.env')
|
||||||
const copyAPI = navigator.clipboard
|
const copyAPI = navigator.clipboard
|
||||||
@@ -192,4 +204,33 @@ watch(toggleForm, (value) => {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const keyChanged = () => {
|
||||||
|
if (!form_key.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = envs.value.filter(i => i.key === form_key.value)
|
||||||
|
form_value.value = (data.length > 0) ? data[0].value : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const getHelp = (key) => {
|
||||||
|
if (!key) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = envs.value.filter(i => i.key === key)
|
||||||
|
if (data.length === 0) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
let text = `${data[0].description}`;
|
||||||
|
|
||||||
|
if (data[0].type) {
|
||||||
|
text += ` Expected value: <code>${('bool' === data[0].type) ? 'bool, 0, 1' : data[0].type}</code>`
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
const filteredRows = (rows) => rows.filter(i => i.value !== undefined);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -16,20 +16,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="is-hidden-mobile" v-if="queued.length > 0">
|
<div class="subtitle is-hidden-mobile" v-if="queued.length > 0">
|
||||||
<p>
|
<p>The following tasks <code>{{ queued.join(', ') }}</code> are queued to be run in background soon.</p>
|
||||||
<span>The following tasks <code>{{ queued.join(', ') }}</code> are queued to be run soon.</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-for="task in tasks" :key="task.name" class="column is-6-tablet is-12-mobile">
|
<div v-for="task in tasks" :key="task.name" class="column is-6-tablet is-12-mobile">
|
||||||
<div class="card">
|
<div class="card" :class="{ 'is-gray' : !task.enabled, 'is-success': task.enabled }">
|
||||||
<header class="card-header">
|
<header class="card-header">
|
||||||
<div class="is-capitalized card-header-title is-centered has-tooltip"
|
<div class="is-capitalized card-header-title">
|
||||||
v-tooltip="'The command: ' + task.command">
|
|
||||||
{{ task.name }}
|
{{ task.name }}
|
||||||
</div>
|
</div>
|
||||||
|
<span class="card-header-icon" v-tooltip="'Enable/Disable Task.'">
|
||||||
|
<input :id="task.name" type="checkbox" class="switch is-success" :checked="task.enabled"
|
||||||
|
@change="toggleTask(task)">
|
||||||
|
<label :for="task.name"></label>
|
||||||
|
</span>
|
||||||
</header>
|
</header>
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="columns is-multiline is-mobile has-text-centered">
|
<div class="columns is-multiline is-mobile has-text-centered">
|
||||||
@@ -71,20 +73,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<footer class="card-footer">
|
<footer class="card-footer">
|
||||||
<div class="card-footer-item">
|
<div class="card-footer-item">
|
||||||
<div class="field">
|
<button class="button is-info" @click="queueTask(task)" :disabled="task.queued || !task.enabled">
|
||||||
<input :id="task.name" type="checkbox" class="switch is-success" :checked="task.enabled"
|
|
||||||
@change="toggleTask(task)">
|
|
||||||
<label :for="task.name">
|
|
||||||
<span class="is-hidden-mobile">Task is </span> {{ task.enabled ? 'Enabled' : 'Disabled' }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer-item" v-if="task.enabled">
|
|
||||||
<button class="button is-info" @click="queueTask(task)" :disabled="task.queued">
|
|
||||||
<span class="icon-text">
|
<span class="icon-text">
|
||||||
<span class="icon"><i class="fas fa-clock"></i></span>
|
<span class="icon"><i class="fas fa-clock"></i></span>
|
||||||
<span v-if="!task.queued">Queue</span>
|
<span>
|
||||||
<span v-else>Queued</span>
|
<template v-if="!task.queued">Queue Task</template>
|
||||||
|
<template v-else>Queued</template>
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -138,7 +133,7 @@ const toggleTask = async (task) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const queueTask = async (task) => {
|
const queueTask = async (task) => {
|
||||||
if (!confirm(`Are you sure you want to queue the task ${task.name}?`)) {
|
if (!confirm(`Queue '${task.name}' to run in background?`)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +145,7 @@ const queueTask = async (task) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const confirmRun = async (task) => {
|
const confirmRun = async (task) => {
|
||||||
if (!confirm(`Are you sure you want to run ${task.name}?`)) {
|
if (!confirm(`Are you sure you want to run '${task.name}' via web console now?`)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await navigateTo({path: '/console', query: {task: task.name, keep: 1}})
|
await navigateTo({path: '/console', query: {task: task.name, keep: 1}})
|
||||||
|
|||||||
@@ -29,24 +29,17 @@ final class Env
|
|||||||
{
|
{
|
||||||
$spec = require __DIR__ . '/../../../config/env.spec.php';
|
$spec = require __DIR__ . '/../../../config/env.spec.php';
|
||||||
|
|
||||||
$response = [
|
foreach ($spec as &$info) {
|
||||||
'data' => [],
|
if (!$this->envFile->has($info['key'])) {
|
||||||
'file' => Config::get('path') . '/config/.env',
|
|
||||||
];
|
|
||||||
|
|
||||||
foreach ($this->envFile->getAll() as $key => $val) {
|
|
||||||
if (false === str_starts_with($key, 'WS_')) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
$info['value'] = $this->envFile->get($info['key']);
|
||||||
$response['data'][] = [
|
|
||||||
'key' => $key,
|
|
||||||
'value' => $val,
|
|
||||||
'mask' => (bool)ag($spec, "{$key}.mask", false),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return api_response(HTTP_STATUS::HTTP_OK, $response);
|
return api_response(HTTP_STATUS::HTTP_OK, [
|
||||||
|
'data' => $spec,
|
||||||
|
'file' => Config::get('path') . '/config/.env',
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Get(self::URL . '/{key}[/]', name: 'system.env.view')]
|
#[Get(self::URL . '/{key}[/]', name: 'system.env.view')]
|
||||||
|
|||||||
Reference in New Issue
Block a user