Linting fixes and form style experiment

- Also updated pnpm on my end for a hopefully clean lockfile
This commit is contained in:
adro 2023-11-01 09:28:29 +01:00
parent 7d2ef675f7
commit 5aec650946
20 changed files with 151 additions and 150 deletions

View file

@ -1,6 +1,6 @@
// import WebSocketServer from 'ws';
import JsonRPC from 'simple-jsonrpc-js';
import axios from "axios";
import axios from 'axios';
import { useToast } from 'vue-toast-notification';
const $toast = useToast();
@ -15,24 +15,24 @@ export function setup(_UnauthorizedCallback: () => void) {
}
export async function apiCall(method: string, params: Record<string, any>): Promise<any>{
console.debug("Starting API Call...");
console.debug('Starting API Call...');
try {
const result = await jrpc.call(method, params);
console.debug("api call result", result);
console.debug('api call result', result);
return { Data: result, Error: null};
} catch (ex: any){
if (ex.code === 401) {
UnauthorizedCallback();
} else {
$toast.error(method+ ': ' + ex.message);
console.debug("api call epic fail", ex);
$toast.error(`${method }: ${ ex.message}`);
console.debug('api call epic fail', ex);
}
return { Data: null, Error: ex};
}
}
export async function authenticate(username: string, password: string): Promise<any> {
const pResponse = axios.post("/login", { username, password }, {timeout: 10100});
const pResponse = axios.post('/login', { username, password }, {timeout: 10100});
try {
const response = await pResponse;
// Dont log this as the user password is inside: console.debug(response);
@ -43,7 +43,7 @@ export async function authenticate(username: string, password: string): Promise<
}
export async function logout(): Promise<any> {
const pResponse = axios.post("/logout", null, {timeout: 10100});
const pResponse = axios.post('/logout', null, {timeout: 10100});
try {
const response = await pResponse;
return { data: response.data, error: null};
@ -53,18 +53,18 @@ export async function logout(): Promise<any> {
}
export async function checkAuthentication() {
const pResponse = axios.post("/session", null, {timeout: 10100});
const pResponse = axios.post('/session', null, {timeout: 10100});
try {
const response = await pResponse;
const last_hash = window.localStorage.getItem("commit_hash");
const last_hash = window.localStorage.getItem('commit_hash');
if (last_hash) {
if (last_hash !== response.data.commit_hash) {
console.log("Detected New Backend Version, Reloading...");
window.localStorage.removeItem("commit_hash");
console.log('Detected New Backend Version, Reloading...');
window.localStorage.removeItem('commit_hash');
window.location.reload();
}
} else window.localStorage.setItem("commit_hash", response.data.commit_hash);
} else window.localStorage.setItem('commit_hash', response.data.commit_hash);
return {auth: 2, error: null};
} catch (error: any) {
if (error.response.status == 401) {

View file

@ -26,9 +26,7 @@ const emit = defineEmits<{
(event: 'draggedRow', draggedRow: number, draggedOverRow: number): void,
}>();
if (selection == undefined) {
selection = [];
}
if (!selection) selection = [];
const displayData = $computed(() => (sortSelf && sortBy !== '')
? data?.sort((a, b) => {
@ -53,8 +51,9 @@ function toggleSorting(columnName: string) {
}
function rowSelection(index: number) {
if (!selection) selection = [];
if (shiftState) {
if (selection.length === 0) {
if (!selection?.length) {
selection = [index];
} else {
let last = selection[selection.length-1];
@ -84,11 +83,11 @@ function rowSelection(index: number) {
selection = [index];
}
}
emit("selectionChanged");
emit('selectionChanged');
}
function atPath(value: any, path: string): any {
for (const segment of path.split(".")) {
for (const segment of path.split('.')) {
value = value[segment];
}
return value;
@ -102,7 +101,7 @@ function dragDropRow() {
data.splice(draggedRow, 1);
data.splice(draggedOverRow, 0, row);
data = data;
emit("draggedRow", draggedRow, draggedOverRow);
emit('draggedRow', draggedRow, draggedOverRow);
}
// Reset drag data
@ -137,7 +136,7 @@ function dragDropRow() {
@dragenter="() => draggedOverRow = index"
@dragend="() => dragDropRow()"
:class="{
'selected': selection.includes(index),
'selected': (selection ?? []).includes(index),
'dragged-over-before': index === draggedOverRow && draggedOverRow < draggedRow,
'dragged-over-after': index === draggedOverRow && draggedOverRow > draggedRow,
}">

View file

@ -20,7 +20,7 @@ const emit = defineEmits<{
}>();
async function draggedRow(draggedRow: number, draggedOverRow: number) {
emit("draggedRow", draggedRow, draggedOverRow);
emit('draggedRow', draggedRow, draggedOverRow);
}
</script>
@ -31,6 +31,6 @@ async function draggedRow(draggedRow: number, draggedOverRow: number) {
<slot/>
</PageHeader>
<div v-if="loading" >Loading...</div>
<NiceTable v-else :columns="columns" v-model:selection="selection" @draggedRow="draggedRow" v-bind="tableProps" :data="data"/>
<NiceTable v-else :columns="columns" v-model:selection="selection" @dragged-row="draggedRow" v-bind="tableProps" :data="data"/>
</div>
</template>

View file

@ -29,11 +29,11 @@ const props = withDefaults(defineProps<{
placeholder?: string,
}>(), {
modelValue: null,
search: "",
search: '',
options: () => ({}),
multiple: false,
searchProvider: null,
placeholder: "Search...",
placeholder: 'Search...',
});
let { multiple, searchProvider, placeholder } = $(props);
@ -62,14 +62,14 @@ onMounted(() => {
await performSearch(unknownKeys);
knownKeys = Object.keys(options);
unknownKeys = (val as Index[]).filter(key => !knownKeys.includes(key.toString()));
for (let key of unknownKeys) console.warn(`Unknown key in DropdownInput:`, key/*, options*/);
for (let key of unknownKeys) console.warn('Unknown key in DropdownInput:', key/*, options*/);
return modelValue = (val as Index[]).filter(key => knownKeys.includes(key.toString()));
}
if (!knownKeys.includes(val.toString())) {
await performSearch([val]);
knownKeys = Object.keys(options);
if (!knownKeys.includes(val.toString()))
return console.warn(`Unknown key in DropdownInput:`, val/*, options*/);
return console.warn('Unknown key in DropdownInput:', val/*, options*/);
}
modelValue = val;
}, { deep: true, immediate: true });
@ -150,9 +150,9 @@ function toggle(key: any) {
function handleKeydown(e: KeyboardEvent) {
switch (e.key) {
case "Backspace":
case "Delete":
if (!modelValue || search !== "" || !multiple) break;
case 'Backspace':
case 'Delete':
if (!modelValue || search !== '' || !multiple) break;
if (navigated === 0) modelValue.pop();
else if (navigated > 0) navigated = 0;
else {
@ -161,21 +161,21 @@ function handleKeydown(e: KeyboardEvent) {
}
modelValue = modelValue;
break;
case "ArrowUp":
case 'ArrowUp':
navigated--;
if (-navigated > selCount) navigated = 0;
e.preventDefault(); // Prevent cursor from moving to the front/back
break;
case "ArrowDown":
case 'ArrowDown':
navigated++;
if (navigated > Object.entries(options).length) navigated = 0;
e.preventDefault(); // Prevent cursor from moving to the front/back
break;
case "Enter":
case 'Enter':
if (!expanded) expand();
else if (navigated > 0) toggle(Object.entries(options)[navigated-1][0]);
break;
case "Escape":
case 'Escape':
if (navigated !== 0) navigated = 0;
else expanded = false;
break;

View file

@ -81,4 +81,7 @@ watchEffect(() => {
}
.variant { padding: 0.25rem; gap: 0.25rem; }
.selected { background-color: var(--cl-bg-sl); }
.enum-fields {
padding-left: 0px;
}
</style>

View file

@ -1,7 +1,7 @@
<!-- Wrapper component that sets "multiple" on DropdownInput to true and declares its type to be an array of any -->
<script setup lang="ts">
import { equals, Index } from "../../util";
import { Options, MaybeSearchProvider } from "./DropdownInput.vue";
import { equals, Index } from '../../util';
import { Options, MaybeSearchProvider } from './DropdownInput.vue';
const props = withDefaults(defineProps<{
// Two-Way Bindings (v-model)
modelValue?: Index[],
@ -13,10 +13,10 @@ const props = withDefaults(defineProps<{
placeholder?: string,
}>(), {
modelValue: () => [],
search: "",
search: '',
options: () => ({}),
searchProvider: null,
placeholder: "Search...",
placeholder: 'Search...',
});
const emit = defineEmits<{

View file

@ -62,4 +62,9 @@ watch($$(modelValue), (val) => {
label::after {
content: ":";
}
label {
border-left: 1px solid var(--cl-fg);
border-bottom: 1px solid var(--cl-fg);
}
</style>

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
import { isNullish, Index, MaybeIndex } from '../../util';
import { Index, MaybeIndex } from '../../util';
const props = withDefaults(defineProps<{
options: Record<Index, {

View file

@ -1,7 +1,7 @@
<!-- Wrapper component that sets "multiple" on DropdownInput to false and declares its type to be an Index -->
<script setup lang="ts">
import { equals, MaybeIndex } from "../../util";
import { Options, MaybeSearchProvider } from "./DropdownInput.vue";
import { equals, MaybeIndex } from '../../util';
import { Options, MaybeSearchProvider } from './DropdownInput.vue';
const props = withDefaults(defineProps<{
// Two-Way Bindings (v-model)
modelValue?: MaybeIndex,
@ -13,10 +13,10 @@ const props = withDefaults(defineProps<{
placeholder?: string,
}>(), {
modelValue: null,
search: "",
search: '',
options: () => ({}),
searchProvider: null,
placeholder: "Search...",
placeholder: 'Search...',
});
const emit = defineEmits<{

View file

@ -1,11 +1,12 @@
<script setup lang="ts">
const { title, noSpacer } = $(withDefaults(defineProps<{
const props = withDefaults(defineProps<{
title?: string,
noSpacer?: boolean,
}>(), {
title: "",
title: '',
noSpacer: false,
}));
});
let { title, noSpacer } = $(props);
watchEffect(() => useTitle(`${title} - nfSense`));
</script>
<template>

View file

@ -5,11 +5,11 @@ import './global-styles/mlfe.css';
import './global-styles/transitions.css';
import 'vue-toast-notification/dist/theme-default.css';
import PillBar from "./components/inputs/PillBar.vue";
import TextBox from "./components/inputs/TextBox.vue";
import NumberBox from "./components/inputs/NumberBox.vue";
import MultilineTextBox from "./components/inputs/MultilineTextBox.vue";
import CheckBox from "./components/inputs/CheckBox.vue";
import PillBar from './components/inputs/PillBar.vue';
import TextBox from './components/inputs/TextBox.vue';
import NumberBox from './components/inputs/NumberBox.vue';
import MultilineTextBox from './components/inputs/MultilineTextBox.vue';
import CheckBox from './components/inputs/CheckBox.vue';
import SingleSelect from './components/inputs/SingleSelect.vue';
import MultiSelect from './components/inputs/MultiSelect.vue';

View file

@ -59,7 +59,7 @@ onMounted(async() => {
<template>
<div>
<TableView title="DNAT Rules" :columns="columns" :loading="loading" @draggedRow="draggedRow" v-model:selection="selection" v-model:data="rules" :table-props="{sort:true, sortSelf: true, draggable: true}">
<TableView title="DNAT Rules" :columns="columns" :loading="loading" @dragged-row="draggedRow" v-model:selection="selection" v-model:data="rules" :table-props="{sort:true, sortSelf: true, draggable: true}">
<button @click="load">Refresh</button>
<router-link class="button" to="/firewall/destinationnatrules/edit">Create</router-link>
<router-link class="button" :class="{ disabled: selection.length != 1 }" :to="'/firewall/destinationnatrules/edit/' + selection[0]">Edit</router-link>

View file

@ -58,7 +58,7 @@ onMounted(async() => {
<template>
<div>
<TableView title="Forward Rules" :columns="columns" :loading="loading" @draggedRow="draggedRow" v-model:selection="selection" v-model:data="rules" :table-props="{sort:true, sortSelf: true, draggable: true}">
<TableView title="Forward Rules" :columns="columns" :loading="loading" @dragged-row="draggedRow" v-model:selection="selection" v-model:data="rules" :table-props="{sort:true, sortSelf: true, draggable: true}">
<button @click="load">Refresh</button>
<router-link class="button" to="/firewall/forwardrules/edit">Create</router-link>
<router-link class="button" :class="{ disabled: selection.length != 1 }" :to="'/firewall/forwardrules/edit/' + selection[0]">Edit</router-link>

View file

@ -59,7 +59,7 @@ onMounted(async() => {
<template>
<div>
<TableView title="SNAT Rules" :columns="columns" :loading="loading" @draggedRow="draggedRow" v-model:selection="selection" v-model:data="rules" :table-props="{sort:true, sortSelf: true, draggable: true}">
<TableView title="SNAT Rules" :columns="columns" :loading="loading" @dragged-row="draggedRow" v-model:selection="selection" v-model:data="rules" :table-props="{sort:true, sortSelf: true, draggable: true}">
<button @click="load">Refresh</button>
<router-link class="button" to="/firewall/sourcenatrules/edit">Create</router-link>
<router-link class="button" :class="{ disabled: selection.length != 1 }" :to="'/firewall/sourcenatrules/edit/' + selection[0]">Edit</router-link>

View file

@ -1,7 +1,13 @@
<script setup lang="ts">
import { apiCall } from '../api';
let links = $ref([]);
type Link = {
name: string,
carrier_state: string,
operational_state: string,
}
let links: Link[] = $ref([]);
let loading = $ref(false);
async function load(){
@ -26,9 +32,11 @@ onMounted(async() => {
<div style="overflow-y: auto;">
<PageHeader title="Dashboard">
</PageHeader>
<div v-if="!loading" v-for="(link, index) in links" :key="index">
<p>{{ link.name }} {{ link.carrier_state }} {{ link.operational_state }}</p>
</div>
<template v-if="!loading">
<div v-for="(link, index) in links" :key="index">
<p>{{ link.name }} {{ link.carrier_state }} {{ link.operational_state }}</p>
</div>
</template>
<div v-else>
Loading...
</div>

View file

@ -26,9 +26,11 @@ onMounted(async () => {
<div style="overflow-y: auto;">
<PageHeader title="Wireguard Status">
</PageHeader>
<div v-if="!loading" v-for="(line, index) in status.split('\n')" :key="index">
<p>{{ line }}</p>
</div>
<template v-if="!loading">
<div v-for="(line, index) in status.split('\n')" :key="index">
<p>{{ line }}</p>
</div>
</template>
<div v-else>
Loading...
</div>

View file

@ -12,7 +12,7 @@ export function equals(a: any, b: any): boolean {
}
export function isNullish(value: any) {
return !!(value === null || value === undefined);
return (value === null || value === undefined);
}
export type Index = string | number | symbol;