perspective_viewer/custom_elements/
export_dropdown.rs1use std::cell::RefCell;
14use std::rc::Rc;
15
16use perspective_js::utils::global;
17use wasm_bindgen::prelude::*;
18use wasm_bindgen_futures::spawn_local;
19use web_sys::*;
20use yew::*;
21
22use super::viewer::PerspectiveViewerElement;
23use crate::components::export_dropdown::*;
24use crate::custom_elements::modal::*;
25use crate::model::*;
26use crate::utils::*;
27use crate::*;
28
29#[wasm_bindgen]
30#[derive(Clone)]
31pub struct ExportDropDownMenuElement {
32 elem: HtmlElement,
33 modal: Rc<RefCell<Option<ModalElement<ExportDropDownMenu>>>>,
34}
35
36impl CustomElementMetadata for ExportDropDownMenuElement {
37 const CUSTOM_ELEMENT_NAME: &'static str = "perspective-export-menu";
38}
39
40#[wasm_bindgen]
41impl ExportDropDownMenuElement {
42 #[wasm_bindgen(constructor)]
43 pub fn new(elem: HtmlElement) -> Self {
44 Self {
45 elem,
46 modal: Default::default(),
47 }
48 }
49
50 pub fn open(&self, target: HtmlElement) {
51 if let Some(x) = &*self.modal.borrow() {
52 ApiFuture::spawn(x.clone().open(target, None));
53 }
54 }
55
56 pub fn hide(&self) -> ApiResult<()> {
57 let borrowed = self.modal.borrow();
58 borrowed.as_ref().into_apierror()?.hide()
59 }
60
61 pub fn __set_model(&self, parent: &PerspectiveViewerElement) {
65 self.set_config_model(parent)
66 }
67
68 pub fn connected_callback(&self) {}
69}
70
71impl ExportDropDownMenuElement {
72 pub fn new_from_model<A>(model: &A) -> Self
73 where
74 A: GetViewerConfigModel + StateProvider,
75 <A as StateProvider>::State: HasPresentation + HasRenderer + HasSession,
76 {
77 let dropdown = global::document()
78 .create_element("perspective-export-menu")
79 .unwrap()
80 .unchecked_into::<HtmlElement>();
81
82 let elem = Self::new(dropdown);
83 elem.set_config_model(model);
84 elem
85 }
86
87 fn set_config_model<A>(&self, model: &A)
88 where
89 A: GetViewerConfigModel + StateProvider,
90 <A as StateProvider>::State: HasPresentation + HasRenderer + HasSession,
91 {
92 let callback = Callback::from({
93 let model = model.clone_state();
94 let modal_rc = self.modal.clone();
95 move |x: ExportFile| {
96 if !x.name.is_empty() {
97 clone!(modal_rc, model);
98 spawn_local(async move {
99 let val = model.export_method_to_blob(x.method).await.unwrap();
100 let is_chart = model.renderer().is_chart();
101 download(&x.as_filename(is_chart), &val).unwrap();
102 modal_rc.borrow().clone().unwrap().hide().unwrap();
103 })
104 }
105 }
106 });
107
108 let renderer = model.renderer().clone();
109 let session = model.session().clone();
110 let props = props!(ExportDropDownMenuProps {
111 renderer,
112 session,
113 callback,
114 root: self.elem.clone()
115 });
116
117 let modal = ModalElement::new(self.elem.clone(), props, true, None);
118 *self.modal.borrow_mut() = Some(modal);
119 }
120}