Skip to main content

perspective_viewer/custom_elements/
export_dropdown.rs

1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████       █      █      █      █      █ █▄  ▀███ █       ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█  ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄  ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄   █ ▄▄▄▄▄ ┃
5// ┃ █      ██████ █  ▀█▄       █ ██████      █      ███▌▐███ ███████▄ █       ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors.                              ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13use 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    /// Internal Only.
62    ///
63    /// Set this custom element model's raw pointer.
64    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}