@@ -96,14 +96,14 @@ fn navbar(props: &NavProps) -> Html {
< span class = " self-center text-2xl font-semibold whitespace-nowrap dark:text-white " > { " PeazyWeb " } < / span >
< span class = " self-center text-2xl font-semibold whitespace-nowrap dark:text-white " > { " PeazyWeb " } < / span >
< / a >
< / a >
< button data - collapse - toggle = " navbar-default " type = " button " class = " inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600 " aria - controls = " navbar-default " aria - expanded = " false " >
< button data - collapse - toggle = " navbar-default " type = " button " class = " inline-flex items-center p-2 w-10 h-10 justify-center text-sm text-gray-500 rounded-lg md:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600 " aria - controls = " navbar-default " aria - expanded = " false " >
< span class = " sr-only " > { " Open main menu " } < / span >
< span class = " sr-only " > { " Меню " } < / span >
< svg class = " w-5 h-5 " aria - hidden = " true " xmlns = " http://www.w3.org/2000/svg " fill = " none " viewBox = " 0 0 17 14 " >
< svg class = " w-5 h-5 " aria - hidden = " true " xmlns = " http://www.w3.org/2000/svg " fill = " none " viewBox = " 0 0 17 14 " >
< path stroke = " currentColor " stroke - linecap = " round " stroke - linejoin = " round " stroke - width = " 2 " d = " M1 1h15M1 7h15M1 13h15 " / >
< path stroke = " currentColor " stroke - linecap = " round " stroke - linejoin = " round " stroke - width = " 2 " d = " M1 1h15M1 7h15M1 13h15 " / >
< / svg >
< / svg >
< / button >
< / button >
< div class = " hidden w-full md:block md:w-auto " id = " navbar-default " >
< div class = " hidden w-full md:block md:w-auto " id = " navbar-default " >
< ul class = " font-medium flex flex-col p-4 md:p-0 mt-4 border border-gray-100 rounded-lg bg-gray-50 md:flex-row md:space-x-8 rtl:space-x-reverse md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700 " >
< ul class = " font-medium flex flex-col p-4 md:p-0 mt-4 border border-gray-100 rounded-lg bg-gray-50 md:flex-row md:space-x-8 rtl:space-x-reverse md:mt-0 md:border-0 md:bg-white dark:bg-gray-800 md:dark:bg-gray-900 dark:border-gray-700 " >
< li class = { if is_current_home { classes_active } else { classes_inactive } } > < Link < Route > to = { Route ::Home } > { " Home " } < / Link < Route > > < / li >
< li class = { if is_current_home { classes_active } else { classes_inactive } } > < Link < Route > to = { Route ::Home } > { " Главная " } < / Link < Route > > < / li >
if has_dir {
if has_dir {
< li class = {
< li class = {
match props . currrent_route . clone ( ) {
match props . currrent_route . clone ( ) {
@@ -112,7 +112,7 @@ fn navbar(props: &NavProps) -> Html {
}
}
} > < Link < Route > to = { Route ::Configs { dir_name : props . currrent_dir . to_string ( ) } } > { props . currrent_dir . clone ( ) } < / Link < Route > > < / li >
} > < Link < Route > to = { Route ::Configs { dir_name : props . currrent_dir . to_string ( ) } } > { props . currrent_dir . clone ( ) } < / Link < Route > > < / li >
}
}
< li class = { if is_current_dir { classes_active } else { classes_inactive } } > < Link < Route > to = { Route ::Directories } > { " Directories " } < / Link < Route > > < / li >
< li class = { if is_current_dir { classes_active } else { classes_inactive } } > < Link < Route > to = { Route ::Directories } > { " Каталоги " } < / Link < Route > > < / li >
< / ul >
< / ul >
< / div >
< / div >
< / div >
< / div >
@@ -139,9 +139,9 @@ fn directories() -> Html {
json . sort ( ) ;
json . sort ( ) ;
dirs . set ( json ) ;
dirs . set ( json ) ;
}
}
_ = > error_message . set ( " Failed to fetch directories " . into ( ) ) ,
_ = > error_message . set ( " Ошибка чтения катологов " . into ( ) ) ,
} ,
} ,
_ = > error_message . set ( " Failed to fetch directories " . into ( ) ) ,
_ = > error_message . set ( " Ошибка получения каталогов " . into ( ) ) ,
}
}
} )
} )
} )
} )
@@ -158,12 +158,12 @@ fn directories() -> Html {
html! {
html! {
< div >
< div >
< RefreshButton onclick = { get_dirs . reform ( | _ | ( ) ) } / >
< RefreshButton onclick = { get_dirs . reform ( | _ | ( ) ) } / >
< h2 class = " text-2xl font-bold text-gray-700 mb-2 " > { " Directories " } < / h2 >
< h2 class = " text-2xl font-bold text-gray-700 mb-2 " > { " Каталоги конфигураций " } < / h2 >
< table class = " w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 " >
< table class = " w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 " >
< thead class = " text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400 " >
< thead class = " text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400 " >
< tr >
< tr >
< th scope = " col " class = " px-6 py-3 " >
< th scope = " col " class = " px-6 py-3 " >
{ " Directory name " }
{ " Каталог " }
< / th >
< / th >
< / tr >
< / tr >
< / thead >
< / thead >
@@ -209,9 +209,9 @@ fn configs(props: &ConfigsProps) -> Html {
json . sort ( ) ;
json . sort ( ) ;
configs . set ( json ) ;
configs . set ( json ) ;
}
}
_ = > error_message . set ( " Failed to fetch configs " . into ( ) ) ,
_ = > error_message . set ( " Ошибка чтения конфигураций " . into ( ) ) ,
} ,
} ,
_ = > error_message . set ( " Failed to fetch configs " . into ( ) ) ,
_ = > error_message . set ( " Ошибка получения конфигураций " . into ( ) ) ,
}
}
} )
} )
} )
} )
@@ -227,14 +227,14 @@ fn configs(props: &ConfigsProps) -> Html {
html! {
html! {
< div >
< div >
< p > < RefreshButton onclick = { get_configs . reform ( | _ | ( ) ) } / >
< p > < RefreshButton onclick = { get_configs . reform ( | _ | ( ) ) } / >
< Link < Route > to = { Route ::CreateConfig { dir_name : props . dir . clone ( ) . to_string ( ) } } > < button class = " text-white bg-gradient-to-br from-pink-500 to-orange-400 hover:bg-gradient-to-bl focus:ring-4 focus:outline-none focus:ring-pink-200 dark:focus:ring-pink-800 font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 mb-2 " >
< Link < Route > to = { Route ::CreateConfig { dir_name : props . dir . clone ( ) . to_string ( ) } } > < button class = " text-white bg-gradient-to-br from-pink-500 to-orange-400 hover:bg-gradient-to-bl focus:ring-4 focus:outline-none focus:ring-pink-200 dark:focus:ring-pink-800 font-bold rounded-lg text-sm px-5 py-2.5 text-center me-2 mb-2 " >
{ " Create " } < / button > < / Link < Route > > < / p >
{ " Создать " } < / button > < / Link < Route > > < / p >
< h2 class = " text-2xl font-bold text-gray-700 mb-2 " > { format! ( " Configs for {} : " , props . dir . clone ( ) ) } < / h2 >
< h2 class = " text-2xl font-bold text-gray-700 mb-2 " > { format! ( " Конфигурации для {} : " , props . dir . clone ( ) ) } < / h2 >
< table class = " w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 " >
< table class = " w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400 " >
< thead class = " text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400 " >
< thead class = " text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400 " >
< tr >
< tr >
< th scope = " col " class = " px-6 py-3 " >
< th scope = " col " class = " px-6 py-3 " >
{ " Name " }
{ " Имя " }
< / th >
< / th >
< / tr >
< / tr >
< / thead >
< / thead >
@@ -289,7 +289,7 @@ fn config(props: &ConfigProps) -> Html {
contents . set ( text ) ;
contents . set ( text ) ;
}
}
}
}
_ = > contents . set ( " Failed to fetch contents " . into ( ) ) ,
_ = > contents . set ( " ...Ошибка загрузки содержимого... " . into ( ) ) ,
}
}
} )
} )
} )
} )
@@ -309,7 +309,7 @@ fn config(props: &ConfigProps) -> Html {
< div class = " w-full " >
< div class = " w-full " >
< RefreshButton onclick = { get_contents . reform ( | _ | ( ) ) } / >
< RefreshButton onclick = { get_contents . reform ( | _ | ( ) ) } / >
< div class = " mb-2 flex justify-between items-center " >
< div class = " mb-2 flex justify-between items-center " >
< p class = " text-sm font-medium text-gray-900 " > { " Config " } < b > { & props . file_name } < / b > { " for " } < b > { & props . dir } < / b > { " : " } < / p >
< p class = " text-sm font-medium text-gray-900 " > { " Конфигурация " } < b > { & props . file_name } < / b > { " для " } < b > { & props . dir } < / b > { " : " } < / p >
< / div >
< / div >
< div class = " relative bg-gray-50 rounded-lg dark:bg-gray-700 p-4 " >
< div class = " relative bg-gray-50 rounded-lg dark:bg-gray-700 p-4 " >
< div class = " overflow-scroll max-h-full " >
< div class = " overflow-scroll max-h-full " >
@@ -320,7 +320,7 @@ fn config(props: &ConfigProps) -> Html {
< 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 " >
< 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 = " 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 " / >
< 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 >
< / svg > { " Скачать " } < / button > < / a >
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
@@ -371,7 +371,7 @@ fn create_config(props: &GenerateProps) -> Html {
}
}
}
}
_ = > {
_ = > {
error . set ( " Failed to create config " . into ( ) ) ;
error . set ( " Ошибка создания конфигурации " . into ( ) ) ;
}
}
}
}
} )
} )
@@ -385,11 +385,11 @@ fn create_config(props: &GenerateProps) -> Html {
< br / >
< br / >
< div class = " w-full max-w-sm p-4 bg-white border border-gray-200 rounded-lg shadow-sm sm:p-6 md:p-8 dark:bg-gray-800 dark:border-gray-700 " >
< div class = " w-full max-w-sm p-4 bg-white border border-gray-200 rounded-lg shadow-sm sm:p-6 md:p-8 dark:bg-gray-800 dark:border-gray-700 " >
< form class = " space-y-6 " action = " # " >
< form class = " space-y-6 " action = " # " >
< h5 class = " text-xl font-medium text-gray-900 dark:text-white " > { format! ( " Create a config for {} : " , props . dir . clone ( ) ) } < / h5 >
< h5 class = " text-xl font-medium text-gray-900 dark:text-white " > { format! ( " Создание конфигурации для {} : " , props . dir . clone ( ) ) } < / h5 >
< div >
< div >
< label class = " block mb-2 text-sm font-medium text-gray-900 dark:text-white " for = " common-name " > { " Common Name :" }
< label class = " block mb-2 text-sm font-medium text-gray-900 dark:text-white " for = " common-name " > { " Имя :" }
< / label >
< / label >
< input type = " text " id = " common-name " placeholder = " enter common name " class = " bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white " required = true oninput = { Callback ::from ( {
< input type = " text " id = " common-name " placeholder = " введите название " class = " bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white " required = true oninput = { Callback ::from ( {
let config_name = config_name . clone ( ) ;
let config_name = config_name . clone ( ) ;
move | e : InputEvent | {
move | e : InputEvent | {
let input = e . target_dyn_into ::< web_sys ::HtmlInputElement > ( ) . unwrap ( ) ;
let input = e . target_dyn_into ::< web_sys ::HtmlInputElement > ( ) . unwrap ( ) ;
@@ -399,7 +399,7 @@ fn create_config(props: &GenerateProps) -> Html {
< / div >
< / div >
< button type = " button " onclick = { generate_config_request . reform ( | _ | ( ) ) }
< button type = " button " onclick = { generate_config_request . reform ( | _ | ( ) ) }
class = " text-white bg-gradient-to-r from-red-400 via-red-500 to-red-600 hover:bg-gradient-to-br focus:ring-4 focus:outline-none focus:ring-red-300 dark:focus:ring-red-800 shadow-lg shadow-red-500/50 dark:shadow-lg dark:shadow-red-800/80 font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 mb-2 " >
class = " text-white bg-gradient-to-r from-red-400 via-red-500 to-red-600 hover:bg-gradient-to-br focus:ring-4 focus:outline-none focus:ring-red-300 dark:focus:ring-red-800 shadow-lg shadow-red-500/50 dark:shadow-lg dark:shadow-red-800/80 font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 mb-2 " >
{ " Create " }
{ " Создать " }
< / button >
< / button >
< / form >
< / form >
< / div >
< / div >
@@ -407,7 +407,7 @@ fn create_config(props: &GenerateProps) -> Html {
< ErrorAlert error = { error . as_str ( ) . to_owned ( ) } / >
< ErrorAlert error = { error . as_str ( ) . to_owned ( ) } / >
} else {
} else {
< div class = " p-4 mb-4 text-sm text-green-800 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400 " role = " alert " >
< div class = " p-4 mb-4 text-sm text-green-800 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400 " role = " alert " >
< span class = " font-medium " > { " Success !" } < / span > { " Config file successfully created ! " }
< span class = " font-medium " > { " Успешно !" } < / span > { " Конфигурация создана ! " }
< / div >
< / div >
< Config dir = { dir_name } file_name = { format! ( " {} .ovpn " , config_name . as_str ( ) ) } contents = { result . as_str ( ) . to_owned ( ) } / >
< Config dir = { dir_name } file_name = { format! ( " {} .ovpn " , config_name . as_str ( ) ) } contents = { result . as_str ( ) . to_owned ( ) } / >
}
}
@@ -424,7 +424,7 @@ fn switch(routes: Route) -> Html {
< section class = " bg-white dark:bg-gray-900 " >
< section class = " bg-white dark:bg-gray-900 " >
< div class = " py-8 px-4 mx-auto max-w-screen-xl text-center lg:py-16 " >
< div class = " py-8 px-4 mx-auto max-w-screen-xl text-center lg:py-16 " >
< h1 class = " mb-4 text-4xl font-extrabold tracking-tight leading-none text-gray-900 md:text-5xl lg:text-6xl dark:text-white " > { " PeazyWeb " } < / h1 >
< h1 class = " mb-4 text-4xl font-extrabold tracking-tight leading-none text-gray-900 md:text-5xl lg:text-6xl dark:text-white " > { " PeazyWeb " } < / h1 >
< p class = " mb-8 text-lg font-normal text-gray-500 lg:text-xl sm:px-16 lg:px-48 dark:text-gray-400 " > { " Your VPN configuration files at your fingertips !" } < / p >
< p class = " mb-8 text-lg font-normal text-gray-500 lg:text-xl sm:px-16 lg:px-48 dark:text-gray-400 " > { " Ваши файлы конфигурации OpenVPN у вас под рукой !" } < / p >
< / div >
< / div >
< / section >
< / section >
< / div > } ,
< / div > } ,
@@ -456,10 +456,14 @@ fn switch(routes: Route) -> Html {
< / div >
< / div >
} ,
} ,
_ = > html! {
_ = > html! {
< div >
< >
< Navbar / >
< Navbar / >
< h1 > { " todo " } < / h1 >
< div class = " grid-cols-3 place-items-center " >
< br / >
< h1 class = " font-extrabold text-9xl " > { " 404 " } < / h1 >
< span class = " text-2xl font-normal " > { " Н е найдено" } < / span >
< / div >
< / div >
< / >
} ,
} ,
}
}
}
}