Skip to main content

perspective_viewer/components/
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::rc::Rc;
14
15use yew::prelude::*;
16
17use crate::config::*;
18use crate::renderer::*;
19use crate::session::Session;
20use crate::ui::{DropDownMenu, DropDownMenuItem};
21
22pub type ExportDropDownMenuItem = DropDownMenuItem<ExportFile>;
23
24#[derive(Properties, PartialEq)]
25pub struct ExportDropDownMenuProps {
26    pub renderer: Renderer,
27    pub session: Session,
28    pub callback: Callback<ExportFile>,
29}
30
31pub enum ExportDropDownMenuMsg {
32    TitleChange,
33}
34
35#[derive(Default)]
36pub struct ExportDropDownMenu {
37    title: String,
38    input_ref: NodeRef,
39    invalid: bool,
40}
41
42impl Component for ExportDropDownMenu {
43    type Message = ExportDropDownMenuMsg;
44    type Properties = ExportDropDownMenuProps;
45
46    fn view(&self, ctx: &Context<Self>) -> yew::virtual_dom::VNode {
47        let callback = ctx.link().callback(|_| ExportDropDownMenuMsg::TitleChange);
48        let is_chart = ctx.props().renderer.is_chart();
49        html! {
50            <>
51                <span class="dropdown-group-label">{ "Save as" }</span>
52                <input
53                    class={if self.invalid { "invalid" } else { "" }}
54                    oninput={callback}
55                    ref={&self.input_ref}
56                    value={self.title.to_owned()}
57                />
58                <DropDownMenu<ExportFile>
59                    values={Rc::new(get_menu_items(&self.title, is_chart))}
60                    callback={&ctx.props().callback}
61                />
62            </>
63        }
64    }
65
66    fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
67        match msg {
68            ExportDropDownMenuMsg::TitleChange => {
69                self.title = self
70                    .input_ref
71                    .cast::<web_sys::HtmlInputElement>()
72                    .unwrap()
73                    .value();
74
75                self.invalid = self.title.is_empty();
76                true
77            },
78        }
79    }
80
81    fn create(ctx: &Context<Self>) -> Self {
82        Self {
83            title: ctx
84                .props()
85                .session
86                .get_title()
87                .unwrap_or_else(|| "untitled".to_owned()),
88            ..Default::default()
89        }
90    }
91}
92
93fn get_menu_items(name: &str, is_chart: bool) -> Vec<ExportDropDownMenuItem> {
94    vec![
95        ExportDropDownMenuItem::OptGroup(
96            "Current View".into(),
97            if is_chart {
98                vec![
99                    ExportMethod::Csv.new_file(name, is_chart),
100                    ExportMethod::Json.new_file(name, is_chart),
101                    ExportMethod::Ndjson.new_file(name, is_chart),
102                    ExportMethod::Arrow.new_file(name, is_chart),
103                    ExportMethod::ArrowLz4.new_file(name, is_chart),
104                    ExportMethod::ArrowZstd.new_file(name, is_chart),
105                    ExportMethod::Html.new_file(name, is_chart),
106                    ExportMethod::Plugin.new_file(name, is_chart),
107                ]
108            } else {
109                vec![
110                    ExportMethod::Csv.new_file(name, is_chart),
111                    ExportMethod::Json.new_file(name, is_chart),
112                    ExportMethod::Ndjson.new_file(name, is_chart),
113                    ExportMethod::Arrow.new_file(name, is_chart),
114                    ExportMethod::ArrowLz4.new_file(name, is_chart),
115                    ExportMethod::ArrowZstd.new_file(name, is_chart),
116                    ExportMethod::Html.new_file(name, is_chart),
117                ]
118            },
119        ),
120        ExportDropDownMenuItem::OptGroup("All".into(), vec![
121            ExportMethod::CsvAll.new_file(name, is_chart),
122            ExportMethod::JsonAll.new_file(name, is_chart),
123            ExportMethod::NdjsonAll.new_file(name, is_chart),
124            ExportMethod::ArrowAll.new_file(name, is_chart),
125            ExportMethod::ArrowLz4All.new_file(name, is_chart),
126            ExportMethod::ArrowZstdAll.new_file(name, is_chart),
127        ]),
128        ExportDropDownMenuItem::OptGroup("Config".into(), vec![
129            ExportMethod::JsonConfig.new_file(name, is_chart),
130        ]),
131    ]
132}