use std::collections::HashSet;
use futures::join;
use itertools::Itertools;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::JsFuture;
use super::export_app;
use super::export_method::*;
use super::get_viewer_config::*;
use super::structural::*;
use crate::config::*;
use crate::js::JsPerspectiveViewerPlugin;
use crate::utils::*;
fn tag_name_to_package(plugin: &JsPerspectiveViewerPlugin) -> String {
let tag_name = plugin.unchecked_ref::<web_sys::HtmlElement>().tag_name();
let tag_parts = tag_name.split('-').take(3).map(|x| x.to_lowercase());
Itertools::intersperse(tag_parts, "-".to_owned()).collect::<String>()
}
pub trait CopyExportModel:
HasSession + HasRenderer + HasPresentation + GetViewerConfigModel
{
fn html_as_jsvalue(&self) -> ApiFuture<web_sys::Blob> {
let view_config = self.get_viewer_config();
let session = self.session().clone();
let plugins = self
.renderer()
.get_all_plugins()
.iter()
.map(tag_name_to_package)
.collect::<HashSet<String>>()
.into_iter()
.collect::<Vec<_>>();
ApiFuture::new(async move {
let (arrow, config) = join!(session.arrow_as_vec(true), view_config);
let arrow = arrow?;
let mut config = config?;
config.settings = false;
let js_config = serde_json::to_string(&config)?;
let html = export_app::render(&base64::encode(arrow), &js_config, &plugins);
js_sys::JsString::from(html.trim()).as_blob()
})
}
fn png_as_jsvalue(&self) -> ApiFuture<web_sys::Blob> {
let renderer = self.renderer().clone();
ApiFuture::new(async move {
let plugin = renderer.get_active_plugin()?;
let render = js_sys::Reflect::get(&plugin, js_intern::js_intern!("render"))?;
let render_fun = render.unchecked_into::<js_sys::Function>();
let png = render_fun.call0(&plugin)?;
let result = JsFuture::from(png.unchecked_into::<js_sys::Promise>())
.await?
.unchecked_into();
Ok(result)
})
}
fn export_method_to_jsvalue(&self, method: ExportMethod) -> ApiFuture<web_sys::Blob> {
match method {
ExportMethod::Csv => {
let session = self.session().clone();
ApiFuture::new(async move { session.csv_as_jsvalue(false).await?.as_blob() })
}
ExportMethod::CsvAll => {
let session = self.session().clone();
ApiFuture::new(async move { session.csv_as_jsvalue(true).await?.as_blob() })
}
ExportMethod::Json => {
let session = self.session().clone();
ApiFuture::new(async move { session.json_as_jsvalue(false).await?.as_blob() })
}
ExportMethod::JsonAll => {
let session = self.session().clone();
ApiFuture::new(async move { session.json_as_jsvalue(true).await?.as_blob() })
}
ExportMethod::Arrow => {
let session = self.session().clone();
ApiFuture::new(async move { session.arrow_as_jsvalue(false).await?.as_blob() })
}
ExportMethod::ArrowAll => {
let session = self.session().clone();
ApiFuture::new(async move { session.arrow_as_jsvalue(true).await?.as_blob() })
}
ExportMethod::Html => {
let html_task = self.html_as_jsvalue();
ApiFuture::new(async move { html_task.await })
}
ExportMethod::Png => {
let png_task = self.png_as_jsvalue();
ApiFuture::new(async move { png_task.await })
}
ExportMethod::JsonConfig => {
let config_task = self.get_viewer_config();
ApiFuture::new(async move {
config_task
.await?
.encode(&Some(ViewerConfigEncoding::JSONString))?
.dyn_into::<js_sys::JsString>()?
.as_blob()
})
}
}
}
}
impl<T: HasRenderer + HasSession + HasPresentation> CopyExportModel for T {}