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

@ -90,6 +90,7 @@
"vue/max-attributes-per-line": "off",
"vue/html-closing-bracket-newline": "off",
"vue/no-dupe-keys": "off",
"vue/no-template-shadow": "off",
"vue/singleline-html-element-content-newline": "off",
"indent": [
"error",

142
client/pnpm-lock.yaml generated
View file

@ -66,14 +66,14 @@ devDependencies:
'@typescript-eslint/parser': 6.9.1_i3vkbg2fztj7jno7sh3heeojya
'@vitejs/plugin-vue': 4.4.0_vite@4.5.0+vue@3.3.7
'@vue-macros/reactivity-transform': 0.3.23_vue@3.3.7
'@vue-macros/volar': 0.17.1_ft3qjyskndwnuyutiycxdowo3q
'@vue-macros/volar': 0.17.2_ft3qjyskndwnuyutiycxdowo3q
eslint: 8.52.0
eslint-plugin-vue: 9.18.1_eslint@8.52.0
typescript: 5.2.2
unplugin-auto-import: 0.16.7_@vueuse+core@10.5.0
unplugin-icons: 0.17.1
unplugin-vue-components: 0.25.2_vue@3.3.7
unplugin-vue-macros: 2.6.1_q64zeehrg4w2rr4xbfppgk6lgq
unplugin-vue-macros: 2.6.2_q64zeehrg4w2rr4xbfppgk6lgq
vite: 4.5.0
vite-plugin-pages: 0.31.0_vite@4.5.0
vue-tsc: 1.8.22_typescript@5.2.2
@ -645,42 +645,42 @@ packages:
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
dev: true
/@unhead/dom/1.8.1:
resolution: {integrity: sha512-cBGCXSeJVizG95dTudB069N0DMzWCHznbjYAJUv6sh0fwPUXUfKSHgf3h+Av3rkKeWEYguULN+bpnPOIfs7fJQ==}
/@unhead/dom/1.8.2:
resolution: {integrity: sha512-wyWf2bFItWvWHdfv8BlIyS7fcPYQBhJkwvkCjf3D7bnTXrd2ZyoUck07x3XApFiZavW8KD+A3S6jS39f/h4lBw==}
dependencies:
'@unhead/schema': 1.8.1
'@unhead/shared': 1.8.1
'@unhead/schema': 1.8.2
'@unhead/shared': 1.8.2
dev: false
/@unhead/schema/1.8.1:
resolution: {integrity: sha512-mR9i4BANtAug7gZEuyPkGYtVv2CF0wv8bqbPrt3OVSmpW0ts6bin1+ILM7HVKDpAOC7O1l4iyRrHOPocNPeVKQ==}
/@unhead/schema/1.8.2:
resolution: {integrity: sha512-bpCv8ualep2aqbhkBXUKfhYICi35+Pb1CBc5v6oJHHJgHKBIAbBQpbpi14amRMnRuSYDeSOCEM6SV8OJntcNDA==}
dependencies:
hookable: 5.5.3
zhead: 2.2.4
dev: false
/@unhead/shared/1.8.1:
resolution: {integrity: sha512-sFPx36i+InwneUJggwgobvta5KpE/Aj8SIOwHVMXZyj2w/TJshVpR+APFNKn3VMVlliZgl8UPLOROBDxAMXRDQ==}
/@unhead/shared/1.8.2:
resolution: {integrity: sha512-GDrUDN3x2anpNQQOgjmKjpi2ygNsBAwok9C6Z1YCeM2YtjF1lhqF9cTCXaapNEq81FkC0R0LTgnVxa/HJ4n3lQ==}
dependencies:
'@unhead/schema': 1.8.1
'@unhead/schema': 1.8.2
dev: false
/@unhead/ssr/1.8.1:
resolution: {integrity: sha512-SRP+eEQMw+eAGxyTpXDwWDEATY1N8YIpcZwYLJ8dqUaiEYUZTuigCvWv38MAJbT6Os9XSYioWuEwB95HAJwfKg==}
/@unhead/ssr/1.8.2:
resolution: {integrity: sha512-6x5O8z7QOWc3gD6+Zw7pgNSo4AmHqlYHp56JJ0eFSQPrvxFDdmC/ukebG3ATbFcwfCTyobm4IC25Kk4vMOYo0A==}
dependencies:
'@unhead/schema': 1.8.1
'@unhead/shared': 1.8.1
'@unhead/schema': 1.8.2
'@unhead/shared': 1.8.2
dev: false
/@unhead/vue/1.8.1_vue@3.3.7:
resolution: {integrity: sha512-qLxrbbr4+AJjlRsayPnIoaMN6p+qndmGNLLslrcfxq0w3qCUSfVbPA/02AD1vpEUlxXy4hHFnnhQzi0b7gEufg==}
/@unhead/vue/1.8.2_vue@3.3.7:
resolution: {integrity: sha512-EcXw7Q++GFcsaJhZ9s6SdRnyVGelOqfhY5/xOt7FfWnTkYGqBaOxWhTrIvNSThh58lkMnAxCr/azI/z6pBVNgw==}
peerDependencies:
vue: '>=2.7 || >=3'
dependencies:
'@unhead/schema': 1.8.1
'@unhead/shared': 1.8.1
'@unhead/schema': 1.8.2
'@unhead/shared': 1.8.2
hookable: 5.5.3
unhead: 1.8.1
unhead: 1.8.2
vue: 3.3.7_typescript@5.2.2
dev: false
@ -705,34 +705,34 @@ packages:
vue: 3.3.7_typescript@5.2.2
dev: true
/@volar/language-core/1.10.4:
resolution: {integrity: sha512-Na69qA6uwVIdA0rHuOc2W3pHtVQQO8hCNim7FOaKNpRJh0oAFnu5r9i7Oopo5C4cnELZkPNjTrbmpcCTiW+CMQ==}
/@volar/language-core/1.10.10:
resolution: {integrity: sha512-nsV1o3AZ5n5jaEAObrS3MWLBWaGwUj/vAsc15FVNIv+DbpizQRISg9wzygsHBr56ELRH8r4K75vkYNMtsSNNWw==}
dependencies:
'@volar/source-map': 1.10.4
'@volar/source-map': 1.10.10
dev: true
/@volar/language-core/1.10.9:
resolution: {integrity: sha512-QXHMX7CeXLqXwvC7nbr6iZ3zrqgKdJ9f6g1B211eZBnvaBki2ds0+Kz8cprUiulVuMQEPJNhDfuh8Vym1gxHRQ==}
/@volar/language-core/1.10.7:
resolution: {integrity: sha512-6+WI7HGqWCsKJ/bms4V45WP7eDeoGxDtLjYPrHB7QkIWVkRLIeGPzzBoonZz9kERM+Kld3W89Y+IlICejVAKhA==}
dependencies:
'@volar/source-map': 1.10.9
'@volar/source-map': 1.10.7
dev: true
/@volar/source-map/1.10.4:
resolution: {integrity: sha512-RxZdUEL+pV8p+SMqnhVjzy5zpb1QRZTlcwSk4bdcBO7yOu4rtEWqDGahVCEj4CcXour+0yJUMrMczfSCpP9Uxg==}
/@volar/source-map/1.10.10:
resolution: {integrity: sha512-GVKjLnifV4voJ9F0vhP56p4+F3WGf+gXlRtjFZsv6v3WxBTWU3ZVeaRaEHJmWrcv5LXmoYYpk/SC25BKemPRkg==}
dependencies:
muggle-string: 0.3.1
dev: true
/@volar/source-map/1.10.9:
resolution: {integrity: sha512-ul8yGO9nCxy6UedVuo0VsfKMLZzr39N1rgbtnYTGP5C554EDcUix6K/HDurhVdPHEDIw1yhXltLZZQKi3NrTvA==}
/@volar/source-map/1.10.7:
resolution: {integrity: sha512-anA254XO0lmmeu0p/kvgPOCkrVpqNIHWMvEkPX70PSk4ntg0iBzN/f0Kip6deXvibl6v14Q3Z8RihWrZwdZEEQ==}
dependencies:
muggle-string: 0.3.1
dev: true
/@volar/typescript/1.10.9:
resolution: {integrity: sha512-5jLB46mCQLJqLII/qDLgfyHSq1cesjwuJQIa2GNWd7LPLSpX5vzo3jfQLWc/gyo3up2fQFrlRJK2kgY5REtwuQ==}
/@volar/typescript/1.10.10:
resolution: {integrity: sha512-4a2r5bdUub2m+mYVnLu2wt59fuoYWe7nf0uXtGHU8QQ5LDNfzAR0wK7NgDiQ9rcl2WT3fxT2AA9AylAwFtj50A==}
dependencies:
'@volar/language-core': 1.10.9
'@volar/language-core': 1.10.10
path-browserify: 1.0.1
dev: true
@ -932,11 +932,11 @@ packages:
- rollup
dev: true
/@vue-macros/devtools/0.1.3_cnaluuumdmttzz4zpr3jp6tchm:
resolution: {integrity: sha512-aQRC9/TfmQajTMbZZ1BJn61rrraQztJqf64JdXRIpotbGR+xufLY/KIyTTB4SgL1pE1eW/ar5FaZTSjMqyVGIg==}
/@vue-macros/devtools/0.1.4_cnaluuumdmttzz4zpr3jp6tchm:
resolution: {integrity: sha512-md5WzjC4qgOOjnYKaqEfZknSeiEeGX13k/Hqi+aqvb+kIF0F6/5oxroqaPQemuNN/gUNMn8ZfA/JmcOYxGVFcQ==}
engines: {node: '>=16.14.0'}
peerDependencies:
vite: ^4.0.0
vite: ^4.0.0 || ^5.0.0-0
peerDependenciesMeta:
vite:
optional: true
@ -1107,8 +1107,8 @@ packages:
- vue
dev: true
/@vue-macros/volar/0.17.1_ft3qjyskndwnuyutiycxdowo3q:
resolution: {integrity: sha512-PBd3mieM2+zlhChUKto32DEEYz1diN6UhoAYaICxnVO6S4x1VkmxgTis52TuwtOFpgxgO/mXdlhdy0MgkUr+tg==}
/@vue-macros/volar/0.17.2_ft3qjyskndwnuyutiycxdowo3q:
resolution: {integrity: sha512-vvAdf4TEr7XpZJJ/yccfrQQ//lhWa7wsaO4/nGe3DdZEmdQ+opDYDS4MkD/K4kiZdA4/eiWcO/NVWY5bESdWhA==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue-tsc: ^1.6.0
@ -1117,12 +1117,12 @@ packages:
optional: true
dependencies:
'@rollup/pluginutils': 5.0.5
'@volar/language-core': 1.10.4
'@volar/language-core': 1.10.7
'@vue-macros/common': 1.8.0_vue@3.3.7
'@vue-macros/define-props': 1.0.21_yeap6wk4ldaear5sgzhiqg566e
'@vue-macros/short-bind': 0.1.0_vue@3.3.7
'@vue-macros/short-vmodel': 1.3.0_vue@3.3.7
'@vue/language-core': 1.8.20_typescript@5.2.2
'@vue/language-core': 1.8.22_typescript@5.2.2
vue-tsc: 1.8.22_typescript@5.2.2
transitivePeerDependencies:
- '@vue-macros/reactivity-transform'
@ -1169,25 +1169,6 @@ packages:
resolution: {integrity: sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==}
dev: false
/@vue/language-core/1.8.20_typescript@5.2.2:
resolution: {integrity: sha512-vNJaqjCTSrWEr+erSq6Rq0CqDC8MOAwyxirxwK8esOxd+1LmAUJUTG2p7I84Mj1Izy5uHiHQAkRTVR2QxMBY+A==}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@volar/language-core': 1.10.9
'@volar/source-map': 1.10.9
'@vue/compiler-dom': 3.3.7
'@vue/shared': 3.3.7
computeds: 0.0.1
minimatch: 9.0.3
muggle-string: 0.3.1
typescript: 5.2.2
vue-template-compiler: 2.7.15
dev: true
/@vue/language-core/1.8.22_typescript@5.2.2:
resolution: {integrity: sha512-bsMoJzCrXZqGsxawtUea1cLjUT9dZnDsy5TuZ+l1fxRMzUGQUG9+Ypq4w//CqpWmrx7nIAJpw2JVF/t258miRw==}
peerDependencies:
@ -1196,8 +1177,8 @@ packages:
typescript:
optional: true
dependencies:
'@volar/language-core': 1.10.9
'@volar/source-map': 1.10.9
'@volar/language-core': 1.10.10
'@volar/source-map': 1.10.10
'@vue/compiler-dom': 3.3.7
'@vue/shared': 3.3.7
computeds: 0.0.1
@ -1262,10 +1243,10 @@ packages:
peerDependencies:
vue: '>=2.7 || >=3'
dependencies:
'@unhead/dom': 1.8.1
'@unhead/schema': 1.8.1
'@unhead/ssr': 1.8.1
'@unhead/vue': 1.8.1_vue@3.3.7
'@unhead/dom': 1.8.2
'@unhead/schema': 1.8.2
'@unhead/ssr': 1.8.2
'@unhead/vue': 1.8.2_vue@3.3.7
vue: 3.3.7_typescript@5.2.2
dev: false
@ -2930,6 +2911,7 @@ packages:
/source-map/0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
requiresBuild: true
dev: false
optional: true
@ -3066,12 +3048,12 @@ packages:
/ufo/1.3.1:
resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==}
/unhead/1.8.1:
resolution: {integrity: sha512-hidjRl/irt/kvbJmyA+oED8xh+VnlQqfye3oxoZEuGr+JEKnU7keWNyiQxkSWpo9z5rwg52CKgCmY7oMuPMtmw==}
/unhead/1.8.2:
resolution: {integrity: sha512-f7Ha07cT+cgYav06tRNKxUrOZ722QtvYExn0McE68DYUGUM2boPCxXWlHcZXpSAbOj5OQI5AwQE5Xb3Qp2dWDQ==}
dependencies:
'@unhead/dom': 1.8.1
'@unhead/schema': 1.8.1
'@unhead/shared': 1.8.1
'@unhead/dom': 1.8.2
'@unhead/schema': 1.8.2
'@unhead/shared': 1.8.2
hookable: 5.5.3
dev: false
@ -3118,13 +3100,13 @@ packages:
- rollup
dev: true
/unplugin-combine/0.7.0_vite@4.5.0:
resolution: {integrity: sha512-Pxa8ovANAUN/bz/pzGN8xnTqFfSJndIJAttXS4/BdVq7mxtKB65RVa2UxAnLmEzgwvtefXAjZgyx9fk5Bv0vEA==}
engines: {node: '>=14.19.0'}
/unplugin-combine/0.8.0_vite@4.5.0:
resolution: {integrity: sha512-2a+Jf0gmX+N0aEjdPIGBSxtHcP+5izQus20+qmQFz43w2jh1ZhC2p3fKekBdDPj5ZQlO15bA+OLDkoOiiBz/BA==}
engines: {node: '>=16.14.0'}
peerDependencies:
esbuild: '>=0.13'
rollup: ^3.2.0
vite: ^2.3.0 || ^3.0.0 || ^4.0.0
rollup: ^3.2.0 || ^4.0.0
vite: ^2.3.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0
webpack: 4 || 5
peerDependenciesMeta:
esbuild:
@ -3213,8 +3195,8 @@ packages:
- vue
dev: true
/unplugin-vue-macros/2.6.1_q64zeehrg4w2rr4xbfppgk6lgq:
resolution: {integrity: sha512-YHqCZgZPasdRwmmuautjXkV6uOQ0amg/qHnXyUMgLI8/FkgtfGx+QgeknXpLgiOC2PVXlsuCqbcGnHJ/N4VtUg==}
/unplugin-vue-macros/2.6.2_q64zeehrg4w2rr4xbfppgk6lgq:
resolution: {integrity: sha512-U3hyp5RVHKUmnu+OQy1BKE3bVoTQmFkxed7o4G3Zh6jZDT/Q22bF97Qs7/N1/cDHSenNa06PWBXX173FPeqR1Q==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.2.25
@ -3230,7 +3212,7 @@ packages:
'@vue-macros/define-props-refs': 1.1.10_vue@3.3.7
'@vue-macros/define-render': 1.4.3_vue@3.3.7
'@vue-macros/define-slots': 1.0.15_vue@3.3.7
'@vue-macros/devtools': 0.1.3_cnaluuumdmttzz4zpr3jp6tchm
'@vue-macros/devtools': 0.1.4_cnaluuumdmttzz4zpr3jp6tchm
'@vue-macros/export-expose': 0.0.13_vue@3.3.7
'@vue-macros/export-props': 0.3.18_vue@3.3.7
'@vue-macros/export-render': 0.1.1_vue@3.3.7
@ -3245,7 +3227,7 @@ packages:
'@vue-macros/short-emits': 1.4.10_vue@3.3.7
'@vue-macros/short-vmodel': 1.3.0_vue@3.3.7
unplugin: 1.5.0
unplugin-combine: 0.7.0_vite@4.5.0
unplugin-combine: 0.8.0_vite@4.5.0
unplugin-vue-define-options: 1.3.18_vue@3.3.7
vue: 3.3.7_typescript@5.2.2
transitivePeerDependencies:
@ -3447,7 +3429,7 @@ packages:
peerDependencies:
typescript: '*'
dependencies:
'@volar/typescript': 1.10.9
'@volar/typescript': 1.10.10
'@vue/language-core': 1.8.22_typescript@5.2.2
semver: 7.5.4
typescript: 5.2.2

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;

View file

@ -16,13 +16,13 @@ import LinkAttributes from 'markdown-it-link-attributes';
// https://vitejs.dev/config/
export default defineConfig({
server: {
"proxy": {
"/api": "http://localhost:8080",
"/login": "http://localhost:8080",
"/logout": "http://localhost:8080",
"/session": "http://localhost:8080",
"/ws": {
target: "ws://localhost:8080",
'proxy': {
'/api': 'http://localhost:8080',
'/login': 'http://localhost:8080',
'/logout': 'http://localhost:8080',
'/session': 'http://localhost:8080',
'/ws': {
target: 'ws://localhost:8080',
ws: true,
},
},
@ -96,8 +96,8 @@ export default defineConfig({
'@vueuse/core',
'@vueuse/head',
{
from: "vue-toast-notification",
imports: ["useToast"],
from: 'vue-toast-notification',
imports: ['useToast'],
},
],
dts: 'src/generated/auto-imports.d.ts',