perspective_viewer/components/
export_dropdown.rs1use std::rc::Rc;
14
15use session::Session;
16use yew::prelude::*;
17
18use super::containers::dropdown_menu::*;
19use super::modal::{ModalLink, SetModalLink};
20use super::style::StyleProvider;
21use crate::model::*;
22use crate::renderer::*;
23use crate::utils::*;
24use crate::*;
25
26pub type ExportDropDownMenuItem = DropDownMenuItem<ExportFile>;
27
28#[derive(Properties, PartialEq)]
29pub struct ExportDropDownMenuProps {
30 pub renderer: Renderer,
31 pub session: Session,
32 pub callback: Callback<ExportFile>,
33 pub root: web_sys::HtmlElement,
34
35 #[prop_or_default]
36 weak_link: WeakScope<ExportDropDownMenu>,
37}
38
39impl ModalLink<ExportDropDownMenu> for ExportDropDownMenuProps {
40 fn weak_link(&self) -> &'_ utils::WeakScope<ExportDropDownMenu> {
41 &self.weak_link
42 }
43}
44
45pub enum ExportDropDownMenuMsg {
46 TitleChange,
47}
48
49#[derive(Default)]
50pub struct ExportDropDownMenu {
51 title: String,
52 _sub: Option<Subscription>,
53 input_ref: NodeRef,
54 invalid: bool,
55}
56
57impl Component for ExportDropDownMenu {
58 type Message = ExportDropDownMenuMsg;
59 type Properties = ExportDropDownMenuProps;
60
61 fn view(&self, ctx: &Context<Self>) -> yew::virtual_dom::VNode {
62 let callback = ctx.link().callback(|_| ExportDropDownMenuMsg::TitleChange);
63 let plugin = ctx.props().renderer.get_active_plugin().unwrap();
64 let is_chart = plugin.name().as_str() != "Datagrid";
67 html! {
68 <StyleProvider root={ctx.props().root.clone()}>
69 <span class="dropdown-group-label">{ "Save as" }</span>
70 <input
71 class={if self.invalid { "invalid" } else { "" }}
72 oninput={callback}
73 ref={&self.input_ref}
74 value={self.title.to_owned()}
75 />
76 <DropDownMenu<ExportFile>
77 values={Rc::new(get_menu_items(&self.title, is_chart))}
78 callback={&ctx.props().callback}
79 />
80 </StyleProvider>
81 }
82 }
83
84 fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
85 match msg {
86 ExportDropDownMenuMsg::TitleChange => {
87 self.title = self
88 .input_ref
89 .cast::<web_sys::HtmlInputElement>()
90 .unwrap()
91 .value();
92
93 self.invalid = self.title.is_empty();
94 true
95 },
96 }
97 }
98
99 fn create(ctx: &Context<Self>) -> Self {
100 ctx.set_modal_link();
101 let _sub = Some(
102 ctx.props()
103 .renderer
104 .plugin_changed
105 .add_listener(ctx.link().callback(|_| ExportDropDownMenuMsg::TitleChange)),
106 );
107
108 Self {
109 title: ctx
110 .props()
111 .session
112 .get_title()
113 .unwrap_or_else(|| "untitled".to_owned()),
114 _sub,
115 ..Default::default()
116 }
117 }
118}
119
120fn get_menu_items(name: &str, is_chart: bool) -> Vec<ExportDropDownMenuItem> {
121 vec![
122 ExportDropDownMenuItem::OptGroup(
123 "Current View".into(),
124 if is_chart {
125 vec![
126 ExportMethod::Csv.new_file(name, is_chart),
127 ExportMethod::Json.new_file(name, is_chart),
128 ExportMethod::Ndjson.new_file(name, is_chart),
129 ExportMethod::Arrow.new_file(name, is_chart),
130 ExportMethod::Html.new_file(name, is_chart),
131 ExportMethod::Plugin.new_file(name, is_chart),
132 ]
133 } else {
134 vec![
135 ExportMethod::Csv.new_file(name, is_chart),
136 ExportMethod::Json.new_file(name, is_chart),
137 ExportMethod::Ndjson.new_file(name, is_chart),
138 ExportMethod::Arrow.new_file(name, is_chart),
139 ExportMethod::Html.new_file(name, is_chart),
140 ]
141 },
142 ),
143 ExportDropDownMenuItem::OptGroup("All".into(), vec![
144 ExportMethod::CsvAll.new_file(name, is_chart),
145 ExportMethod::JsonAll.new_file(name, is_chart),
146 ExportMethod::NdjsonAll.new_file(name, is_chart),
147 ExportMethod::ArrowAll.new_file(name, is_chart),
148 ]),
149 ExportDropDownMenuItem::OptGroup("Config".into(), vec![
150 ExportMethod::JsonConfig.new_file(name, is_chart),
151 ]),
152 ]
153}