add generation

This commit is contained in:
Dmitry Belyaev 2025-03-24 21:30:37 +03:00
parent edd86af7ef
commit 4320b5dc13
Signed by: b4tman
GPG Key ID: 41A00BF15EA7E5F3
2 changed files with 128 additions and 38 deletions
backend/src
frontend/src

@ -1,9 +1,9 @@
use rocket::fs::NamedFile;
use rocket::http::Method;
use rocket::http::Status;
use rocket::response::{Responder, status};
use rocket::serde::{Deserialize, json::Json};
use rocket::{self, get, launch, post, routes};
use rocket::http::Method;
use rocket_cors::{AllowedOrigins, CorsOptions};
use std::env;
use std::path::Path;
@ -216,8 +216,10 @@ fn rocket() -> _ {
)
.allow_credentials(true);
rocket::build().mount(
rocket::build()
.mount(
"/api/v1",
routes![index, list_directories, list_directory, get_file, generate],
).attach(cors.to_cors().unwrap())
)
.attach(cors.to_cors().unwrap())
}

@ -106,12 +106,10 @@ fn directories() -> Html {
// Добавляем use_effect с пустым вектором зависимостей
{
let get_dirs = get_dirs.clone();
use_effect_with((),
move |_| {
use_effect_with((), move |_| {
get_dirs.emit(());
()
},
);
});
}
html! {
@ -185,8 +183,9 @@ fn configs(props: &ConfigsProps) -> Html {
<p><button
onclick={get_configs.reform(|_| ())}
class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mb-4">
{ "Refresh" }
</button></p>
{ "Refresh" } </button>
<Link<Route> to={Route::Generate { dir_name: props.dir.clone().to_string() }}> <button class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mb-4">
{ "Generate" } </button> </Link<Route>> </p>
<h1>{ "Configs" }</h1>
<h2 class="text-2xl font-bold text-gray-700 mb-2">{format!("Configs for {}:", props.dir.clone())}</h2>
<ul class="list-disc pl-5">
@ -275,6 +274,89 @@ fn config(props: &ConfigProps) -> Html {
}
}
#[derive(Properties, PartialEq)]
pub struct GenerateProps {
pub dir: AttrValue,
}
#[function_component(Generate)]
fn generate(props: &GenerateProps) -> Html {
let dir_name = props.dir.clone();
let config_name = use_state(|| "".to_string());
let result = use_state(|| "".to_string());
let done = use_state(|| false);
let generate_config = {
let dir_name = dir_name.clone();
let config_name = config_name.clone();
let done = done.clone();
let result = result.clone();
Callback::from(move |_| {
let request_body = GenerationRequest {
directory: dir_name.clone().to_string(),
common_name: config_name.clone().to_string(),
};
let json_payload = serde_json::to_string(&request_body).unwrap();
let url = "http://127.0.0.1:8000/api/v1/generate/";
let result = result.clone();
let done = done.clone();
spawn_local(async move {
match Request::post(url)
.header("Content-Type", "application/json")
.body(json_payload)
.unwrap()
.send()
.await
{
Ok(response) if response.ok() => {
if let Ok(text) = response.text().await {
result.set(text);
done.set(true);
}
}
_ => {
gloo::console::log!("Failed to fetch response");
}
}
})
})
};
html! {
<div>
if !*done.clone() {
<div class="w-full">
<p><button
onclick={generate_config.reform(|_| ())}
class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mb-4">
{ "Generate" }
</button></p>
<div class="mb-2 flex justify-between items-center">
<p class="text-sm font-medium text-gray-900 dark:text-white">{"Enter the name of the config you want to generate:"}</p>
<form>
<label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white" for="common-name">{"Common Name:"}</label>
<input type="text" id="common-name" oninput={Callback::from({
let config_name = config_name.clone();
move |e: InputEvent| {
let input = e.target_dyn_into::<web_sys::HtmlInputElement>().unwrap();
config_name.set(input.value());
}
})} class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500" />
</form>
</div>
</div>
} else {
<div>
<Link<Route> to={Route::Config{dir_name: dir_name.clone().to_string(), file_name: format!("{}.ovpn", config_name.clone().to_string())}}><button class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mb-4">{ "Go to " } { config_name.clone().to_string() } </button></Link<Route>>
<p>{"Generated config for "}<b>{dir_name.clone()}</b>{" with name "}<b>{config_name.clone().to_string()}</b>{":"}</p>
<pre><code>{result.clone().to_string()}</code></pre>
</div>
}
</div>
}
}
fn switch(routes: Route) -> Html {
match routes.clone() {
Route::Home => html! {
@ -294,6 +376,12 @@ fn switch(routes: Route) -> Html {
<Configs dir={dir_name.clone()} />
</div>
},
Route::Generate { dir_name } => html! {
<div>
<Navbar currrent_route={routes.clone()} currrent_dir={dir_name.clone()} />
<Generate dir={dir_name.clone()} />
</div>
},
Route::Config {
dir_name,
file_name,