Finished settings page
@@ -30,9 +30,9 @@ export default {
|
||||
|
||||
mounted() {
|
||||
const that = this;
|
||||
this.$store.dispatch("dlcache/update", this);
|
||||
this.$store.dispatch("dlcache/update");
|
||||
setInterval(function(){
|
||||
that.$store.dispatch("dlcache/update", that);
|
||||
that.$store.dispatch("dlcache/update");
|
||||
}, 1000);
|
||||
return;
|
||||
}
|
||||
|
@@ -23,9 +23,9 @@ export default {
|
||||
|
||||
mounted() {
|
||||
const that = this;
|
||||
this.$store.dispatch("logs/update", this);
|
||||
this.$store.dispatch("logs/update");
|
||||
setInterval(function(){
|
||||
that.$store.dispatch("logs/update", that);
|
||||
that.$store.dispatch("logs/update");
|
||||
}, 1000);
|
||||
return;
|
||||
}
|
||||
|
@@ -16,10 +16,16 @@ export default {
|
||||
meta: [
|
||||
{ charset: 'utf-8' },
|
||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
||||
{ hid: 'description', name: 'description', content: '' }
|
||||
{ hid: 'description', name: 'description', content: '' },
|
||||
{ name: 'msapplication-TileColor', content: '#031934' },
|
||||
{ name: 'theme-color', content: '#031934' },
|
||||
],
|
||||
link: [
|
||||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
|
||||
{ rel: 'apple-touch-icon', sizes: "180x180", href: '/apple-touch-icon.png' },
|
||||
{ rel: 'icon', type: "image/png", sizes: "32x32", href: '/favicon-32x32.png' },
|
||||
{ rel: 'icon', type: "image/png", sizes: "16x16", href: '/favicon-16x16.png' },
|
||||
{ rel: 'manifest', href: '/site.webmanifest' },
|
||||
{ rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#031934' },
|
||||
]
|
||||
},
|
||||
|
||||
|
@@ -2,13 +2,20 @@
|
||||
<div>
|
||||
|
||||
<div class="hidden md:block">
|
||||
<Spacer height="0.5em" m_height="1em" />
|
||||
<Spacer height="0" m_height="1em" />
|
||||
<Logo class="logo mt-4" />
|
||||
<Spacer height="2em" m_height="2em" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row flex-wrap md:flex-no-wrap input-flex justify-between md:justify-center">
|
||||
<input class="flex-grow md:mr-4 mb-2 md:mb-0 w-full" type="url" name="video_url" id="video_url" ref="video_url" placeholder="video-url">
|
||||
<input class="flex-grow md:mr-4 mb-2 md:mb-0 w-full"
|
||||
type="url"
|
||||
name="video_url"
|
||||
id="video_url"
|
||||
ref="video_url"
|
||||
placeholder="video-url"
|
||||
v-on:keydown="keyMonitor"
|
||||
/>
|
||||
|
||||
<div class="w-full md:hidden" />
|
||||
|
||||
@@ -47,7 +54,7 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
downloadButtonClicked: function(){
|
||||
downloadButtonClicked: function() {
|
||||
|
||||
const that = this;
|
||||
if (this.$refs.video_url.value.match(/(https?:\/\/)?[a-zA-Z0-9-_.]+\.[a-zA-Z-_.]+/)) {
|
||||
@@ -63,7 +70,13 @@ export default {
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
keyMonitor: function(event) {
|
||||
if (event.key == "Enter") {
|
||||
this.downloadButtonClicked();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@@ -9,26 +9,70 @@
|
||||
|
||||
<div class="w-full lg:w-1/2 border-right lg:pr-3">
|
||||
|
||||
<div v-if="serverOs === 'Windows'" class="option toggle flex justify-between items-center">
|
||||
<p>Show console</p>
|
||||
<Toggle :isOn="false"/>
|
||||
</div>
|
||||
<div v-if="typeof(getSettings().general) != 'undefined'">
|
||||
<div v-if="serverOs === 'Windows'" class="option toggle flex justify-between items-center">
|
||||
<p>Show console</p>
|
||||
<div v-on:click="setSettings_toggle_showConsole">
|
||||
<Toggle
|
||||
:isOn="getSettings().general.show_console"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="option text narrow flex justify-between w-full items-center">
|
||||
<p class="mr-3">Max speed</p>
|
||||
<input type="text" id="max_speed" name="max_speed" placeholder="100M">
|
||||
</div>
|
||||
<div class="option text narrow flex justify-between w-full items-center">
|
||||
<p class="mr-3">Max speed</p>
|
||||
<input
|
||||
type="text"
|
||||
id="max_speed"
|
||||
name="max_speed"
|
||||
placeholder="100M"
|
||||
v-model="getSettings().downloader.max_dlrate_per_thread"
|
||||
v-on:focusout="setSettings_pushCurrentStore"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="option text narrow flex justify-between w-full items-center">
|
||||
<p class="mr-3">Download threads</p>
|
||||
<input type="text" id="max_threads" name="max_threads" placeholder="10">
|
||||
</div>
|
||||
<div class="option text narrow flex justify-between w-full items-center">
|
||||
<p class="mr-3">Download threads</p>
|
||||
<input
|
||||
type="number"
|
||||
id="max_threads"
|
||||
name="max_threads"
|
||||
placeholder="10"
|
||||
v-model.number="getSettings().downloader.num_threads"
|
||||
v-on:focusout="setSettings_pushCurrentStore"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="option toggle flex justify-between items-center">
|
||||
<p>Only allow localhost</p>
|
||||
<div v-on:click="setSettings_toggle_onlyAllowLocalhost">
|
||||
<Toggle
|
||||
:isOn="getSettings().access.only_allow_localhost"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="option toggle flex justify-between items-center">
|
||||
<p>Enable whitelist</p>
|
||||
<Toggle :isOn="false"/>
|
||||
<div v-on:click="setSettings_toggle_enableWhitelist">
|
||||
<Toggle
|
||||
:isOn="getSettings().access.enable_whitelist"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Spacer height="2em" />
|
||||
<div v-if="getSettings().access.enable_whitelist">
|
||||
<h2>Whitelist</h2>
|
||||
<textarea class="mt-2 w-full" ref="whitelist_input" v-on:input="whitelistInputJsonSyntaxCheck" />
|
||||
<div class="flex w-full">
|
||||
<div class="button button--small button--nowarn mt-2 mr-2" v-on:click="saveWhitelist" ref="button_saveWhitelist">Save whitelist</div>
|
||||
<div class="button button--small button--nowarn mt-2" v-on:click="updateWhitelist">Update whitelist</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="w-full lg:w-1/2 border-left lg:pl-3 mt-6 lg:mt-0">
|
||||
@@ -68,6 +112,7 @@
|
||||
</div>
|
||||
<div class="flex flex-col ml-1">
|
||||
<div class="button" v-on:click="killServer">Kill server</div>
|
||||
<div class="button mt-2" v-on:click="resetToDefaults">Reset to defaults</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -112,7 +157,7 @@ export default {
|
||||
},
|
||||
serverOs: function() {
|
||||
return this.$store.state.serverOs.os_name;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -163,11 +208,112 @@ export default {
|
||||
});
|
||||
return;
|
||||
},
|
||||
|
||||
resetToDefaults: function() {
|
||||
this.$store.dispatch("settings/resetToDefaults");
|
||||
},
|
||||
|
||||
getSettings: function() {
|
||||
return this.$store.state.settings.config;
|
||||
},
|
||||
|
||||
setSettings_toggle_showConsole: function() {
|
||||
var curConf = this.getSettings();
|
||||
curConf.general.show_console = !curConf.general.show_console;
|
||||
this.$store.commit("settings/updateGet", curConf); // Apply changes to frontend immediately
|
||||
this.$store.dispatch("settings/updateSet", curConf); // Push to server, and update frontend again after response
|
||||
return;
|
||||
},
|
||||
setSettings_toggle_onlyAllowLocalhost: function() {
|
||||
var curConf = this.getSettings();
|
||||
curConf.access.only_allow_localhost = !curConf.access.only_allow_localhost;
|
||||
this.$store.commit("settings/updateGet", curConf); // Apply changes to frontend immediately
|
||||
this.$store.dispatch("settings/updateSet", curConf); // Push to server, and update frontend again after response
|
||||
return;
|
||||
},
|
||||
setSettings_toggle_enableWhitelist: function() {
|
||||
var curConf = this.getSettings();
|
||||
curConf.access.enable_whitelist = !curConf.access.enable_whitelist;
|
||||
this.$store.commit("settings/updateGet", curConf); // Apply changes to frontend immediately
|
||||
this.$store.dispatch("settings/updateSet", curConf); // Push to server, and update frontend again after response
|
||||
|
||||
if (curConf.access.enable_whitelist) {
|
||||
this.whitelistToInputfield();
|
||||
}
|
||||
return;
|
||||
},
|
||||
setSettings_pushCurrentStore: function() {
|
||||
this.$store.dispatch("settings/updateSet", this.getSettings());
|
||||
return;
|
||||
},
|
||||
|
||||
whitelistToInputfield: function() {
|
||||
// If this.$refs.whitelist_input is still undefined, just try again later, lmao
|
||||
if (typeof(this.$refs.whitelist_input) === "undefined") {
|
||||
setTimeout(this.whitelistToInputfield, 200);
|
||||
}
|
||||
else {
|
||||
var whitelistString = JSON.stringify(this.getSettings().access.whitelist, undefined, 2);
|
||||
this.$refs.whitelist_input.value = whitelistString;
|
||||
return whitelistString;
|
||||
}
|
||||
},
|
||||
|
||||
saveWhitelist: function() {
|
||||
const prevContent = this.$refs.whitelist_input.value;
|
||||
const element = this.$refs.whitelist_input;
|
||||
try {
|
||||
const arrayWhitelist = JSON.parse(prevContent);
|
||||
var curConf = this.getSettings();
|
||||
curConf.access.whitelist = arrayWhitelist;
|
||||
this.$store.commit("settings/updateGet", curConf); // Apply changes to frontend immediately
|
||||
this.whitelistToInputfield();
|
||||
this.$store.dispatch("settings/updateSet", curConf); // Push to server, and update frontend again after response
|
||||
element.classList.remove("inputfield--error");
|
||||
} catch (e) {
|
||||
this.$refs.whitelist_input.value = prevContent;
|
||||
element.classList.add("inputfield--error");
|
||||
this.$refs.button_saveWhitelist.classList.add("button--disabled");
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
updateWhitelist: function() {
|
||||
const that = this;
|
||||
this.$store.dispatch("settings/updateGet", function() {
|
||||
that.whitelistToInputfield();
|
||||
that.whitelistInputJsonSyntaxCheck();
|
||||
return;
|
||||
});
|
||||
return;
|
||||
},
|
||||
|
||||
whitelistInputJsonSyntaxCheck: function() {
|
||||
const element = this.$refs.whitelist_input;
|
||||
try {
|
||||
JSON.parse(element.value);
|
||||
element.classList.remove("inputfield--error");
|
||||
this.$refs.button_saveWhitelist.classList.remove("button--disabled");
|
||||
} catch (e) {
|
||||
element.classList.add("inputfield--error");
|
||||
this.$refs.button_saveWhitelist.classList.add("button--disabled");
|
||||
}
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$store.dispatch("diskUsage/update", this);
|
||||
this.$store.dispatch("serverOs/update", this);
|
||||
const that = this;
|
||||
|
||||
this.$store.dispatch("diskUsage/update");
|
||||
this.$store.dispatch("serverOs/update");
|
||||
this.$store.dispatch("settings/updateGet", function() {
|
||||
that.whitelistToInputfield();
|
||||
});
|
||||
|
||||
setInterval(function(){
|
||||
that.$store.dispatch("settings/updateGet");
|
||||
}, 1000);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -197,6 +343,19 @@ h2 {
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
color: theme("colors.purple-0");
|
||||
border-radius: 5px;
|
||||
font-size: 16pt;
|
||||
padding: 0.7em;
|
||||
min-height: 200px;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&.inputfield--error {
|
||||
background-color: #f77;
|
||||
}
|
||||
}
|
||||
|
||||
.option {
|
||||
color: theme("colors.text-gray-1");
|
||||
font-size: 18pt;
|
||||
@@ -239,12 +398,30 @@ h2 {
|
||||
color: #000;
|
||||
font-family: ZillaSlab, serif;
|
||||
font-size: 18pt;
|
||||
transition: background-color 0.2s;
|
||||
width: 200px;
|
||||
transition:
|
||||
background-color 0.2s,
|
||||
opacity 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-color: theme("colors.text-error-1");
|
||||
}
|
||||
|
||||
&--small {
|
||||
font-size: 14pt;
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
&--nowarn:hover {
|
||||
background-color: theme("colors.purple-1");
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
cursor: pointer;
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
|
BIN
tubio-frontend-nuxt-app/static/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
tubio-frontend-nuxt-app/static/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
tubio-frontend-nuxt-app/static/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
9
tubio-frontend-nuxt-app/static/browserconfig.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/mstile-150x150.png"/>
|
||||
<TileColor>#da532c</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
BIN
tubio-frontend-nuxt-app/static/favicon-16x16.png
Normal file
After Width: | Height: | Size: 672 B |
BIN
tubio-frontend-nuxt-app/static/favicon-32x32.png
Normal file
After Width: | Height: | Size: 948 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 15 KiB |
BIN
tubio-frontend-nuxt-app/static/mstile-150x150.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
15
tubio-frontend-nuxt-app/static/safari-pinned-tab.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="595.000000pt" height="595.000000pt" viewBox="0 0 595.000000 595.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,595.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M0 2975 l0 -2415 2975 0 2975 0 0 2415 0 2415 -2975 0 -2975 0 0
|
||||
-2415z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 603 B |
19
tubio-frontend-nuxt-app/static/site.webmanifest
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "",
|
||||
"short_name": "",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
@@ -11,13 +11,13 @@ export const mutations = {
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
update(context, instance) {
|
||||
update(context) {
|
||||
axios.post("/api", {
|
||||
request: "get_disk_usage"
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
instance.$store.commit("diskUsage/update", response.data.disk_usage);
|
||||
context.commit("update", response.data.disk_usage);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@@ -11,13 +11,13 @@ export const mutations = {
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
update(context, instance) {
|
||||
update(context) {
|
||||
axios.post("/api", {
|
||||
request: "fetch_alltime_cache"
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
instance.$store.commit("dlcache/update", response.data.cache);
|
||||
context.commit("update", response.data.cache);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@@ -11,13 +11,13 @@ export const mutations = {
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
update(context, instance) {
|
||||
update(context) {
|
||||
axios.post("/api", {
|
||||
request: "fetch_session_logs"
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
instance.$store.commit("logs/update", response.data.logs);
|
||||
context.commit("update", response.data.logs);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@@ -11,13 +11,13 @@ export const mutations = {
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
update(context, instance) {
|
||||
update(context) {
|
||||
axios.post("/api", {
|
||||
request: "get_os_name"
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
instance.$store.commit("serverOs/update", response.data.os_name);
|
||||
context.commit("update", response.data.os_name);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@@ -0,0 +1,48 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export const state = () => ({
|
||||
config: {}
|
||||
});
|
||||
|
||||
export const mutations = {
|
||||
updateGet(state, data) {
|
||||
state.config = data;
|
||||
},
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
updateGet(context, callback) {
|
||||
axios.post("/api", {
|
||||
request: "update_config"
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
context.commit("updateGet", response.data.config);
|
||||
if (typeof(callback) === "function") callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
updateSet(context, newConfig) {
|
||||
axios.post("/api", {
|
||||
request: "update_config",
|
||||
config: newConfig
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
// Also update the vuex store...
|
||||
context.commit("updateGet", response.data.config);
|
||||
}
|
||||
});
|
||||
},
|
||||
resetToDefaults(context) {
|
||||
axios.post("/api", {
|
||||
request: "reset_config_to_default_values"
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
// Also update the vuex store...
|
||||
context.commit("updateGet", response.data.config);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|