diff --git a/src/routes.rs b/src/routes.rs index 778776f..df13a6c 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -9,6 +9,7 @@ use crate::util::hash::{decode, encode}; use crate::util::jobs::JobContainer; use actix_files::NamedFile; use actix_web::error::{ErrorBadRequest, ErrorInternalServerError, ErrorNotFound}; +use actix_web::http::{self}; use actix_web::{delete, error, get, post, put, web, Either, Error, HttpResponse}; use anyhow::Result; use futures_util::StreamExt; @@ -59,9 +60,20 @@ pub async fn get_raw( #[cfg(feature = "desktop")] { info!("Opening {:?}...", file_path); + let mut response = HttpResponse::NoContent(); let path = if !file_path.is_executable() { file_path } else { + response + .header( + http::header::WARNING, + "199 - Opening parent directory due to file being executable.", + ) + .header( + http::header::ACCESS_CONTROL_EXPOSE_HEADERS, + http::header::WARNING.to_string(), + ); + file_path .parent() .ok_or_else(|| { @@ -70,7 +82,7 @@ pub async fn get_raw( .to_path_buf() }; opener::open(path).map_err(error::ErrorServiceUnavailable)?; - return Ok(Either::B(HttpResponse::NoContent().finish())); + return Ok(Either::B(response.finish())); } #[cfg(not(feature = "desktop"))] @@ -83,7 +95,9 @@ pub async fn get_raw( Err(error::ErrorNotFound("NOT FOUND")) } } else { - Err(ErrorBadRequest("Address does not refer to a rawable object.")) + Err(ErrorBadRequest( + "Address does not refer to a rawable object.", + )) } } diff --git a/ui/src/App.svelte b/ui/src/App.svelte index 9fcfc5a..d8658dd 100644 --- a/ui/src/App.svelte +++ b/ui/src/App.svelte @@ -62,6 +62,7 @@ --background: #{$background}; --background-emph: #{color.scale($background, $lightness: -3%)}; --error: darkred; + --warning: orange; font-size: 15px; b { diff --git a/ui/src/components/display/UpObject.svelte b/ui/src/components/display/UpObject.svelte index e5f6cc0..556384b 100644 --- a/ui/src/components/display/UpObject.svelte +++ b/ui/src/components/display/UpObject.svelte @@ -46,6 +46,17 @@ if (!response.ok) { throw new Error(response.statusText); } + if (response.headers.has("warning")) { + const warningText = response.headers + .get("warning") + .split(" ") + .slice(2) + .join(" "); + notify.emit( + "notification", + new UpNotification(warningText, "warning") + ); + } }) .catch((err) => { notify.emit( diff --git a/ui/src/components/layout/Notifications.svelte b/ui/src/components/layout/Notifications.svelte index 88451b0..5bc844d 100644 --- a/ui/src/components/layout/Notifications.svelte +++ b/ui/src/components/layout/Notifications.svelte @@ -19,7 +19,8 @@ }); const icons = { - error: "exclamation-triangle", + error: "x-octagon", + warning: "exclamation-triangle" }; @@ -37,4 +38,8 @@ .notification-error { color: var(--error); } + + .notification-warning { + color: var(--warning); + } diff --git a/ui/src/notifications.ts b/ui/src/notifications.ts index 1137308..b7bb370 100644 --- a/ui/src/notifications.ts +++ b/ui/src/notifications.ts @@ -4,20 +4,20 @@ type NotifyEvents = { notification: UpNotification; }; -export type NotificationLevel = "info" | "error"; +export type UpNotificationLevel = "info" | "warning" | "error"; export interface INotification { id: string; content: string; - level: NotificationLevel; + level: UpNotificationLevel; } export class UpNotification implements INotification { id: string; content: string; - level: NotificationLevel; + level: UpNotificationLevel; - constructor(content: string, level?: NotificationLevel) { + constructor(content: string, level?: UpNotificationLevel) { this.id = String(Math.random()); this.content = content; this.level = level || "info";