mirror of
https://github.com/1f349/admin.1f349.com.git
synced 2024-11-09 22:32:57 +00:00
Make functional and test publishing
This commit is contained in:
parent
97a2cf089b
commit
944af0d8d9
@ -37,8 +37,10 @@
|
||||
on:click={() => {
|
||||
$loginStore = null;
|
||||
localStorage.removeItem("login-session");
|
||||
}}>Logout</button
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
</header>
|
||||
@ -52,7 +54,6 @@
|
||||
{/each}
|
||||
</div>
|
||||
<div id="option-view">
|
||||
<h2>{sidebarSelection.name}</h2>
|
||||
<svelte:component this={sidebarSelection.view} />
|
||||
</div>
|
||||
{/if}
|
||||
@ -120,7 +121,8 @@
|
||||
height: calc(100% - 70px);
|
||||
|
||||
#sidebar {
|
||||
width: 200px;
|
||||
width: 150px;
|
||||
min-width: 150px;
|
||||
|
||||
button {
|
||||
background-color: #2c2c2c;
|
||||
|
@ -61,6 +61,7 @@ body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
code {
|
||||
code,
|
||||
.code-font {
|
||||
font-family: 'Fira Code', monospace;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
export let value: number = 0;
|
||||
export let editable: boolean;
|
||||
export let editable: boolean = false;
|
||||
export let keys: Key[];
|
||||
let isEditing: boolean;
|
||||
|
||||
|
53
src/components/RedirectRow.svelte
Normal file
53
src/components/RedirectRow.svelte
Normal file
@ -0,0 +1,53 @@
|
||||
<script lang="ts">
|
||||
import {type CSPair, noCPair, noSPair} from "../types/cspair";
|
||||
import {type Route, redirectKeys, redirectEqual} from "../types/target";
|
||||
import Flags from "./Flags.svelte";
|
||||
|
||||
export let redirect: CSPair<Route>;
|
||||
|
||||
function resetRedirect(): any {
|
||||
redirect.client = JSON.parse(JSON.stringify(redirect.server));
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if noCPair(redirect)}
|
||||
<tr class="deleted">
|
||||
<td class="code-font">{redirect.server.src}</td>
|
||||
<td><input type="text" class="code-font" disabled bind:value={redirect.server.dst} size={redirect.server.dst.length + 2} /></td>
|
||||
<td><Flags value={redirect.server.flags} keys={redirectKeys} /></td>
|
||||
<td><input type="checkbox" disabled checked={false} /></td>
|
||||
<td><button on:click={() => resetRedirect()}>Restore</button></td>
|
||||
</tr>
|
||||
{:else}
|
||||
<tr class:created={noSPair(redirect)} class:modified={noSPair(redirect) || !redirectEqual(redirect.client, redirect.server)}>
|
||||
<td class="code-font">{redirect.client.src}</td>
|
||||
<td><input type="text" class="code-font" bind:value={redirect.client.dst} size={redirect.client.dst.length + 2} /></td>
|
||||
<td><Flags bind:value={redirect.client.flags} editable keys={redirectKeys} /></td>
|
||||
<td><input type="checkbox" bind:checked={redirect.client.active} /></td>
|
||||
<td>
|
||||
{#if !noSPair(redirect)}
|
||||
<button on:click={() => resetRedirect()}>Reset</button>
|
||||
{/if}
|
||||
<button on:click={() => (redirect.client = null)}>Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
tr.created {
|
||||
background-color: #1a5100;
|
||||
}
|
||||
|
||||
tr.modified {
|
||||
background-color: #515100;
|
||||
}
|
||||
|
||||
tr.deleted {
|
||||
background-color: #510000;
|
||||
}
|
||||
|
||||
td input[type="text"] {
|
||||
font-family: "Fira Code";
|
||||
padding: 4px;
|
||||
}
|
||||
</style>
|
52
src/components/RouteRow.svelte
Normal file
52
src/components/RouteRow.svelte
Normal file
@ -0,0 +1,52 @@
|
||||
<script lang="ts">
|
||||
import {type CSPair, noCPair, noSPair} from "../types/cspair";
|
||||
import {type Route, routeKeys, routeEqual} from "../types/target";
|
||||
import Flags from "./Flags.svelte";
|
||||
|
||||
export let route: CSPair<Route>;
|
||||
|
||||
function resetRoute(): any {
|
||||
route.client = JSON.parse(JSON.stringify(route.server));
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if noCPair(route)}
|
||||
<tr class="deleted">
|
||||
<td class="code-font">{route.server.src}</td>
|
||||
<td><input type="text" class="code-font" disabled bind:value={route.server.dst} size={route.server.dst.length + 2} /></td>
|
||||
<td><Flags value={route.server.flags} keys={routeKeys} /></td>
|
||||
<td><input type="checkbox" disabled checked={false} /></td>
|
||||
<td><button on:click={() => resetRoute()}>Restore</button></td>
|
||||
</tr>
|
||||
{:else}
|
||||
<tr class:created={noSPair(route)} class:modified={noSPair(route) || !routeEqual(route.client, route.server)}>
|
||||
<td class="code-font">{route.client.src}</td>
|
||||
<td><input type="text" class="code-font" bind:value={route.client.dst} size={route.client.dst.length + 2} /></td>
|
||||
<td><Flags bind:value={route.client.flags} editable keys={routeKeys} /></td>
|
||||
<td><input type="checkbox" bind:checked={route.client.active} /></td>
|
||||
<td>
|
||||
{#if !noSPair(route)}
|
||||
<button on:click={() => resetRoute()}>Reset</button>
|
||||
{/if}
|
||||
<button on:click={() => (route.client = null)}>Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
tr.created {
|
||||
background-color: #1a5100;
|
||||
}
|
||||
|
||||
tr.modified {
|
||||
background-color: #515100;
|
||||
}
|
||||
|
||||
tr.deleted {
|
||||
background-color: #510000;
|
||||
}
|
||||
|
||||
td input[type="text"] {
|
||||
padding: 4px;
|
||||
}
|
||||
</style>
|
11
src/types/cspair.ts
Normal file
11
src/types/cspair.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export type CSPair<T> = {client: T; server: T} | CSPairNotC<T> | CSPairNotS<T>;
|
||||
export type CSPairNotC<T> = {client: null; server: T};
|
||||
export type CSPairNotS<T> = {client: T; server: null};
|
||||
|
||||
export function noCPair<T>(pair: CSPair<T>): pair is CSPairNotC<T> {
|
||||
return pair.client == null;
|
||||
}
|
||||
|
||||
export function noSPair<T>(pair: CSPair<T>): pair is CSPairNotS<T> {
|
||||
return pair.server == null;
|
||||
}
|
39
src/types/target.ts
Normal file
39
src/types/target.ts
Normal file
@ -0,0 +1,39 @@
|
||||
export interface Route {
|
||||
src: string;
|
||||
dst: string;
|
||||
flags: number;
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
export interface Redirect {
|
||||
src: string;
|
||||
dst: string;
|
||||
flags: number;
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
export function routeEqual(a: Route, b: Route): boolean {
|
||||
if (b == null) return false;
|
||||
return a.src === b.src && a.dst === b.dst && a.flags === b.flags && a.active === b.active;
|
||||
}
|
||||
|
||||
export function redirectEqual(a: Redirect, b: Redirect): boolean {
|
||||
if (b == null) return false;
|
||||
return a.src === b.src && a.dst === b.dst && a.flags === b.flags && a.active === b.active;
|
||||
}
|
||||
|
||||
export const routeKeys = [
|
||||
{char: "p", name: "Prefix Path"},
|
||||
{char: "a", name: "Absolute Path"},
|
||||
{char: "c", name: "CORS"},
|
||||
{char: "s", name: "Secure Mode"},
|
||||
{char: "h", name: "Forward Host"},
|
||||
{char: "f", name: "Forward Address"},
|
||||
{char: "i", name: "Ignore Certificate"},
|
||||
{char: "w", name: "Websocket"},
|
||||
];
|
||||
|
||||
export const redirectKeys = [
|
||||
{char: "p", name: "Prefix Path"},
|
||||
{char: "a", name: "Absolute Path"},
|
||||
];
|
@ -1 +1 @@
|
||||
<div>No options available here</div>
|
||||
<div style="padding:8px;background-color:#bb7900;">Warning: This is currently still under development</div>
|
||||
|
@ -1 +1 @@
|
||||
<div>No options available here: {import.meta.env.VITE_API_ORCHID}</div>
|
||||
<div style="padding:8px;background-color:#bb7900;">Warning: This is currently still under development</div>
|
||||
|
@ -1,67 +1,30 @@
|
||||
<script lang="ts">
|
||||
import Flags from "../components/Flags.svelte";
|
||||
import RedirectRow from "../components/RedirectRow.svelte";
|
||||
import RouteRow from "../components/RouteRow.svelte";
|
||||
import {getBearer} from "../stores/login";
|
||||
import type {CSPair} from "../types/cspair";
|
||||
import {type Route, type Redirect, redirectEqual, redirectKeys} from "../types/target";
|
||||
|
||||
const apiViolet = import.meta.env.VITE_API_VIOLET;
|
||||
|
||||
const routeKeys = [
|
||||
{char: "p", name: "Prefix Path"},
|
||||
{char: "a", name: "Absolute Path"},
|
||||
{char: "c", name: "CORS"},
|
||||
{char: "s", name: "Secure Mode"},
|
||||
{char: "h", name: "Forward Host"},
|
||||
{char: "f", name: "Forward Address"},
|
||||
{char: "i", name: "Ignore Certificate"},
|
||||
{char: "w", name: "Websocket"},
|
||||
];
|
||||
let routeData: {[key: string]: CSPair<Route>} = {};
|
||||
let redirectData: {[key: string]: CSPair<Redirect>} = {};
|
||||
|
||||
const redirectKeys = [
|
||||
{char: "p", name: "Prefix Path"},
|
||||
{char: "a", name: "Absolute Path"},
|
||||
];
|
||||
let routeSrcs: string[] = [];
|
||||
let redirectSrcs: string[] = [];
|
||||
|
||||
interface Route {
|
||||
src: string;
|
||||
dst: string;
|
||||
flags: number;
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
interface Redirect {
|
||||
src: string;
|
||||
dst: string;
|
||||
flags: number;
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
type CSPair<T> = {client: T; server: T} | CSPairNotC<T> | CSPairNotS<T>;
|
||||
type CSPairNotC<T> = {client: null; server: T};
|
||||
type CSPairNotS<T> = {client: T; server: null};
|
||||
|
||||
let routeData: Map<string, CSPair<Route>> = new Map();
|
||||
let redirectData: Map<string, CSPair<Redirect>> = new Map();
|
||||
|
||||
let routeSrcs: Set<string> = new Set();
|
||||
let redirectSrcs: Set<string> = new Set();
|
||||
$: routeSrcs = Object.entries(routeData)
|
||||
.filter(x => x[1].client != null || x[1].server != null)
|
||||
.map(x => x[0])
|
||||
.sort((a, b) => a.localeCompare(b));
|
||||
$: redirectSrcs = Object.entries(redirectData)
|
||||
.filter(x => x[1].client != null || x[1].server != null)
|
||||
.map(x => x[0])
|
||||
.sort((a, b) => a.localeCompare(b));
|
||||
|
||||
$: console.log(routeData);
|
||||
|
||||
function routeEqual(a: Route, b: Route): boolean {
|
||||
return a.src === b.src && a.dst === b.dst && a.flags === b.flags && a.active === b.active;
|
||||
}
|
||||
|
||||
function redirectEqual(a: Route, b: Route): boolean {
|
||||
return a.src === b.src && a.dst === b.dst && a.flags === b.flags && a.active === b.active;
|
||||
}
|
||||
|
||||
function noCPair<T>(pair: CSPair<T>): pair is CSPairNotC<T> {
|
||||
return pair.client == null;
|
||||
}
|
||||
|
||||
function noSPair<T>(pair: CSPair<T>): pair is CSPairNotS<T> {
|
||||
return pair.server == null;
|
||||
}
|
||||
|
||||
let promiseForRoutes = new Promise<void>((res, rej) => {
|
||||
fetch(apiViolet + "/route", {headers: {Authorization: getBearer()}})
|
||||
.then(x => {
|
||||
@ -71,7 +34,7 @@
|
||||
.then(x => {
|
||||
let routes = x as Route[];
|
||||
routes.forEach(x => {
|
||||
routeData.set(x.src, {client: JSON.parse(JSON.stringify(x)), server: x});
|
||||
routeData[x.src] = {client: JSON.parse(JSON.stringify(x)), server: x};
|
||||
});
|
||||
res();
|
||||
})
|
||||
@ -86,7 +49,7 @@
|
||||
.then(x => {
|
||||
let redirects = x as Redirect[];
|
||||
redirects.forEach(x => {
|
||||
redirectData.set(x.src, {client: JSON.parse(JSON.stringify(x)), server: x});
|
||||
redirectData[x.src] = {client: JSON.parse(JSON.stringify(x)), server: x};
|
||||
});
|
||||
res();
|
||||
})
|
||||
@ -94,43 +57,33 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<div style="padding:8px;background-color:#bb7900;">
|
||||
Warning: This is currently still under development and does not update the routes and redirects on the server
|
||||
</div>
|
||||
|
||||
<h2>Routes</h2>
|
||||
{#await promiseForRoutes}
|
||||
<div>Loading...</div>
|
||||
{:then}
|
||||
<table>
|
||||
<tr>
|
||||
<th>Source</th>
|
||||
<th>Destination</th>
|
||||
<th>Flags</th>
|
||||
<th>Active</th>
|
||||
</tr>
|
||||
{#each routeSrcs as src (src)}
|
||||
{@const route = routeData.get(src)}
|
||||
{#if route}
|
||||
{#if noCPair(route)}
|
||||
<tr class="deleted">
|
||||
<td>{route.server.src}</td>
|
||||
<td>{route.server.dst}</td>
|
||||
<td><Flags bind:value={route.flags} editable keys={routeKeys} /></td>
|
||||
<td><input type="checkbox" bind:checked={route.active} /></td>
|
||||
</tr>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Source</th>
|
||||
<th>Destination</th>
|
||||
<th>Flags</th>
|
||||
<th>Active</th>
|
||||
<th>Option</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each routeSrcs as src (src)}
|
||||
{#if routeData[src]}
|
||||
<RouteRow bind:route={routeData[src]} />
|
||||
{:else}
|
||||
<tr><td colspan="5">Error loading row for {src}</td></tr>
|
||||
{/if}
|
||||
{@const isCreated = !route.server}
|
||||
{@const isDeleted = !route.client}
|
||||
<tr class:created={isCreated} class:modified={isCreated || !routeEqual(route.client, route.server)} class:deleted={isDeleted}>
|
||||
<td>{route.client.src}</td>
|
||||
<td>{route.client.dst}</td>
|
||||
<td><Flags bind:value={route.flags} editable keys={routeKeys} /></td>
|
||||
<td><input type="checkbox" bind:checked={route.active} /></td>
|
||||
<td>
|
||||
{#if !isCreated}
|
||||
<button on:click={() => resetRoute(i, serverRoute)}>Reset</button>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
{/each}
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{:catch err}
|
||||
<div>{err}</div>
|
||||
@ -141,27 +94,24 @@
|
||||
<div>Loading...</div>
|
||||
{:then}
|
||||
<table>
|
||||
<tr>
|
||||
<th>Source</th>
|
||||
<th>Destination</th>
|
||||
<th>Flags</th>
|
||||
<th>Active</th>
|
||||
</tr>
|
||||
{#each clientRedirects as redirect, i (redirect.src)}
|
||||
{@const serverRedirect = getServerRedirect(redirect.src)}
|
||||
{@const isNew = serverRedirect == undefined}
|
||||
<tr class:created={isNew} class:modified={isNew || !redirectEqual(redirect, serverRedirect)}>
|
||||
<td>{redirect.src}</td>
|
||||
<td>{redirect.dst}</td>
|
||||
<td><Flags bind:value={redirect.flags} editable keys={redirectKeys} /></td>
|
||||
<td><input type="checkbox" bind:checked={redirect.active} /></td>
|
||||
<td>
|
||||
{#if !isNew}
|
||||
<button on:click={() => resetRedirect(i, serverRedirect)}>Reset</button>
|
||||
{/if}
|
||||
</td>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Source</th>
|
||||
<th>Destination</th>
|
||||
<th>Flags</th>
|
||||
<th>Active</th>
|
||||
<th>Option</th>
|
||||
</tr>
|
||||
{/each}
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each redirectSrcs as src (src)}
|
||||
{#if redirectData[src]}
|
||||
<RedirectRow bind:redirect={redirectData[src]} />
|
||||
{:else}
|
||||
<tr><td colspan="5">Error loading row for {src}</td></tr>
|
||||
{/if}
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{:catch err}
|
||||
<div>{err}</div>
|
||||
@ -169,12 +119,22 @@
|
||||
|
||||
<style lang="scss">
|
||||
table {
|
||||
> tr.created {
|
||||
background-color: #1a5100;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
width: 100%;
|
||||
|
||||
thead {
|
||||
background-color: #04aa6d;
|
||||
}
|
||||
|
||||
> tr.modified {
|
||||
background-color: #515100;
|
||||
:global(th),
|
||||
:global(td) {
|
||||
padding: 11px 8px 11px 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
td:nth-child(2n) {
|
||||
background-color: #38444d;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user