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