mirror of
https://codeberg.org/PLG-Development/PLG-MuDiCS
synced 2026-07-06 00:47:09 +00:00
add control requests, use pings and improve display_status
This commit is contained in:
@@ -1,17 +1,19 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { display_status_to_info, type DisplayStatus } from "../ts/types";
|
||||||
|
|
||||||
let { selected, status, className = "" } = $props<{
|
let { selected, status, className = "" } = $props<{
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
status: string;
|
status: DisplayStatus;
|
||||||
className?: string;
|
className?: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
function get_text_color(selected: boolean, status: string) {
|
function get_text_color(selected: boolean, status: DisplayStatus) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 'Online':
|
case 'app_online':
|
||||||
return selected ? 'text-green-700' : 'text-green-400';
|
return selected ? 'text-green-700' : 'text-green-400';
|
||||||
case 'Lädt':
|
case 'app_offline':
|
||||||
return selected ? 'text-amber-700' : 'text-amber-400';
|
return selected ? 'text-amber-700' : 'text-amber-400';
|
||||||
case 'Offline':
|
case 'host_offline':
|
||||||
return selected ? 'text-red-700' : 'text-red-400';
|
return selected ? 'text-red-700' : 'text-red-400';
|
||||||
default:
|
default:
|
||||||
return selected ? 'text-stone-700' : 'text-stone-400';
|
return selected ? 'text-stone-700' : 'text-stone-400';
|
||||||
@@ -20,5 +22,5 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="{get_text_color(selected, status)} {className} transition-colors duration-100">
|
<div class="{get_text_color(selected, status)} {className} transition-colors duration-100">
|
||||||
{status}
|
{display_status_to_info(status)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import DisplayView from '../components/DisplayView.svelte';
|
import DisplayView from '../components/DisplayView.svelte';
|
||||||
import SplashScreen from './../../../../shared/splash_screen.html?raw';
|
import SplashScreen from './../../../../shared/splash_screen.html?raw';
|
||||||
import PopUp from '../components/PopUp.svelte';
|
import PopUp from '../components/PopUp.svelte';
|
||||||
import type { PopupContent } from '../ts/types';
|
import { display_status_to_info, type PopupContent } from '../ts/types';
|
||||||
import TextInput from '../components/TextInput.svelte';
|
import TextInput from '../components/TextInput.svelte';
|
||||||
import {
|
import {
|
||||||
add_display,
|
add_display,
|
||||||
@@ -17,6 +17,8 @@
|
|||||||
remove_display
|
remove_display
|
||||||
} from '../ts/stores/displays';
|
} from '../ts/stores/displays';
|
||||||
import { text } from '@sveltejs/kit';
|
import { text } from '@sveltejs/kit';
|
||||||
|
import { notifications } from '../ts/stores/notification';
|
||||||
|
import { ping_ip } from '../ts/api_handler';
|
||||||
|
|
||||||
const ip_regex =
|
const ip_regex =
|
||||||
/^(?:(?:10|127)\.(?:25[0-5]|2[0-4]\d|1?\d?\d)\.(?:25[0-5]|2[0-4]\d|1?\d?\d)\.(?:25[0-5]|2[0-4]\d|1?\d?\d)|192\.168\.(?:25[0-5]|2[0-4]\d|1?\d?\d)\.(?:25[0-5]|2[0-4]\d|1?\d?\d)|172\.(?:1[6-9]|2\d|3[0-1])\.(?:25[0-5]|2[0-4]\d|1?\d?\d)\.(?:25[0-5]|2[0-4]\d|1?\d?\d))$/;
|
/^(?:(?:10|127)\.(?:25[0-5]|2[0-4]\d|1?\d?\d)\.(?:25[0-5]|2[0-4]\d|1?\d?\d)\.(?:25[0-5]|2[0-4]\d|1?\d?\d)|192\.168\.(?:25[0-5]|2[0-4]\d|1?\d?\d)\.(?:25[0-5]|2[0-4]\d|1?\d?\d)|172\.(?:1[6-9]|2\d|3[0-1])\.(?:25[0-5]|2[0-4]\d|1?\d?\d)\.(?:25[0-5]|2[0-4]\d|1?\d?\d))$/;
|
||||||
@@ -45,14 +47,15 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function finalize_add_edit_display(existing_display_id: string|null) {
|
async function finalize_add_edit_display(existing_display_id: string | null) {
|
||||||
const ip = text_inputs_valid.ip.value;
|
const ip = text_inputs_valid.ip.value;
|
||||||
const mac = text_inputs_valid.mac.value === '' ? null : text_inputs_valid.mac.value;
|
const mac = text_inputs_valid.mac.value === '' ? null : text_inputs_valid.mac.value;
|
||||||
const name = text_inputs_valid.name.value;
|
const name = text_inputs_valid.name.value;
|
||||||
if (!!existing_display_id) {
|
if (!!existing_display_id) {
|
||||||
edit_display_data(existing_display_id, ip, mac, name);
|
edit_display_data(existing_display_id, ip, mac, name);
|
||||||
} else {
|
} else {
|
||||||
add_display(ip, mac, name, 'Online');
|
const status = await ping_ip(text_inputs_valid.ip.value);
|
||||||
|
add_display(ip, mac, name, status);
|
||||||
}
|
}
|
||||||
popup_close_function();
|
popup_close_function();
|
||||||
}
|
}
|
||||||
@@ -153,8 +156,14 @@
|
|||||||
className="grow"
|
className="grow"
|
||||||
/>
|
/>
|
||||||
<div class="flex items-end shrink-0">
|
<div class="flex items-end shrink-0">
|
||||||
<Button disabled={!text_inputs_valid.ip.valid} className="px-4 gap-2" bg="bg-stone-750"
|
<Button
|
||||||
><Radio /> Ping</Button
|
disabled={!text_inputs_valid.ip.valid}
|
||||||
|
className="px-4 gap-2"
|
||||||
|
bg="bg-stone-750"
|
||||||
|
click_function={async () => {
|
||||||
|
const status = await ping_ip(text_inputs_valid.ip.value);
|
||||||
|
notifications.push('info', `Ping '${text_inputs_valid.ip.value}'`, `Aktueller Zustand: ${display_status_to_info(status)}`);
|
||||||
|
}}><Radio /> Ping</Button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import type { FolderElement } from "./types";
|
import { notifications } from "./stores/notification";
|
||||||
|
import { to_display_status, type DisplayStatus, type FolderElement } from "./types";
|
||||||
import { get_uuid } from "./utils";
|
import { get_uuid } from "./utils";
|
||||||
|
|
||||||
export async function get_screenshot(ip: string) {
|
export async function get_screenshot(ip: string) {
|
||||||
const options = { method: 'PATCH' };
|
const options = { method: 'PATCH' };
|
||||||
return await request(ip, '/takeScreenshot', options);
|
return await request_display(ip, '/takeScreenshot', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function open_file(ip: string, path_to_file: string) {
|
export async function open_file(ip: string, path_to_file: string): Promise<boolean> {
|
||||||
const options = { method: 'PATCH', headers: { 'content-type': 'application/octet-stream' } };
|
const options = { method: 'PATCH', headers: { 'content-type': 'application/octet-stream' } };
|
||||||
const raw_response = await request(ip, `/file${path_to_file}`, options);
|
const raw_response = await request_display(ip, `/file${path_to_file}`, options);
|
||||||
|
return !!raw_response;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get_file_data(ip: string, path: string): Promise<FolderElement[]> {
|
export async function get_file_data(ip: string, path: string): Promise<FolderElement[]> {
|
||||||
@@ -34,7 +36,8 @@ export async function get_file_data(ip: string, path: string): Promise<FolderEle
|
|||||||
done
|
done
|
||||||
` })
|
` })
|
||||||
};
|
};
|
||||||
const raw_response = await request(ip, '/shellCommand', options);
|
const raw_response = await request_display(ip, '/shellCommand', options);
|
||||||
|
if (!raw_response) return [];
|
||||||
const response: FileInfo[] = raw_response.stdout.trim()
|
const response: FileInfo[] = raw_response.stdout.trim()
|
||||||
.split("\n")
|
.split("\n")
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
@@ -62,12 +65,32 @@ done
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export async function ping_ip(ip: string): Promise<DisplayStatus> {
|
||||||
|
const raw_response = await request_control(`/ping?ip=${ip}`, { method: 'GET' });
|
||||||
|
console.log(raw_request);
|
||||||
|
if (!raw_response) return null;
|
||||||
|
return raw_response.status ? to_display_status(raw_response.status) : null;
|
||||||
|
}
|
||||||
|
|
||||||
async function request(ip: string, api_route: string, options: { method: string, headers?: Record<string, string>, body?: any }) {
|
|
||||||
|
|
||||||
|
|
||||||
|
async function request_display(ip: string, api_route: string, options: { method: string, headers?: Record<string, string>, body?: any }): Promise<null | any> {
|
||||||
|
const url = `http://${ip}:1323/api${api_route}`;
|
||||||
|
return await raw_request(url, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function request_control(api_route: string, options: { method: string, headers?: Record<string, string>, body?: any }): Promise<null | any> {
|
||||||
|
const url = `${window.location.origin}/api${api_route}`;
|
||||||
|
return await raw_request(url, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function raw_request(url: string, options: { method: string, headers?: Record<string, string>, body?: any }): Promise<null | any> {
|
||||||
try {
|
try {
|
||||||
const url = `http://${ip}:1323/api${api_route}?t=${Date.now()}`;
|
const cache_buster = `${url.includes('?') ? '&' : '?'}=${Date.now()}`;
|
||||||
console.log(url)
|
console.log(url + cache_buster)
|
||||||
const response = await fetch(url, options);
|
const response = await fetch(url + cache_buster, options);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
console.error(`HTTP error! Status: ${response.status}`);
|
console.error(`HTTP error! Status: ${response.status}`);
|
||||||
}
|
}
|
||||||
@@ -75,9 +98,14 @@ async function request(ip: string, api_route: string, options: { method: string,
|
|||||||
if (!contentType.includes("application/json")) {
|
if (!contentType.includes("application/json")) {
|
||||||
return await response.blob();
|
return await response.blob();
|
||||||
} else {
|
} else {
|
||||||
return await response.json();
|
const json = await response.json();
|
||||||
|
if (json.error && json.error !== '') {
|
||||||
|
notifications.push("error", `Fehler bei Anfrage '${url}'`, json.error);
|
||||||
|
}
|
||||||
|
return json;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { get, writable, type Writable } from "svelte/store";
|
import { get, writable, type Writable } from "svelte/store";
|
||||||
import type { Display, DisplayGroup } from "../types";
|
import type { Display, DisplayGroup, DisplayStatus } from "../types";
|
||||||
import { is_selected, select, selected_display_ids } from "./select";
|
import { is_selected, select, selected_display_ids } from "./select";
|
||||||
import { get_uuid, image_content_hash } from "../utils";
|
import { get_uuid, image_content_hash } from "../utils";
|
||||||
import { get_screenshot } from "../api_handler";
|
import { get_screenshot } from "../api_handler";
|
||||||
@@ -17,7 +17,7 @@ export function is_display_name_taken(name: string): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function add_display(ip: string, mac: string | null, name: string, status: string) {
|
export function add_display(ip: string, mac: string | null, name: string, status: DisplayStatus) {
|
||||||
displays.update((displays: DisplayGroup[]) => {
|
displays.update((displays: DisplayGroup[]) => {
|
||||||
displays[0].data.push({ id: get_uuid(), ip, preview_url: null, preview_timeout_id: null, mac, name, status });
|
displays[0].data.push({ id: get_uuid(), ip, preview_url: null, preview_timeout_id: null, mac, name, status });
|
||||||
return displays;
|
return displays;
|
||||||
@@ -164,6 +164,6 @@ function add_testing_displays() {
|
|||||||
// add_display("127.0.0.1", "00:1A:2B:3C:4D:5E", name, "Offline");
|
// add_display("127.0.0.1", "00:1A:2B:3C:4D:5E", name, "Offline");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
add_display("127.0.0.1", "00:1A:2B:3C:4D:5E", "PC", "Offline");
|
add_display("127.0.0.1", "00:1A:2B:3C:4D:5E", "PC", "host_offline");
|
||||||
// add_display("192.168.178.111", "D4:81:D7:C0:DF:3C", "Laptop", "Online");
|
// add_display("192.168.178.111", "D4:81:D7:C0:DF:3C", "Laptop", "Online");
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ export type Display = {
|
|||||||
preview_timeout_id: number | null;
|
preview_timeout_id: number | null;
|
||||||
mac: string | null;
|
mac: string | null;
|
||||||
name: string;
|
name: string;
|
||||||
status: string;
|
status: DisplayStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DisplayGroup = {
|
export type DisplayGroup = {
|
||||||
@@ -89,3 +89,24 @@ export type PopupContent = {
|
|||||||
title_icon?: typeof X | null;
|
title_icon?: typeof X | null;
|
||||||
closable?: boolean;
|
closable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DisplayStatus = "host_offline" | "app_offline" | "app_online" | null;
|
||||||
|
|
||||||
|
export function to_display_status(value: string): DisplayStatus {
|
||||||
|
return ["host_offline", "app_offline", "app_online"].includes(value)
|
||||||
|
? (value as DisplayStatus)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function display_status_to_info(status: DisplayStatus): string {
|
||||||
|
switch (status) {
|
||||||
|
case 'app_online':
|
||||||
|
return 'Online';
|
||||||
|
case 'app_offline':
|
||||||
|
return 'Lädt';
|
||||||
|
case 'host_offline':
|
||||||
|
return 'Offline';
|
||||||
|
case null:
|
||||||
|
return '???';
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user