Files
peazyweb/frontend/src/components/pages/config.rs
2025-03-31 15:04:11 +03:00

82 lines
3.7 KiB
Rust

use gloo::net::http::Request;
use wasm_bindgen_futures::spawn_local;
use yew::prelude::*;
use crate::{api::APIEndpoints, components::refresh_button::RefreshButton};
use base64::{Engine as _, engine::general_purpose};
fn string_to_base64_data_url(data: &str, content_type: &str) -> String {
let mut buf = String::new();
general_purpose::STANDARD.encode_string(data, &mut buf);
format!("data:{};base64,{}", content_type, buf)
}
#[derive(Properties, PartialEq)]
pub struct ConfigProps {
pub dir: AttrValue,
pub file_name: AttrValue,
#[prop_or("".into())]
pub contents: AttrValue,
}
#[function_component(Config)]
pub fn config(props: &ConfigProps) -> Html {
let dir_name = props.dir.clone();
let file_name = props.file_name.clone();
let contents = use_state(|| props.contents.to_string());
let get_contents = {
let contents = contents.clone();
Callback::from(move |_| {
let url =
APIEndpoints::get_contents(dir_name.clone().as_str(), file_name.clone().as_str());
let contents = contents.clone();
spawn_local(async move {
match Request::get(&url).send().await {
Ok(response) if response.ok() => {
if let Ok(text) = response.text().await {
contents.set(text);
}
}
_ => contents.set("...Ошибка загрузки содержимого...".into()),
}
})
})
};
{
let get_contents_clone = get_contents.clone();
let is_contents_empty = props.contents.is_empty();
use_effect_with((), move |_| {
if is_contents_empty {
get_contents_clone.emit(());
}
});
}
html! {
<div class="w-full">
<RefreshButton onclick={get_contents.reform(|_| ())} />
<div class="mb-2 flex justify-between items-center">
<p class="text-sm font-medium text-gray-900">{"Конфигурация "}<b>{&props.file_name}</b>{" для "}<b>{&props.dir}</b>{":"}</p>
</div>
<div class="relative bg-gray-50 rounded-lg dark:bg-gray-700 p-4">
<div class="overflow-scroll max-h-full">
<pre><code id="code-block" class="text-sm text-gray-500 dark:text-gray-400 whitespace-pre">{&*contents}</code></pre>
</div>
<div class="absolute top-2 end-2 bg-gray-50 dark:bg-gray-700">
<a href={string_to_base64_data_url(&contents, "application/octet-stream")} download={&props.file_name}>
<button type="button" class="text-white bg-gradient-to-br from-purple-600 to-blue-500 hover:bg-gradient-to-bl focus:ring-4 focus:outline-none focus:ring-blue-300 dark:focus:ring-blue-800 font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 mb-2">
<svg class="w-6 h-6 text-gray-800 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 24 24">
<path fill-rule="evenodd" d="M13 11.15V4a1 1 0 1 0-2 0v7.15L8.78 8.374a1 1 0 1 0-1.56 1.25l4 5a1 1 0 0 0 1.56 0l4-5a1 1 0 1 0-1.56-1.25L13 11.15Z" clip-rule="evenodd"/>
<path fill-rule="evenodd" d="M9.657 15.874 7.358 13H5a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-2.358l-2.3 2.874a3 3 0 0 1-4.685 0ZM17 16a1 1 0 1 0 0 2h.01a1 1 0 1 0 0-2H17Z" clip-rule="evenodd"/>
</svg>{"Скачать"}
</button>
</a>
</div>
</div>
</div>
}
}