mirror of
https://github.com/seriousm4x/UpSnap.git
synced 2026-07-22 05:32:27 -04:00
set custom icon
- split settings collection into settings_private and settings_public - add icon input to frontend
This commit is contained in:
@@ -13,14 +13,14 @@ var CronPing *cron.Cron
|
||||
var CronWakeShutdown *cron.Cron
|
||||
|
||||
func RunPing(app *pocketbase.PocketBase) {
|
||||
settingsRecords, err := app.Dao().FindRecordsByExpr("settings")
|
||||
settingsPrivateRecords, err := app.Dao().FindRecordsByExpr("settings_private")
|
||||
if err != nil {
|
||||
logger.Error.Println(err)
|
||||
}
|
||||
|
||||
// init cronjob
|
||||
CronPing = cron.New()
|
||||
CronPing.AddFunc(settingsRecords[0].GetString("interval"), func() {
|
||||
CronPing.AddFunc(settingsPrivateRecords[0].GetString("interval"), func() {
|
||||
// skip cron if no realtime clients connected
|
||||
realtimeClients := len(app.SubscriptionsBroker().Clients())
|
||||
if realtimeClients == 0 {
|
||||
|
||||
80
backend/migrations/1678400249_created_settings_public.go
Normal file
80
backend/migrations/1678400249_created_settings_public.go
Normal file
@@ -0,0 +1,80 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
jsonData := `{
|
||||
"id": "t1rajoyzl6691g3",
|
||||
"created": "2023-03-09 22:17:29.463Z",
|
||||
"updated": "2023-03-09 22:17:29.463Z",
|
||||
"name": "settings_public",
|
||||
"type": "base",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"system": false,
|
||||
"id": "s1grje98",
|
||||
"name": "website_title",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "tlzz87pj",
|
||||
"name": "favicon",
|
||||
"type": "file",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSelect": 1,
|
||||
"maxSize": 5242880,
|
||||
"mimeTypes": [
|
||||
"image/x-icon",
|
||||
"image/png",
|
||||
"image/svg+xml",
|
||||
"image/gif",
|
||||
"image/jpeg"
|
||||
],
|
||||
"thumbs": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"listRule": "",
|
||||
"viewRule": "",
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"options": {}
|
||||
}`
|
||||
|
||||
collection := &models.Collection{}
|
||||
if err := json.Unmarshal([]byte(jsonData), &collection); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return daos.New(db).SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("t1rajoyzl6691g3")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dao.DeleteCollection(collection)
|
||||
})
|
||||
}
|
||||
65
backend/migrations/1678400310_updated_settings.go
Normal file
65
backend/migrations/1678400310_updated_settings.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models/schema"
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("nmj3ko20gzkg8n3")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
collection.Name = "settings_private"
|
||||
|
||||
collection.ListRule = nil
|
||||
|
||||
collection.ViewRule = nil
|
||||
|
||||
// remove
|
||||
collection.Schema.RemoveField("slrjkipw")
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("nmj3ko20gzkg8n3")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
collection.Name = "settings"
|
||||
|
||||
collection.ListRule = types.Pointer("@request.auth.id != \"\"")
|
||||
|
||||
collection.ViewRule = types.Pointer("@request.auth.id != \"\"")
|
||||
|
||||
// add
|
||||
del_website_title := &schema.SchemaField{}
|
||||
json.Unmarshal([]byte(`{
|
||||
"system": false,
|
||||
"id": "slrjkipw",
|
||||
"name": "website_title",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
}`), del_website_title)
|
||||
collection.Schema.AddField(del_website_title)
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
})
|
||||
}
|
||||
@@ -70,12 +70,12 @@ func HandlerScan(c echo.Context) error {
|
||||
}
|
||||
|
||||
// check if scan range is valid
|
||||
allSettings, err := App.Dao().FindRecordsByExpr("settings")
|
||||
allPrivateSettings, err := App.Dao().FindRecordsByExpr("settings_private")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
settings := allSettings[0]
|
||||
scanRange := settings.GetString("scan_range")
|
||||
settingsPrivate := allPrivateSettings[0]
|
||||
scanRange := settingsPrivate.GetString("scan_range")
|
||||
_, ipNet, err := net.ParseCIDR(scanRange)
|
||||
if err != nil {
|
||||
return apis.NewBadRequestError(err.Error(), nil)
|
||||
|
||||
@@ -85,7 +85,7 @@ func StartPocketBase(distDirFS fs.FS) {
|
||||
// add event hook before starting server.
|
||||
// using this outside App.OnBeforeServe() would not work
|
||||
App.OnModelAfterUpdate().Add(func(e *core.ModelEvent) error {
|
||||
if e.Model.TableName() == "settings" {
|
||||
if e.Model.TableName() == "settings_private" {
|
||||
for _, job := range cronjobs.CronPing.Entries() {
|
||||
cronjobs.CronPing.Remove(job.ID)
|
||||
}
|
||||
@@ -119,18 +119,32 @@ func StartPocketBase(distDirFS fs.FS) {
|
||||
}
|
||||
|
||||
func importSettings() error {
|
||||
// get first settings record
|
||||
settingsRecords, err := App.Dao().FindRecordsByExpr("settings")
|
||||
// get first settingsPrivate record
|
||||
settingsPrivateRecords, err := App.Dao().FindRecordsByExpr("settings_private")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
settingsCollection, err := App.Dao().FindCollectionByNameOrId("settings")
|
||||
settingsPrivateCollection, err := App.Dao().FindCollectionByNameOrId("settings_private")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
settings := models.NewRecord(settingsCollection)
|
||||
if len(settingsRecords) > 0 {
|
||||
settings = settingsRecords[0]
|
||||
settingsPrivate := models.NewRecord(settingsPrivateCollection)
|
||||
if len(settingsPrivateRecords) > 0 {
|
||||
settingsPrivate = settingsPrivateRecords[0]
|
||||
}
|
||||
|
||||
// get first settingsPublic record
|
||||
settingsPublicRecords, err := App.Dao().FindRecordsByExpr("settings_public")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
settingsPublicCollection, err := App.Dao().FindCollectionByNameOrId("settings_public")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
settingsPublic := models.NewRecord(settingsPublicCollection)
|
||||
if len(settingsPublicRecords) > 0 {
|
||||
settingsPublic = settingsPublicRecords[0]
|
||||
}
|
||||
|
||||
// set ping interval settings. priority:
|
||||
@@ -138,22 +152,22 @@ func importSettings() error {
|
||||
// 2nd: database entry
|
||||
// 3rd: default values
|
||||
interval := "@every 3s"
|
||||
if settings.GetString("interval") != "" {
|
||||
interval = settings.GetString("interval")
|
||||
if settingsPrivate.GetString("interval") != "" {
|
||||
interval = settingsPrivate.GetString("interval")
|
||||
}
|
||||
if os.Getenv("UPSNAP_INTERVAL") != "" {
|
||||
interval = os.Getenv("UPSNAP_INTERVAL")
|
||||
}
|
||||
|
||||
// save settings to db
|
||||
settings.Set("interval", interval)
|
||||
settingsPrivate.Set("interval", interval)
|
||||
if scanRange := os.Getenv("UPSNAP_SCAN_RANGE"); scanRange != "" {
|
||||
settings.Set("scan_range", scanRange)
|
||||
settingsPrivate.Set("scan_range", scanRange)
|
||||
}
|
||||
if scanRange := os.Getenv("UPSNAP_WEBSITE_TITLE"); scanRange != "" {
|
||||
settings.Set("website_title", scanRange)
|
||||
if websiteTitle := os.Getenv("UPSNAP_WEBSITE_TITLE"); websiteTitle != "" {
|
||||
settingsPublic.Set("website_title", websiteTitle)
|
||||
}
|
||||
if err := App.Dao().SaveRecord(settings); err != nil {
|
||||
if err := App.Dao().SaveRecord(settingsPublic); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<html lang="en" class="h-100">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%sveltekit.assets%/gopher.svg" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
%sveltekit.head%
|
||||
</head>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { dev } from '$app/environment';
|
||||
import { parseISO, formatDistance } from 'date-fns';
|
||||
import { pocketbase } from '@stores/pocketbase';
|
||||
import Fa from 'svelte-fa/src/fa.svelte';
|
||||
import {
|
||||
faPowerOff,
|
||||
faEllipsisVertical,
|
||||
@@ -10,7 +11,6 @@
|
||||
faCircleDown,
|
||||
faLock
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import Fa from 'svelte-fa/src/fa.svelte';
|
||||
import { sortPorts } from '../sorts';
|
||||
|
||||
export let device;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script>
|
||||
import { goto } from '$app/navigation';
|
||||
import { pocketbase, devices } from '@stores/pocketbase';
|
||||
import Fa from 'svelte-fa/src/fa.svelte';
|
||||
import { faEye, faEyeSlash, faPlus, faTrashCan } from '@fortawesome/free-solid-svg-icons';
|
||||
import Fa from 'svelte-fa';
|
||||
|
||||
export let device;
|
||||
export let mode;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { pocketbase, authorizedStore } from '@stores/pocketbase';
|
||||
import { pocketbase, authorizedStore, settings_public } from '@stores/pocketbase';
|
||||
|
||||
let username;
|
||||
let password;
|
||||
@@ -43,7 +43,13 @@
|
||||
<div class="container text-dark-emphasis">
|
||||
<div class="row justify-content-center align-items-center">
|
||||
<div class="col text-center p-3 p-md-5">
|
||||
<img src="/gopher.svg" alt="Logo" class="logo pe-none user-select-none" />
|
||||
<img
|
||||
src={$settings_public.favicon !== ''
|
||||
? `${$pocketbase.baseUrl}/api/files/settings_public/${$settings_public.id}/${$settings_public.favicon}`
|
||||
: '/gopher.svg'}
|
||||
alt={$settings_public.website_title ? $settings_public.website_title : 'UpSnap'}
|
||||
class="logo pe-none user-select-none"
|
||||
/>
|
||||
<h2 class="text-dark-emphasis fw-bold text-center mt-3">Login</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { theme } from '@stores/theme';
|
||||
import { pocketbase, authorizedStore, settings } from '@stores/pocketbase';
|
||||
import { pocketbase, authorizedStore, settings_public } from '@stores/pocketbase';
|
||||
import Fa from 'svelte-fa/src/fa.svelte';
|
||||
import {
|
||||
faSun,
|
||||
faMoon,
|
||||
@@ -10,7 +11,6 @@
|
||||
faBrush,
|
||||
faRightFromBracket
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import Fa from 'svelte-fa';
|
||||
|
||||
let userInfo = {
|
||||
usernameOrEmail: '',
|
||||
@@ -18,11 +18,6 @@
|
||||
};
|
||||
|
||||
onMount(async () => {
|
||||
$pocketbase.collection('settings').subscribe('*', function (e) {
|
||||
settings.set(e.record);
|
||||
document.title = $settings.website_title;
|
||||
});
|
||||
|
||||
if ($pocketbase.authStore.baseModel?.collectionName === 'users') {
|
||||
userInfo.role = 'user';
|
||||
} else {
|
||||
@@ -41,24 +36,18 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
{#if $settings.website_title !== ''}
|
||||
<title>{$settings.website_title}</title>
|
||||
{:else}
|
||||
<title>UpSnap</title>
|
||||
{/if}
|
||||
</svelte:head>
|
||||
|
||||
<nav class="navbar navbar-expand-sm pt-0">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/">
|
||||
<img
|
||||
src="/gopher.svg"
|
||||
alt="UpSnap"
|
||||
src={$settings_public.favicon !== ''
|
||||
? `${$pocketbase.baseUrl}/api/files/settings_public/${$settings_public.id}/${$settings_public.favicon}`
|
||||
: '/gopher.svg'}
|
||||
alt={$settings_public.website_title ? $settings_public.website_title : 'UpSnap'}
|
||||
width="45"
|
||||
height="45"
|
||||
class:me-2={$settings.website_title !== ''}
|
||||
/>{$settings.website_title ? $settings.website_title : ''}
|
||||
class:me-2={$settings_public.website_title !== ''}
|
||||
/>{$settings_public.website_title ? $settings_public.website_title : ''}
|
||||
</a>
|
||||
<button
|
||||
class="navbar-toggler border-0"
|
||||
|
||||
@@ -5,8 +5,15 @@
|
||||
import Login from '@components/Login.svelte';
|
||||
import Transition from '@components/Transition.svelte';
|
||||
import { theme } from '@stores/theme';
|
||||
import { pocketbase, authorizedStore, devices, settings } from '@stores/pocketbase';
|
||||
import {
|
||||
pocketbase,
|
||||
authorizedStore,
|
||||
devices,
|
||||
settings_private,
|
||||
settings_public
|
||||
} from '@stores/pocketbase';
|
||||
|
||||
let favicon;
|
||||
let preferesDark;
|
||||
let isAuth = false;
|
||||
|
||||
@@ -38,6 +45,15 @@
|
||||
isAuth = state;
|
||||
});
|
||||
|
||||
// load public settings and subscribe to changes and change favicon
|
||||
const settingsPublicRes = await $pocketbase.collection('settings_public').getList(1, 1);
|
||||
settings_public.set(settingsPublicRes.items[0]);
|
||||
updateSettingsPublic();
|
||||
$pocketbase.collection('settings_public').subscribe('*', function (e) {
|
||||
settings_public.set(e.record);
|
||||
updateSettingsPublic();
|
||||
});
|
||||
|
||||
// load auth from localstorage
|
||||
const pbCookie = localStorage.getItem('pocketbase_auth');
|
||||
if (pbCookie) {
|
||||
@@ -55,10 +71,18 @@
|
||||
}
|
||||
});
|
||||
|
||||
async function getSettingsAndDevices() {
|
||||
let settingsRes = {};
|
||||
settingsRes = await $pocketbase.collection('settings').getList(1, 1);
|
||||
settings.set(settingsRes.items[0]);
|
||||
function updateSettingsPublic() {
|
||||
favicon.href =
|
||||
$settings_public.favicon === ''
|
||||
? '/gopher.svg'
|
||||
: `${$pocketbase.baseUrl}/api/files/settings_public/${$settings_public.id}/${$settings_public.favicon}`;
|
||||
document.title =
|
||||
$settings_public.website_title === '' ? 'UpSnap' : $settings_public.website_title;
|
||||
}
|
||||
|
||||
async function getSettingsPrivateAndDevices() {
|
||||
const settingsPrivateRes = await $pocketbase.collection('settings_private').getList(1, 1);
|
||||
settings_private.set(settingsPrivateRes.items[0]);
|
||||
|
||||
let tempDevices = {};
|
||||
const devicesRes = await $pocketbase.collection('devices').getFullList(200, {
|
||||
@@ -72,11 +96,12 @@
|
||||
}
|
||||
|
||||
$: if (isAuth) {
|
||||
getSettingsAndDevices();
|
||||
getSettingsPrivateAndDevices();
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<link rel="shortcut icon" href="/gopher.svg" bind:this={favicon} />
|
||||
<script>
|
||||
if (document) {
|
||||
preferesDark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
<script>
|
||||
import { dev } from '$app/environment';
|
||||
import { pocketbase, settings, devices } from '@stores/pocketbase';
|
||||
import { pocketbase, settings_private, settings_public, devices } from '@stores/pocketbase';
|
||||
import UnauthorizedMsg from '@components/UnauthorizedMsg.svelte';
|
||||
import DeviceForm from '@components/DeviceForm.svelte';
|
||||
import Fa from 'svelte-fa/src/fa.svelte';
|
||||
import { faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import Fa from 'svelte-fa';
|
||||
|
||||
let version = import.meta.env.UPSNAP_VERSION;
|
||||
|
||||
let files;
|
||||
let iconFiles = [];
|
||||
let iconPreview;
|
||||
let restoreFiles = [];
|
||||
let timeout;
|
||||
let buttons = {
|
||||
settings: {
|
||||
@@ -43,13 +45,38 @@
|
||||
};
|
||||
let scannedDevices = {};
|
||||
|
||||
$: if (iconPreview && iconFiles.length > 0) {
|
||||
iconPreview.src = URL.createObjectURL(iconFiles[0]);
|
||||
} else if (iconPreview && $settings_public.favicon !== '') {
|
||||
iconPreview.src = `${$pocketbase.baseUrl}/api/files/settings_public/${$settings_public.id}/${$settings_public.favicon}`;
|
||||
} else if (iconPreview) {
|
||||
iconPreview.src = '/gopher.svg';
|
||||
}
|
||||
|
||||
async function saveSettings() {
|
||||
buttons.settings.state = 'waiting';
|
||||
try {
|
||||
if ($settings.interval === '') {
|
||||
$settings.interval = '@every 3s';
|
||||
// update settings private
|
||||
if ($settings_private.interval === '') {
|
||||
$settings_private.interval = '@every 3s';
|
||||
}
|
||||
await $pocketbase.collection('settings').update($settings.id, $settings);
|
||||
await $pocketbase
|
||||
.collection('settings_private')
|
||||
.update($settings_private.id, $settings_private);
|
||||
|
||||
// update settings public
|
||||
if (iconFiles.length > 0) {
|
||||
const formData = new FormData();
|
||||
formData.append('favicon', iconFiles[0]);
|
||||
await $pocketbase
|
||||
.collection('settings_public')
|
||||
.update($settings_public.id, formData);
|
||||
}
|
||||
await $pocketbase
|
||||
.collection('settings_public')
|
||||
.update($settings_public.id, $settings_public);
|
||||
|
||||
//set button
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => {
|
||||
buttons.settings.state = 'none';
|
||||
@@ -69,8 +96,8 @@
|
||||
async function scanDevices() {
|
||||
buttons.scan.state = 'waiting';
|
||||
await $pocketbase
|
||||
.collection('settings')
|
||||
.update($settings.id, $settings)
|
||||
.collection('settings_private')
|
||||
.update($settings_private.id, $settings_private)
|
||||
.catch((err) => {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(() => {
|
||||
@@ -137,7 +164,7 @@
|
||||
}
|
||||
|
||||
let reader = new FileReader();
|
||||
reader.readAsText(files[0]);
|
||||
reader.readAsText(restoreFiles[0]);
|
||||
reader.onload = async (e) => {
|
||||
// parse uploaded file
|
||||
let data = JSON.parse(e.target.result);
|
||||
@@ -195,9 +222,9 @@
|
||||
<UnauthorizedMsg />
|
||||
<section class="m-0 mt-4 p-4 shadow-sm">
|
||||
<form on:submit|preventDefault={saveSettings}>
|
||||
<h3 class="mb-3">Ping interval</h3>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3 class="mb-3">Ping interval</h3>
|
||||
<p>Sets the interval in which the devices are pinged.</p>
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text">Cron</span>
|
||||
@@ -207,10 +234,10 @@
|
||||
aria-label="Interval"
|
||||
aria-describedby="addon-wrapping"
|
||||
type="text"
|
||||
bind:value={$settings.interval}
|
||||
bind:value={$settings_private.interval}
|
||||
/>
|
||||
</div>
|
||||
<h3 class="my-3">Website title</h3>
|
||||
<h3 class="my-3">Title</h3>
|
||||
<p>Set the website title in the navbar.</p>
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text" id="website-title">Title</span>
|
||||
@@ -220,9 +247,38 @@
|
||||
placeholder="e.g. 'UpSnap'"
|
||||
aria-label="Website title"
|
||||
aria-describedby="website-title"
|
||||
bind:value={$settings.website_title}
|
||||
bind:value={$settings_public.website_title}
|
||||
/>
|
||||
</div>
|
||||
<h3 class="my-3">Icon</h3>
|
||||
<img
|
||||
src=""
|
||||
alt=""
|
||||
class="img-fluid icon-preview mb-3"
|
||||
bind:this={iconPreview}
|
||||
/>
|
||||
<div class="mb-3">
|
||||
<label for="iconInput" class="form-label"
|
||||
>Set a custom favicon (.ico, .png, .svg, .jpg/.jpeg).</label
|
||||
>
|
||||
<div class="input-group">
|
||||
<input
|
||||
class="form-control"
|
||||
type="file"
|
||||
id="iconInput"
|
||||
accept=".ico,.png,.svg,.gif,.jpg,.jpeg"
|
||||
bind:files={iconFiles}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-danger"
|
||||
on:click={() => {
|
||||
iconFiles = [];
|
||||
$settings_public.favicon = '';
|
||||
}}>Back to Gopher</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="callout callout-info m-0">
|
||||
@@ -281,7 +337,7 @@
|
||||
placeholder="e.g. '192.168.1.0/24'"
|
||||
aria-label="ip-range"
|
||||
aria-describedby="ip-range"
|
||||
bind:value={$settings.scan_range}
|
||||
bind:value={$settings_private.scan_range}
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
@@ -290,7 +346,8 @@
|
||||
class:btn-success={buttons.scan.state === 'success' ? true : false}
|
||||
class:btn-warning={buttons.scan.state === 'waiting' ? true : false}
|
||||
class:btn-danger={buttons.scan.state === 'failed' ? true : false}
|
||||
disabled={$settings.scan_range === '' || buttons.scan.state !== 'none'
|
||||
disabled={$settings_private.scan_range === '' ||
|
||||
buttons.scan.state !== 'none'
|
||||
? true
|
||||
: false}
|
||||
>
|
||||
@@ -375,7 +432,7 @@
|
||||
aria-describedby="Restore"
|
||||
type="file"
|
||||
accept=".json"
|
||||
bind:files
|
||||
bind:files={restoreFiles}
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
@@ -383,7 +440,7 @@
|
||||
class:btn-success={buttons.restore.state === 'success' ? true : false}
|
||||
class:btn-warning={buttons.restore.state === 'waiting' ? true : false}
|
||||
class:btn-danger={buttons.restore.state === 'failed' ? true : false}
|
||||
disabled={files ? false : true}
|
||||
disabled={restoreFiles ? false : true}
|
||||
on:click={() => restoreV2Backup()}
|
||||
>
|
||||
{#if buttons.restore.state === 'none'}
|
||||
@@ -408,3 +465,9 @@
|
||||
{/if}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.icon-preview {
|
||||
height: 130px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -10,8 +10,13 @@ pb.autoCancellation(false);
|
||||
|
||||
// export stores
|
||||
export const pocketbase = writable(pb);
|
||||
export const settings = writable({
|
||||
website_title: ''
|
||||
export const settings_private = writable({
|
||||
interal: '',
|
||||
scan_range: ''
|
||||
});
|
||||
export const settings_public = writable({
|
||||
website_title: '',
|
||||
favicon: ''
|
||||
});
|
||||
export const devices = writable({});
|
||||
export const authorizedStore = writable(false);
|
||||
|
||||
Reference in New Issue
Block a user