parent
f76004a261
commit
2ebe43e886
@ -1,6 +0,0 @@
|
||||
/node_modules/
|
||||
/public/build/
|
||||
.vscode/
|
||||
.DS_Store
|
||||
package-lock.json
|
||||
yarn.lock
|
File diff suppressed because it is too large
Load Diff
@ -1,21 +1,63 @@
|
||||
<script lang="ts">
|
||||
import "bootstrap/dist/css/bootstrap.min.css";
|
||||
import Tailwind from "./Tailwind.svelte";
|
||||
import type { SvelteComponent } from "svelte";
|
||||
import { Router, Route } from "svelte-routing";
|
||||
|
||||
import {
|
||||
faChartLine,
|
||||
faClipboardList,
|
||||
faCloudUploadAlt,
|
||||
faTrafficLight,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import type { IconDefinition } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
import { Router, Link, Route } from "svelte-routing";
|
||||
import Home from "./routes/Home.svelte";
|
||||
import Navbar from "./components/Navbar.svelte";
|
||||
import Rules from "./routes/Rules.svelte";
|
||||
import RuleLists from "./routes/RuleLists.svelte";
|
||||
import Recursors from "./routes/Recursors.svelte";
|
||||
|
||||
export let url = "";
|
||||
|
||||
interface NavLink {
|
||||
label: string;
|
||||
to: string;
|
||||
icon: IconDefinition;
|
||||
Component: typeof SvelteComponent;
|
||||
}
|
||||
|
||||
const links: NavLink[] = [
|
||||
{ label: "Stats", to: "/", icon: faChartLine, Component: Home },
|
||||
{
|
||||
label: "Rules",
|
||||
to: "/rules",
|
||||
icon: faTrafficLight,
|
||||
Component: Rules,
|
||||
},
|
||||
{
|
||||
label: "Rule Lists",
|
||||
to: "/rulelists",
|
||||
icon: faClipboardList,
|
||||
Component: RuleLists,
|
||||
},
|
||||
{
|
||||
label: "Recursors",
|
||||
to: "/recursors",
|
||||
icon: faCloudUploadAlt,
|
||||
Component: Recursors,
|
||||
},
|
||||
];
|
||||
</script>
|
||||
|
||||
<Tailwind />
|
||||
<main class="flex w-full h-full">
|
||||
<Router {url}>
|
||||
<nav class="bg-gray-700 text-gray-300 w-1/8 py-5 px-2 shadow-md">
|
||||
<Link to="/">Home</Link>
|
||||
</nav>
|
||||
<Navbar {links} />
|
||||
<div class="flex-column py-5 px-5 w-full h-full overflow-y-auto">
|
||||
<Route path="/" component={Home} />
|
||||
{#each links as link}
|
||||
<Route path={link.to} component={link.Component} />
|
||||
{/each}
|
||||
</div>
|
||||
</Router>
|
||||
</main>
|
||||
|
@ -0,0 +1,9 @@
|
||||
import { apiCall } from './util'
|
||||
|
||||
export interface Recursor {
|
||||
ipAddress: string
|
||||
timeoutMs: number
|
||||
weight: number
|
||||
}
|
||||
|
||||
export const getRecursors = () => apiCall<Recursor>('recursors')
|
@ -0,0 +1,19 @@
|
||||
import { apiCall } from './util'
|
||||
|
||||
export interface RuleAnswer {
|
||||
type: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface Rule {
|
||||
id: number
|
||||
weight: number
|
||||
enabled: boolean
|
||||
created: string
|
||||
name: string
|
||||
value: string
|
||||
answer: RuleAnswer
|
||||
ttl: number
|
||||
}
|
||||
|
||||
export const getRules = () => apiCall<Rule>('rules');
|
@ -0,0 +1,29 @@
|
||||
interface APIResponse<T> {
|
||||
success?: boolean
|
||||
payload?: T[]
|
||||
error?: string
|
||||
|
||||
}
|
||||
|
||||
export const API_HOST = `http://localhost:8080/api/v1`;
|
||||
|
||||
export const apiCall = async function<T>(url: string, method: string = 'GET'): Promise<APIResponse<T>> {
|
||||
try {
|
||||
const data = await fetch(`${API_HOST}/${url}`, {
|
||||
headers: { "Accept": "application/json" },
|
||||
method,
|
||||
});
|
||||
|
||||
const { success, payload } = await data.json();
|
||||
|
||||
if (success) {
|
||||
return { payload };
|
||||
}
|
||||
|
||||
return { error: payload };
|
||||
|
||||
} catch (error) {
|
||||
console.trace(`API CALL FAILED - ${url}: ${error}`);
|
||||
return { error };
|
||||
}
|
||||
}
|
@ -1,17 +1,60 @@
|
||||
<script lang="ts">
|
||||
import { format, parse } from "date-fns";
|
||||
|
||||
import {
|
||||
Input,
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupText,
|
||||
} from "sveltestrap";
|
||||
export let label = "label";
|
||||
import { SearchDateFormatStr } from "../api/metrics";
|
||||
|
||||
interface IDateTimeParts {
|
||||
date: string;
|
||||
time: string;
|
||||
}
|
||||
|
||||
export let label: string = "label";
|
||||
export let defaultValue: Date = new Date();
|
||||
|
||||
const fromDateTimeParts = ({ date, time }: IDateTimeParts): Date =>
|
||||
parse(`${date} ${time}`, SearchDateFormatStr, new Date());
|
||||
|
||||
const toDateTimeParts = (dt: Date = new Date()): IDateTimeParts => ({
|
||||
date: format(dt, "yyyy-MM-dd"),
|
||||
time: format(dt, "HH:mm:ss"),
|
||||
});
|
||||
|
||||
const isDate = (v) => (v.match(/[\d]{4}-\d{2}-\d{2}/) || []).length > 0;
|
||||
|
||||
let dateTimeParts = toDateTimeParts(defaultValue);
|
||||
|
||||
const update = ({ target: { value } }) => {
|
||||
const { date, time } = dateTimeParts;
|
||||
let dateTimePartsInput = isDate(value)
|
||||
? { date: value, time }
|
||||
: { date, time: value };
|
||||
|
||||
const updatedDateTime = fromDateTimeParts(dateTimePartsInput);
|
||||
dateTimeParts = toDateTimeParts(updatedDateTime);
|
||||
console.log(dateTimeParts);
|
||||
};
|
||||
</script>
|
||||
|
||||
<InputGroup class="flex flex-row">
|
||||
<InputGroupAddon addonType="prepend">
|
||||
<InputGroupText>{label}</InputGroupText>
|
||||
</InputGroupAddon>
|
||||
<Input bsSize="sm" type="date" />
|
||||
<Input bsSize="sm" type="time" />
|
||||
<Input
|
||||
bsSize="sm"
|
||||
type="date"
|
||||
value={dateTimeParts.date}
|
||||
on:change={update}
|
||||
/>
|
||||
<Input
|
||||
bsSize="sm"
|
||||
type="time"
|
||||
value={dateTimeParts.time}
|
||||
on:change={update}
|
||||
/>
|
||||
</InputGroup>
|
||||
|
@ -0,0 +1,54 @@
|
||||
<script lang="ts">
|
||||
import Icon from "svelte-awesome";
|
||||
import { Link } from "svelte-routing";
|
||||
|
||||
import type { SvelteComponent } from "svelte";
|
||||
import type { IconDefinition } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
interface NavLink {
|
||||
label: string;
|
||||
to: string;
|
||||
icon: IconDefinition;
|
||||
Component: typeof SvelteComponent;
|
||||
}
|
||||
|
||||
export let links: NavLink[] = [];
|
||||
$: currentPath = location.pathname;
|
||||
</script>
|
||||
|
||||
<nav class="bg-gray-700 text-gray-300 w-1/8 py-5 px-2 shadow-md">
|
||||
<ul class="m-0 p-0 h-full">
|
||||
{#each links as l}
|
||||
<li class:selected={l.to === currentPath} class="link-item">
|
||||
<Link
|
||||
class="flex flex-col justify-center text-gray-300 hover:text-gray-500 no-underline"
|
||||
to={l.to}
|
||||
>
|
||||
<Icon
|
||||
class="w-full text-gray-300"
|
||||
data={l.icon}
|
||||
label={l.label}
|
||||
scale="1.75"
|
||||
/>
|
||||
<span class="text-sm">{l.label}</span>
|
||||
</Link>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<style lang="postcss">
|
||||
.link-item {
|
||||
@apply my-5 py-2 flex justify-center no-underline;
|
||||
}
|
||||
|
||||
.link-item span {
|
||||
margin-top: 5px;
|
||||
@apply no-underline;
|
||||
}
|
||||
|
||||
/* .selected span {
|
||||
text-decoration: underline !important;
|
||||
@apply text-white underline;
|
||||
} */
|
||||
</style>
|
@ -0,0 +1,32 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { Column, Row, Table } from "sveltestrap";
|
||||
import { getRules } from "../api/rules";
|
||||
import type { Rule } from "../api/rules";
|
||||
|
||||
let rows: Rule[] = [];
|
||||
onMount(async () => {
|
||||
try {
|
||||
const { payload } = await getRules();
|
||||
console.log(payload);
|
||||
rows = payload || [];
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="flex flex-column text-sm">
|
||||
{#if rows.length > 0}
|
||||
<Table {rows} let:row hover bordered>
|
||||
<Column header="Enabled">{row.enabled}</Column>
|
||||
<Column header="Weight">{row.weight}</Column>
|
||||
<Column header="Name">{row.name}</Column>
|
||||
<Column header="Expressions">{row.value}</Column>
|
||||
<Column header="Answer"
|
||||
>{row.answer.value} - {row.answer.type}</Column
|
||||
>
|
||||
<Column header="TTL">{row.ttl}</Column>
|
||||
</Table>
|
||||
{/if}
|
||||
</div>
|
@ -0,0 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { fade, fly } from "svelte/transition";
|
||||
export let header: string = "Home";
|
||||
export let description: string = "";
|
||||
</script>
|
||||
|
||||
<section out:fade={{ duration: 100 }} class="w-full">
|
||||
<header class="flex flex-column">
|
||||
<h1 in:fade={{ duration: 500 }}>
|
||||
{header}
|
||||
</h1>
|
||||
<span in:fly={{ y: 150, delay: 50, duration: 150 }}>{description}</span>
|
||||
</header>
|
||||
<section in:fade={{ delay: 150, duration: 550 }} class="py-5">
|
||||
<slot>
|
||||
<em>This page is (un?)intentionally left blank.</em>
|
||||
</slot>
|
||||
</section>
|
||||
</section>
|
@ -0,0 +1,34 @@
|
||||
<script lang="ts">
|
||||
import PageContainer from "./PageContainer.svelte";
|
||||
|
||||
import { onMount } from "svelte";
|
||||
import { Column, Row, Table } from "sveltestrap";
|
||||
import { getRecursors } from "../api/recursors";
|
||||
import type { Recursor } from "../api/recursors";
|
||||
|
||||
let rows: Recursor[] = [];
|
||||
onMount(async () => {
|
||||
try {
|
||||
const { payload } = await getRecursors();
|
||||
console.log(payload);
|
||||
rows = payload || [];
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<PageContainer
|
||||
header="Recursors"
|
||||
description="List of upstreams servers to use for resolving DNS records"
|
||||
>
|
||||
<section class="flex flex-column text-sm">
|
||||
{#if rows.length > 0}
|
||||
<Table {rows} let:row hover bordered>
|
||||
<Column header="IP Address">{row.ipAddress}</Column>
|
||||
<Column header="Weight">{row.weight}</Column>
|
||||
<Column header="Timeout in MS">{row.timeoutMs}</Column>
|
||||
</Table>
|
||||
{/if}
|
||||
</section>
|
||||
</PageContainer>
|
@ -0,0 +1,8 @@
|
||||
<script lang="ts">
|
||||
import PageContainer from "./PageContainer.svelte";
|
||||
</script>
|
||||
|
||||
<PageContainer
|
||||
header="Rule Lists"
|
||||
description="Import rule lists for maintenance free Ad blocking"
|
||||
/>
|
@ -0,0 +1,11 @@
|
||||
<script lang="ts">
|
||||
import RulesViewer from "../components/RulesViewer.svelte";
|
||||
import PageContainer from "./PageContainer.svelte";
|
||||
</script>
|
||||
|
||||
<PageContainer
|
||||
header="Rules"
|
||||
description="Specify rules to alter DNS resolution behavior"
|
||||
>
|
||||
<RulesViewer />
|
||||
</PageContainer>
|
Loading…
Reference in new issue