diff --git a/frontend/scss/_size.scss b/frontend/scss/_size.scss index ce349500c..9645021fd 100644 --- a/frontend/scss/_size.scss +++ b/frontend/scss/_size.scss @@ -11,5 +11,8 @@ $config-max-grid-cells: 3; $config-field-min-width: 200px; $form-grid-cell-width: 300px; +$form-field-min-width: 200px; $form-max-grid-cells: 3; -$form-field-min-width: 200px; \ No newline at end of file +$form-grid-cell-width-small-screen: 200px; +$form-field-min-width-small-screen: 160px; +$form-max-grid-cells-small-screen: 2; \ No newline at end of file diff --git a/frontend/scss/app/components/_input.scss b/frontend/scss/app/components/_input.scss index 6ad9aa79c..4d4facc9f 100644 --- a/frontend/scss/app/components/_input.scss +++ b/frontend/scss/app/components/_input.scss @@ -27,6 +27,11 @@ width: 1.5rem; } } + + .tp__icon-button.active { + color: var(--tag-active-color); + fill: var(--tag-active-color); + } } label { padding-left: 2px; diff --git a/frontend/scss/app/components/_list_view.scss b/frontend/scss/app/components/_list_view.scss index 76e5552c3..f6c4520cc 100644 --- a/frontend/scss/app/components/_list_view.scss +++ b/frontend/scss/app/components/_list_view.scss @@ -41,7 +41,18 @@ flex-flow: column; box-sizing: border-box; width: 100%; - overflow: hidden; gap: var(--gap-default); } +} + +.tp__list-list { + &__body { + overflow: hidden; + } +} + +.tp__list-create { + &__body { + overflow: auto; + } } \ No newline at end of file diff --git a/frontend/scss/app/components/userlist/_proxy-user-credentials-form.scss b/frontend/scss/app/components/userlist/_proxy-user-credentials-form.scss index 00f8833eb..ebbecea6d 100644 --- a/frontend/scss/app/components/userlist/_proxy-user-credentials-form.scss +++ b/frontend/scss/app/components/userlist/_proxy-user-credentials-form.scss @@ -24,6 +24,11 @@ gap: var(--gap-large); box-sizing: border-box; width: 100%; + + @media (max-width: size.$mobile-breakpoint) { + grid-template-columns: repeat(auto-fit, minmax(size.$form-grid-cell-width-small-screen, 1fr)); + max-width: calc(size.$form-max-grid-cells-small-screen * size.$form-grid-cell-width-small-screen + 2 * 1rem); + } } &__toolbar { diff --git a/frontend/src/app/components/input.rs b/frontend/src/app/components/input.rs index b4db7d79c..558ba56dc 100644 --- a/frontend/src/app/components/input.rs +++ b/frontend/src/app/components/input.rs @@ -1,5 +1,5 @@ -use web_sys::{HtmlInputElement, InputEvent, KeyboardEvent}; -use yew::{function_component, html, use_effect_with, use_state, Callback, Html, NodeRef, Properties, TargetCast}; +use web_sys::{HtmlInputElement, InputEvent, KeyboardEvent, MouseEvent}; +use yew::{function_component, html, use_effect_with, use_node_ref, use_state, Callback, Html, NodeRef, Properties, TargetCast}; use crate::app::components::IconButton; use crate::html_if; @@ -25,6 +25,7 @@ pub struct InputProps { #[function_component] pub fn Input(props: &InputProps) -> Html { + let icon_btn_ref = use_node_ref(); let hide_content = use_state(|| props.hidden); let local_ref = props.input_ref.clone().unwrap_or_default(); @@ -38,11 +39,17 @@ pub fn Input(props: &InputProps) -> Html { }); } - let handle_hide_content = { let hide_content = hide_content.clone(); - Callback::from(move |_| { - hide_content.set(!*hide_content); + let button_ref = icon_btn_ref.clone(); + Callback::from(move |(_, event): (String, MouseEvent)| { + if let Some(target) = event.target_dyn_into::() { + if let Some(button) = button_ref.cast::() { + if button == target { + hide_content.set(!*hide_content); + } + } + } }) }; @@ -76,7 +83,7 @@ pub fn Input(props: &InputProps) -> Html { oninput={handle_oninput} /> { html_if!(props.hidden, { - + })} diff --git a/frontend/src/app/components/userlist/proxy_user_credentials_form.rs b/frontend/src/app/components/userlist/proxy_user_credentials_form.rs index 1349baddc..f3ca1cfa0 100644 --- a/frontend/src/app/components/userlist/proxy_user_credentials_form.rs +++ b/frontend/src/app/components/userlist/proxy_user_credentials_form.rs @@ -3,6 +3,7 @@ use chrono::{Duration, Utc}; use yew::prelude::*; use yew_i18n::use_translation; use shared::model::{ApiProxyServerInfoDto, ConfigTargetDto, ProxyType, ProxyUserCredentialsDto, ProxyUserStatus}; +use shared::utils::generate_random_string; use crate::app::TargetUser; use crate::{config_field_child, config_field_custom, edit_field_bool, edit_field_date, edit_field_number, edit_field_text, edit_field_text_option, generate_form_reducer}; use crate::app::components::select::Select; @@ -106,6 +107,7 @@ pub fn ProxyUserCredentialsForm(props: &ProxyUserCredentialsFormProps) -> Html { user.created_at = Some(now.timestamp()); let in_one_year = now + Duration::days(DEFAULT_EXPIRATION_DAYS); user.exp_date = Some(in_one_year.timestamp()); + user.token = Some(generate_random_string(6)); form_state.dispatch(UserFormAction::SetAll(user)); } diff --git a/frontend/src/services/auth_service.rs b/frontend/src/services/auth_service.rs index 025cf1a4d..3893bcdd0 100644 --- a/frontend/src/services/auth_service.rs +++ b/frontend/src/services/auth_service.rs @@ -1,5 +1,5 @@ use std::cell::RefCell; -use super::{get_base_href, request_post, ConfigService}; +use super::{get_base_href, request_post}; use crate::error::Error; use crate::services::requests::set_token; use futures_signals::signal::Mutable; @@ -121,3 +121,9 @@ impl AuthService { } } } + +impl Default for AuthService { + fn default() -> Self { + Self::new() + } +} diff --git a/shared/src/utils/string_utils.rs b/shared/src/utils/string_utils.rs index e21624318..0ab84be5d 100644 --- a/shared/src/utils/string_utils.rs +++ b/shared/src/utils/string_utils.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use chrono::Utc; pub trait Capitalize { fn capitalize(&self) -> String; @@ -29,15 +30,8 @@ pub fn get_trimmed_string(value: &Option) -> Option { } pub fn generate_random_string(length: usize) -> String { - let charset = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - let range = ..charset.len(); - let random_string: String = (0..length) - .map(|_| { - let idx = fastrand::usize(range); - charset[idx] as char - }) - .collect(); - + let mut rng = fastrand::Rng::with_seed(Utc::now().timestamp() as u64); + let random_string: String = (0..length).map(|_| rng.alphanumeric()).collect(); random_string }