add generation
This commit is contained in:
parent
edd86af7ef
commit
4320b5dc13
@ -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;
|
||||
@ -206,18 +206,20 @@ async fn generate(request: Json<GenerationRequest<'_>>) -> Result<NamedFile, Gen
|
||||
|
||||
#[launch]
|
||||
fn rocket() -> _ {
|
||||
let cors = CorsOptions::default()
|
||||
.allowed_origins(AllowedOrigins::all())
|
||||
.allowed_methods(
|
||||
vec![Method::Get, Method::Post]
|
||||
.into_iter()
|
||||
.map(From::from)
|
||||
.collect(),
|
||||
)
|
||||
.allow_credentials(true);
|
||||
let cors = CorsOptions::default()
|
||||
.allowed_origins(AllowedOrigins::all())
|
||||
.allowed_methods(
|
||||
vec![Method::Get, Method::Post]
|
||||
.into_iter()
|
||||
.map(From::from)
|
||||
.collect(),
|
||||
)
|
||||
.allow_credentials(true);
|
||||
|
||||
rocket::build().mount(
|
||||
"/api/v1",
|
||||
routes![index, list_directories, list_directory, get_file, generate],
|
||||
).attach(cors.to_cors().unwrap())
|
||||
rocket::build()
|
||||
.mount(
|
||||
"/api/v1",
|
||||
routes![index, list_directories, list_directory, get_file, generate],
|
||||
)
|
||||
.attach(cors.to_cors().unwrap())
|
||||
}
|
||||
|
@ -106,14 +106,12 @@ fn directories() -> Html {
|
||||
// Добавляем use_effect с пустым вектором зависимостей
|
||||
{
|
||||
let get_dirs = get_dirs.clone();
|
||||
use_effect_with((),
|
||||
move |_| {
|
||||
get_dirs.emit(());
|
||||
()
|
||||
},
|
||||
);
|
||||
use_effect_with((), move |_| {
|
||||
get_dirs.emit(());
|
||||
()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
html! {
|
||||
<div>
|
||||
<p><button
|
||||
@ -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">
|
||||
@ -249,30 +248,113 @@ fn config(props: &ConfigProps) -> Html {
|
||||
}
|
||||
|
||||
html! {
|
||||
<div class="w-full">
|
||||
<p><button
|
||||
onclick={get_contents.reform(|_| ())}
|
||||
class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mb-4">
|
||||
{ "Refresh" }
|
||||
</button></p>
|
||||
<p>{"Config "}<b>{props.file_name.clone()}</b>{" for "}<b>{props.dir.clone()}</b>{":"}</p>
|
||||
<div class="mb-2 flex justify-between items-center">
|
||||
<p class="text-sm font-medium text-gray-900 dark:text-white">{"Config "}<b>{props.file_name.clone()}</b>{" for "}<b>{props.dir.clone()}</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={format!("http://127.0.0.1:8000/api/v1/get/{}/{}", props.dir.clone(), props.file_name.clone())} download={props.file_name.clone()}><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>{"Download"}</button></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[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={get_contents.reform(|_| ())}
|
||||
onclick={generate_config.reform(|_| ())}
|
||||
class="bg-gray-500 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded mb-4">
|
||||
{ "Refresh" }
|
||||
{ "Generate" }
|
||||
</button></p>
|
||||
<p>{"Config "}<b>{props.file_name.clone()}</b>{" for "}<b>{props.dir.clone()}</b>{":"}</p>
|
||||
<div class="mb-2 flex justify-between items-center">
|
||||
<p class="text-sm font-medium text-gray-900 dark:text-white">{"Config "}<b>{props.file_name.clone()}</b>{" for "}<b>{props.dir.clone()}</b>{":"}</p>
|
||||
<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 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={format!("http://127.0.0.1:8000/api/v1/get/{}/{}", props.dir.clone(), props.file_name.clone())} download={props.file_name.clone()}><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>{"Download"}</button></a>
|
||||
</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 {
|
||||
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user