Allow for deleting scripts from the editor.

This commit is contained in:
Condorra 2024-10-11 14:23:37 +11:00
parent c5115993cb
commit 17547c7434
3 changed files with 94 additions and 11 deletions

View File

@ -1,4 +1,4 @@
use std::{ops::Deref, rc::Rc};
use std::{ops::Deref, rc::Rc, str::FromStr};
use crate::{
command_handler::execute_queue, FrameId, GlobalLayoutState, GlobalMemoCell, PanelDirection,
@ -6,10 +6,12 @@ use crate::{
};
use anyhow::Error;
use create_script_dialog::CreateScriptDialog;
use delete_script_dialog::DeleteScriptDialog;
use editor_area::EditorArea;
use editor_nav::EditorNav;
use storage::fetch_initial_editor_state;
use web_sys::KeyboardEvent;
use wasm_bindgen_futures::js_sys::JsString;
use web_sys::{console, KeyboardEvent};
use yew::{
function_component, html, use_node_ref, use_state_eq, AttrValue, Callback, Html, Properties,
UseStateHandle,
@ -19,6 +21,7 @@ pub use self::storage::load_extant_file_contents;
use self::storage::load_file_contents;
mod create_script_dialog;
mod delete_script_dialog;
mod editor_area;
mod editor_nav;
mod storage;
@ -44,13 +47,13 @@ fn close_editor(frame: &FrameId, global_layout: &UseStateHandle<Rc<GlobalLayoutS
global_layout.set(gl_new.into());
}
#[derive(Clone, PartialEq)]
#[derive(Clone, PartialEq, Debug)]
pub struct EditorViewState {
error_msg: Option<AttrValue>,
available_files: Vec<AttrValue>,
open_file: AttrValue,
show_create_dialog: bool,
show_delete_dialog: Option<String>,
show_delete_dialog: Option<AttrValue>,
}
pub fn try_run_script(script: &str, global_memo: &GlobalMemoCell) -> anyhow::Result<()> {
@ -160,10 +163,14 @@ pub fn editor_view(props: &EditorViewProps) -> Html {
let global_memo = props.global_memo.clone();
let kb_editor_state = editor_state.clone();
console::log_1(&JsString::from_str(&format!("{:?}", editor_state.as_ref())).unwrap());
html! {
<div class="w-100 h-100" onkeydown={keyboard_handler(kb_editor_state, global_memo, global_layout, set_err, frame)} ref={editor_ref.clone()}>
{if editor_state.show_create_dialog {
html! { <CreateScriptDialog ..detail_props.clone() /> }
} else if let Some(ref delete_file) = editor_state.show_delete_dialog {
html! { <DeleteScriptDialog editor_state={editor_state.clone()}
filename={delete_file.clone()}/> }
} else {
html! { <></> }
}}

View File

@ -0,0 +1,58 @@
use itertools::Itertools;
use std::{ops::Deref, rc::Rc};
use yew::{function_component, html, AttrValue, Html, Properties, UseStateHandle};
use super::{close_modals, EditorViewState};
#[derive(Properties, PartialEq, Clone)]
pub(super) struct DeleteScriptProps {
pub filename: AttrValue,
pub editor_state: UseStateHandle<Rc<EditorViewState>>,
}
fn delete_script(filename: &AttrValue, state: &UseStateHandle<Rc<EditorViewState>>) {
let mut new_state = (*state.deref().deref()).clone();
if let Some((pos, _)) = new_state
.available_files
.iter()
.find_position(|v| *v == filename)
{
new_state.available_files.remove(pos);
if &new_state.open_file == filename {
new_state.open_file = "init.lua".into();
}
}
new_state.show_delete_dialog = None;
state.set(new_state.into());
}
#[function_component(DeleteScriptDialog)]
pub(super) fn delete_script_dialog(props: &DeleteScriptProps) -> Html {
let state_modalclose1 = props.editor_state.clone();
let state_modalclose2 = props.editor_state.clone();
let state_deletescript = props.editor_state.clone();
let filename_deletescript = props.filename.clone();
html! { <>
<div class="modal-backdrop fade show"/>
<div class="modal" tabindex="-1" aria-modal="true" role="dialog" style="display: block">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{"Delete script"}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"
onclick={move |_ev| close_modals(&state_modalclose1) }></button>
</div>
<div class="modal-body">
<p>{format!("Are you sure you wish to permanently delete {}?", props.filename)}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"
onclick={move |_ev| close_modals(&state_modalclose2) }>{"Close"}</button>
<button type="button" class="btn btn-primary" onclick={move |_ev| delete_script(&filename_deletescript, &state_deletescript) }>{"Delete"}</button>
</div>
</div>
</div>
</div>
</>}
}

View File

@ -1,7 +1,7 @@
use std::{ops::Deref, rc::Rc};
use itertools::Itertools;
use web_sys::KeyboardEvent;
use web_sys::{KeyboardEvent, MouseEvent};
use yew::{function_component, html, AttrValue, Html, UseStateHandle};
use super::{close_editor, run_script, select_file, EditorViewDetailProps, EditorViewState};
@ -49,6 +49,12 @@ fn item_keyboard_handler(
}
}
fn show_delete_dialog(state: &UseStateHandle<Rc<EditorViewState>>, script: &AttrValue) {
let mut new_state = (*state.as_ref()).clone();
new_state.show_delete_dialog = Some(script.clone());
state.set(new_state.into());
}
#[function_component(EditorNav)]
pub(super) fn editor_nav(props: &EditorViewDetailProps) -> Html {
let global_memo = props.global_memo.clone();
@ -82,7 +88,7 @@ pub(super) fn editor_nav(props: &EditorViewDetailProps) -> Html {
.available_files
.iter()
.map(|f| {
let mut classes = vec!["list-group-item", "pe-auto"];
let mut classes = vec!["list-group-item", "d-flex"];
let mut aria_current = None;
if *f == props.editor_state.open_file {
aria_current = Some("true");
@ -92,12 +98,24 @@ pub(super) fn editor_nav(props: &EditorViewDetailProps) -> Html {
let state_for_click = props.editor_state.clone();
let filename_for_kb: AttrValue = f.clone();
let state_for_kb = props.editor_state.clone();
html! { <li aria-current={aria_current} tabindex={0}
let state_for_delscript = state_for_kb.clone();
let filename_for_delscript: AttrValue = f.clone();
html! { <li aria-current={aria_current}
class={classes.iter().join(" ")}
onclick={move |_ev| select_file(&filename_for_click, &state_for_click)}
>
<div tabindex={0}
class="pe-auto"
onkeydown={item_keyboard_handler(filename_for_kb, state_for_kb)}
style="cursor: pointer"
>{f}</li>}
onclick={move |_ev| select_file(&filename_for_click, &state_for_click)}>{f}</div>
<div class="flex-fill"/>
{if f != "init.lua" {
html! { <button class="btn" onclick={move |ev: MouseEvent| {
show_delete_dialog(&state_for_delscript, &filename_for_delscript);
ev.prevent_default();
}} aria-label="Delete" title="Delete"><i class="bi bi-trash"></i></button> }
} else { html!{<></>} } }
</li>}
})
.collect::<Vec<Html>>()
}