refactor(formlist): streamline ItemsList component and clean up unused code
- Removed unused imports, including `Element`, `Node`, and `ActiveCell` struct. - Consolidated signal management for `active_cell_position` and `active_row_index`. - Improved focus handling by adding a reusable `handle_focus` function. - Optimized EditableCell's event handlers for better maintainability.
This commit is contained in:
parent
b616fbb438
commit
b84cd37c44
2 changed files with 23 additions and 37 deletions
|
@ -1,9 +1,11 @@
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos::logging::log;
|
use leptos::logging::log;
|
||||||
|
use web_sys::FocusEvent;
|
||||||
#[component]
|
#[component]
|
||||||
pub fn EditableCell(
|
pub fn EditableCell(
|
||||||
value: String,
|
value: String,
|
||||||
on_input: impl Fn(String) + 'static,
|
on_input: impl Fn(String) + 'static,
|
||||||
|
#[prop(into)] on_focus: Callback<FocusEvent>,
|
||||||
#[prop(optional)] key: Option<String>, // Optional `key` prop
|
#[prop(optional)] key: Option<String>, // Optional `key` prop
|
||||||
) -> impl IntoView {
|
) -> impl IntoView {
|
||||||
let (input_value, set_input_value) = create_signal(value.clone());
|
let (input_value, set_input_value) = create_signal(value.clone());
|
||||||
|
@ -33,14 +35,15 @@ pub fn EditableCell(
|
||||||
on_input(new_value);
|
on_input(new_value);
|
||||||
};
|
};
|
||||||
|
|
||||||
let handle_focus = move |_: web_sys::FocusEvent| {
|
let handle_focus = move |ev:FocusEvent| {
|
||||||
if is_disposed.get() {
|
if is_disposed.get() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
set_has_focus.set(true);
|
set_has_focus.set(true);
|
||||||
|
on_focus.call(ev);
|
||||||
};
|
};
|
||||||
|
|
||||||
let handle_blur = move |_: web_sys::FocusEvent| {
|
let handle_blur = move |_:FocusEvent| {
|
||||||
if is_disposed.get() {
|
if is_disposed.get() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use leptos::logging::log;
|
||||||
use crate::models::item::Item;
|
use crate::models::item::Item;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use wasm_bindgen::JsCast;
|
use wasm_bindgen::JsCast;
|
||||||
use web_sys::{FocusEvent, HtmlElement, Element, Node};
|
use web_sys::{FocusEvent, HtmlElement};
|
||||||
use futures_timer::Delay;
|
use futures_timer::Delay;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
@ -17,11 +17,6 @@ struct WikidataSuggestion {
|
||||||
label: String,
|
label: String,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
}
|
}
|
||||||
#[derive(Clone)]
|
|
||||||
struct ActiveCell {
|
|
||||||
row_index: usize,
|
|
||||||
position: (f64, f64),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn ItemsList(
|
pub fn ItemsList(
|
||||||
|
@ -39,7 +34,6 @@ pub fn ItemsList(
|
||||||
wikidata_id: None,
|
wikidata_id: None,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
let (active_cell, set_active_cell) = create_signal(None::<ActiveCell>);
|
|
||||||
let (active_cell_position, set_active_cell_position) = create_signal(None::<(f64, f64)>);
|
let (active_cell_position, set_active_cell_position) = create_signal(None::<(f64, f64)>);
|
||||||
let (active_row_index, set_active_row_index) = create_signal(None::<usize>);
|
let (active_row_index, set_active_row_index) = create_signal(None::<usize>);
|
||||||
let (wikidata_suggestions, set_wikidata_suggestions) = create_signal(Vec::<WikidataSuggestion>::new());
|
let (wikidata_suggestions, set_wikidata_suggestions) = create_signal(Vec::<WikidataSuggestion>::new());
|
||||||
|
@ -82,16 +76,6 @@ pub fn ItemsList(
|
||||||
item.name = value.clone();
|
item.name = value.clone();
|
||||||
fetch_wikidata_suggestions(value.clone());
|
fetch_wikidata_suggestions(value.clone());
|
||||||
set_active_row_index.set(Some(index));
|
set_active_row_index.set(Some(index));
|
||||||
// Set active cell position with validation
|
|
||||||
if let Some(element) = document().get_element_by_id(&format!("name-{}", index)) {
|
|
||||||
let rect = element.get_bounding_client_rect();
|
|
||||||
log!("Bounding rect: {:?}", rect); // Log rect details
|
|
||||||
if rect.width() > 0.0 && rect.height() > 0.0 {
|
|
||||||
set_active_cell_position.set(Some((rect.left(), rect.bottom())));
|
|
||||||
} else {
|
|
||||||
log!("Element bounding box is not valid for popup positioning.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
"description" => {
|
"description" => {
|
||||||
item.description = value.clone();
|
item.description = value.clone();
|
||||||
|
@ -114,6 +98,21 @@ pub fn ItemsList(
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle focus event for EditableCell
|
||||||
|
let handle_focus = move |index: usize, field: &str, event: FocusEvent| {
|
||||||
|
set_active_row_index.set(Some(index));
|
||||||
|
if field == "name" {
|
||||||
|
if let Some(target) = event.target() {
|
||||||
|
if let Some(element) = target.dyn_ref::<HtmlElement>() {
|
||||||
|
let rect = element.get_bounding_client_rect();
|
||||||
|
set_active_cell_position.set(Some((rect.left(), rect.bottom())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
set_active_cell_position.set(None);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Add a new tag to an item
|
// Add a new tag to an item
|
||||||
let add_tag = move |index: usize, key: String, value: String| {
|
let add_tag = move |index: usize, key: String, value: String| {
|
||||||
set_items.update(|items| {
|
set_items.update(|items| {
|
||||||
|
@ -210,35 +209,19 @@ pub fn ItemsList(
|
||||||
<tr>
|
<tr>
|
||||||
// Editable Name Field with Wikidata Integration
|
// Editable Name Field with Wikidata Integration
|
||||||
<td>
|
<td>
|
||||||
<div
|
|
||||||
on:focus=move |event: FocusEvent| {
|
|
||||||
if let Some(element) = event.target().and_then(|t| t.dyn_into::<HtmlElement>().ok()) {
|
|
||||||
let rect = element.get_bounding_client_rect();
|
|
||||||
set_active_cell.set(Some(ActiveCell {
|
|
||||||
row_index: index,
|
|
||||||
position: (rect.left(), rect.top() + rect.height()),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
on:blur=move |_| {
|
|
||||||
spawn_local(async move {
|
|
||||||
Delay::new(Duration::from_millis(100)).await;
|
|
||||||
set_active_cell.set(None);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<EditableCell
|
<EditableCell
|
||||||
value=item.name.clone()
|
value=item.name.clone()
|
||||||
on_input=move |value| update_item(index, "name", value)
|
on_input=move |value| update_item(index, "name", value)
|
||||||
|
on_focus=move |event| handle_focus(index, "name", event)
|
||||||
key=format!("name-{}", index)
|
key=format!("name-{}", index)
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
// Editable Description Field
|
// Editable Description Field
|
||||||
<td>
|
<td>
|
||||||
<EditableCell
|
<EditableCell
|
||||||
value=item.description.clone()
|
value=item.description.clone()
|
||||||
on_input=move |value| update_item(index, "description", value)
|
on_input=move |value| update_item(index, "description", value)
|
||||||
|
on_focus=move |event| handle_focus(index, "description", event)
|
||||||
key=format!("description-{}", index)
|
key=format!("description-{}", index)
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
|
|
Loading…
Add table
Reference in a new issue