Add reset buttons to color editor modal for individual and bulk color resets
All checks were successful
Build and Push Docker Image / docker (push) Successful in 31s
All checks were successful
Build and Push Docker Image / docker (push) Successful in 31s
- Add "Reset This Color" button in color preview section for individual resets - Add "Reset All Colors" button in modal footer for bulk palette reset - Implement reset callbacks with database persistence via preferences API - Reorganize color preview layout with flex column for better button placement - Style reset buttons with appropriate warning colors and hover states - Support both granular and comprehensive color customization workflows 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -365,6 +365,28 @@ pub fn App() -> Html {
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let on_color_editor_reset_all = {
|
||||||
|
let available_colors = available_colors.clone();
|
||||||
|
let refresh_colors = refresh_colors.clone();
|
||||||
|
Callback::from(move |_| {
|
||||||
|
// Reset to default colors
|
||||||
|
let default_colors = get_default_event_colors();
|
||||||
|
available_colors.set(default_colors.clone());
|
||||||
|
|
||||||
|
// Save to preferences asynchronously
|
||||||
|
let colors_for_save = default_colors.clone();
|
||||||
|
let refresh_colors = refresh_colors.clone();
|
||||||
|
wasm_bindgen_futures::spawn_local(async move {
|
||||||
|
if let Err(e) = save_custom_colors_to_preferences(colors_for_save).await {
|
||||||
|
web_sys::console::log_1(&format!("Failed to save default colors: {}", e).into());
|
||||||
|
} else {
|
||||||
|
// Refresh colors to ensure UI is in sync
|
||||||
|
refresh_colors.emit(());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
let on_view_change = {
|
let on_view_change = {
|
||||||
let current_view = current_view.clone();
|
let current_view = current_view.clone();
|
||||||
Callback::from(move |new_view: ViewMode| {
|
Callback::from(move |new_view: ViewMode| {
|
||||||
@@ -1801,8 +1823,14 @@ pub fn App() -> Html {
|
|||||||
is_open={*color_editor_open}
|
is_open={*color_editor_open}
|
||||||
current_color={color_editor_data.as_ref().map(|(_, color)| color.clone()).unwrap_or_default()}
|
current_color={color_editor_data.as_ref().map(|(_, color)| color.clone()).unwrap_or_default()}
|
||||||
color_index={color_editor_data.as_ref().map(|(index, _)| *index).unwrap_or(0)}
|
color_index={color_editor_data.as_ref().map(|(index, _)| *index).unwrap_or(0)}
|
||||||
|
default_color={
|
||||||
|
let default_colors = get_default_event_colors();
|
||||||
|
let index = color_editor_data.as_ref().map(|(index, _)| *index).unwrap_or(0);
|
||||||
|
default_colors.get(index).cloned().unwrap_or_else(|| "#3B82F6".to_string())
|
||||||
|
}
|
||||||
on_close={on_color_editor_close}
|
on_close={on_color_editor_close}
|
||||||
on_save={on_color_editor_save}
|
on_save={on_color_editor_save}
|
||||||
|
on_reset_all={on_color_editor_reset_all}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ pub struct ColorEditorModalProps {
|
|||||||
pub is_open: bool,
|
pub is_open: bool,
|
||||||
pub current_color: String,
|
pub current_color: String,
|
||||||
pub color_index: usize,
|
pub color_index: usize,
|
||||||
|
pub default_color: String, // Default color for this index
|
||||||
pub on_close: Callback<()>,
|
pub on_close: Callback<()>,
|
||||||
pub on_save: Callback<(usize, String)>, // (index, new_color)
|
pub on_save: Callback<(usize, String)>, // (index, new_color)
|
||||||
|
pub on_reset_all: Callback<()>, // Reset all colors to defaults
|
||||||
}
|
}
|
||||||
|
|
||||||
#[function_component(ColorEditorModal)]
|
#[function_component(ColorEditorModal)]
|
||||||
@@ -86,7 +88,18 @@ pub fn color_editor_modal(props: &ColorEditorModalProps) -> Html {
|
|||||||
class="color-preview-large"
|
class="color-preview-large"
|
||||||
style={format!("background-color: {}", *selected_color)}
|
style={format!("background-color: {}", *selected_color)}
|
||||||
></div>
|
></div>
|
||||||
<span class="color-value">{&*selected_color}</span>
|
<div class="color-preview-info">
|
||||||
|
<span class="color-value">{&*selected_color}</span>
|
||||||
|
<button class="reset-this-color-button" onclick={{
|
||||||
|
let selected_color = selected_color.clone();
|
||||||
|
let default_color = props.default_color.clone();
|
||||||
|
Callback::from(move |_| {
|
||||||
|
selected_color.set(default_color.clone());
|
||||||
|
})
|
||||||
|
}}>
|
||||||
|
{"Reset This Color"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="color-input-section">
|
<div class="color-input-section">
|
||||||
@@ -143,6 +156,16 @@ pub fn color_editor_modal(props: &ColorEditorModalProps) -> Html {
|
|||||||
})}>
|
})}>
|
||||||
{"Cancel"}
|
{"Cancel"}
|
||||||
</button>
|
</button>
|
||||||
|
<button class="reset-all-button" onclick={Callback::from({
|
||||||
|
let on_reset_all = props.on_reset_all.clone();
|
||||||
|
let on_close = props.on_close.clone();
|
||||||
|
move |_| {
|
||||||
|
on_reset_all.emit(());
|
||||||
|
on_close.emit(());
|
||||||
|
}
|
||||||
|
})}>
|
||||||
|
{"Reset All Colors"}
|
||||||
|
</button>
|
||||||
<button class="save-button" onclick={on_save_click}>
|
<button class="save-button" onclick={on_save_click}>
|
||||||
{"Save"}
|
{"Save"}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -4270,6 +4270,13 @@ body {
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.color-preview-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--spacing-sm);
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.color-value {
|
.color-value {
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
@@ -4277,6 +4284,25 @@ body {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reset-this-color-button {
|
||||||
|
background: var(--background-secondary);
|
||||||
|
color: var(--text-secondary);
|
||||||
|
border: 1px solid var(--border-secondary);
|
||||||
|
border-radius: var(--border-radius-small);
|
||||||
|
padding: var(--spacing-xs) var(--spacing-sm);
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: var(--transition-fast);
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reset-this-color-button:hover {
|
||||||
|
background: var(--background-tertiary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
border-color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
.color-input-section {
|
.color-input-section {
|
||||||
margin-bottom: var(--spacing-lg);
|
margin-bottom: var(--spacing-lg);
|
||||||
}
|
}
|
||||||
@@ -4359,7 +4385,7 @@ body {
|
|||||||
border-radius: 0 0 var(--border-radius-medium) var(--border-radius-medium);
|
border-radius: 0 0 var(--border-radius-medium) var(--border-radius-medium);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cancel-button, .save-button {
|
.cancel-button, .reset-all-button, .save-button {
|
||||||
padding: var(--spacing-sm) var(--spacing-md);
|
padding: var(--spacing-sm) var(--spacing-md);
|
||||||
border: 1px solid var(--border-secondary);
|
border: 1px solid var(--border-secondary);
|
||||||
border-radius: var(--border-radius-small);
|
border-radius: var(--border-radius-small);
|
||||||
@@ -4379,6 +4405,19 @@ body {
|
|||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.reset-all-button {
|
||||||
|
background: var(--warning-color);
|
||||||
|
color: white;
|
||||||
|
border-color: var(--warning-color);
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: var(--spacing-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reset-all-button:hover {
|
||||||
|
background: #e0a800;
|
||||||
|
border-color: #e0a800;
|
||||||
|
}
|
||||||
|
|
||||||
.save-button {
|
.save-button {
|
||||||
background: var(--info-color);
|
background: var(--info-color);
|
||||||
color: white;
|
color: white;
|
||||||
|
|||||||
Reference in New Issue
Block a user