Skip to content

Commit

Permalink
Merge pull request #1744 from finos/copy-menu
Browse files Browse the repository at this point in the history
Copy menu
  • Loading branch information
texodus authored Mar 9, 2022
2 parents b246196 + 6a2ab08 commit 2d0744c
Show file tree
Hide file tree
Showing 32 changed files with 738 additions and 414 deletions.
22 changes: 3 additions & 19 deletions packages/perspective-viewer-d3fc/src/js/plugin/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,26 +225,10 @@ export function register(...plugins) {
);
}

const button = document.createElement("a");
button.setAttribute("download", "perspective.png");
document.body.appendChild(button);
button.addEventListener(
"click",
function dlCanvas() {
var dt = canvas.toDataURL("image/png"); // << this fails in IE/Edge...
dt = dt.replace(
/^data:image\/[^;]*/,
"data:application/octet-stream"
);
dt = dt.replace(
/^data:application\/octet-stream/,
"data:application/octet-stream;headers=Content-Disposition%3A%20attachment%3B%20filename=perspective.png"
);
this.href = dt;
},
false
return await new Promise(
(x) => canvas.toBlob((blob) => x(blob)),
"image/png"
);
button.click();
}

async draw(view, end_col, end_row) {
Expand Down
21 changes: 21 additions & 0 deletions rust/perspective-viewer/src/less/dropdown-menu.less
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@
monospace;
}

input {
margin-left: 12px;
margin-right: 12px;
padding: 0;
border: none;
border-bottom: 1px solid var(--inactive--color, #ccc);
background: transparent;
font-family: var(--interface-monospace--font-family, "Roboto Mono"),
monospace;
font-weight: 300;
font-size: 14px;
color: inherit;
outline: none;
}

.invalid {
color: var(--error--color, #ff0000);
border-color: var(--error--color, #ff0000);
}

.selected {
background-color: rgba(0, 0, 0, 0.05);
}
Expand All @@ -41,6 +61,7 @@
display: flex;
flex-direction: column;
margin-left: 12px;
margin-right: 12px;
}

span {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ pub struct DropDownMenu<T>
where
T: Into<Html> + Clone + PartialEq + 'static,
{
top: i32,
left: i32,
position: Option<(i32, i32)>,
_props: PhantomData<T>,
}

Expand All @@ -48,25 +47,20 @@ where

fn create(_ctx: &Context<Self>) -> Self {
DropDownMenu {
top: 0,
left: 0,
position: None,
_props: Default::default(),
}
}

fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
DropDownMenuMsg::SetPos(top, left) => {
self.top = top;
self.left = left;
self.position = Some((top, left));
true
}
}
}

fn changed(&mut self, _ctx: &Context<Self>) -> bool {
false
}

fn view(&self, ctx: &Context<Self>) -> Html {
let values = &ctx.props().values;
Expand Down Expand Up @@ -118,8 +112,14 @@ where
<>
<style>
{ &CSS }
{ format!(":host{{left:{}px;top:{}px;}}", self.left, self.top) }
</style>
{
self.position.map(|(top, left)| html! {
<style>
{ format!(":host{{left:{}px;top:{}px;}}", left, top) }
</style>
}).unwrap_or_default()
}
{ body }
</>
}
Expand Down
33 changes: 33 additions & 0 deletions rust/perspective-viewer/src/rust/components/copy_dropdown.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2018, the Perspective Authors.
//
// This file is part of the Perspective library, distributed under the terms
// of the Apache License 2.0. The full license can be found in the LICENSE
// file.

use super::containers::dropdown_menu::*;
use crate::model::*;

pub fn get_menu_items(has_render: bool) -> Vec<CopyDropDownMenuItem> {
vec![
CopyDropDownMenuItem::OptGroup(
"Current View",
if has_render {
vec![ExportMethod::Csv, ExportMethod::Json, ExportMethod::Png]
} else {
vec![ExportMethod::Csv, ExportMethod::Json]
},
),
CopyDropDownMenuItem::OptGroup(
"All",
vec![ExportMethod::CsvAll, ExportMethod::JsonAll],
),
CopyDropDownMenuItem::OptGroup("Config", vec![ExportMethod::JsonConfig]),
]
}

pub type CopyDropDownMenu = DropDownMenu<ExportMethod>;
pub type CopyDropDownMenuProps = DropDownMenuProps<ExportMethod>;
pub type CopyDropDownMenuMsg = DropDownMenuMsg;
pub type CopyDropDownMenuItem = DropDownMenuItem<ExportMethod>;
142 changes: 109 additions & 33 deletions rust/perspective-viewer/src/rust/components/export_dropdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,121 @@
// file.

use super::containers::dropdown_menu::*;
use crate::model::*;
use crate::renderer::*;

use crate::*;
use js_intern::*;
use std::rc::Rc;
use yew::prelude::*;

#[derive(Clone, Copy, PartialEq)]
pub enum ExportMethod {
Csv,
CsvAll,
Html,
Png,
Arrow,
ArrowAll,
pub type ExportDropDownMenuItem = DropDownMenuItem<ExportFile>;

#[derive(Properties, Clone, PartialEq)]
pub struct ExportDropDownMenuProps {
pub renderer: Renderer,
pub callback: Callback<ExportFile>,
}

impl From<ExportMethod> for Html {
fn from(x: ExportMethod) -> Self {
match x {
ExportMethod::Csv => html_template! {
<code>{ ".csv " }</code>
},
ExportMethod::CsvAll => html_template! {
<code>{ ".csv " }</code>
},
ExportMethod::Html => html_template! {
<code>{ ".html " }</code>
},
ExportMethod::Png => html_template! {
<code>{ ".png " }</code>
},
ExportMethod::Arrow => html_template! {
<code>{ ".arrow " }</code>
},
ExportMethod::ArrowAll => html_template! {
<code>{ ".arrow " }</code>
#[derive(Default)]
pub struct ExportDropDownMenu {
top: i32,
left: i32,
title: String,
input_ref: NodeRef,
invalid: bool,
}

pub enum ExportDropDownMenuMsg {
SetPos(i32, i32),
TitleChange,
}

fn get_menu_items(name: &str, has_render: bool) -> Vec<ExportDropDownMenuItem> {
vec![
ExportDropDownMenuItem::OptGroup(
"Current View",
if has_render {
vec![
ExportMethod::Csv.new_file(name),
ExportMethod::Json.new_file(name),
ExportMethod::Arrow.new_file(name),
ExportMethod::Html.new_file(name),
ExportMethod::Png.new_file(name),
]
} else {
vec![
ExportMethod::Csv.new_file(name),
ExportMethod::Json.new_file(name),
ExportMethod::Arrow.new_file(name),
ExportMethod::Html.new_file(name),
]
},
),
ExportDropDownMenuItem::OptGroup(
"All",
vec![
ExportMethod::CsvAll.new_file(name),
ExportMethod::JsonAll.new_file(name),
ExportMethod::ArrowAll.new_file(name),
],
),
ExportDropDownMenuItem::OptGroup(
"Config",
vec![ExportMethod::JsonConfig.new_file(name)],
),
]
}

impl Component for ExportDropDownMenu {
type Properties = ExportDropDownMenuProps;
type Message = ExportDropDownMenuMsg;

fn view(&self, ctx: &Context<Self>) -> yew::virtual_dom::VNode {
let callback = ctx.link().callback(|_| ExportDropDownMenuMsg::TitleChange);
let plugin = ctx.props().renderer.get_active_plugin().unwrap();
let has_render = js_sys::Reflect::has(&plugin, js_intern!("render")).unwrap();
html_template! {
<style>
{ format!(":host{{left:{}px;top:{}px;}}", self.left, self.top) }
</style>
<span class="dropdown-group-label">{ "Save as" }</span>
<input
class={ if self.invalid { "invalid" } else { "" }}
oninput={ callback }
ref={ self.input_ref.clone() }
value={ self.title.to_owned() } />
<DropDownMenu<ExportFile>
values={ Rc::new(get_menu_items(&self.title, has_render)) }
callback={ ctx.props().callback.clone() }>
</DropDownMenu<ExportFile>>
}
}
}

pub type ExportDropDownMenu = DropDownMenu<ExportMethod>;
pub type ExportDropDownMenuProps = DropDownMenuProps<ExportMethod>;
pub type ExportDropDownMenuMsg = DropDownMenuMsg;
pub type ExportDropDownMenuItem = DropDownMenuItem<ExportMethod>;
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
ExportDropDownMenuMsg::SetPos(top, left) => {
self.top = top;
self.left = left;
true
}
ExportDropDownMenuMsg::TitleChange => {
self.title = self
.input_ref
.cast::<web_sys::HtmlInputElement>()
.unwrap()
.value();

self.invalid = self.title.is_empty();
true
}
}
}

fn create(_ctx: &Context<Self>) -> Self {
ExportDropDownMenu {
title: "untitled".to_owned(),
..Default::default()
}
}
}
1 change: 1 addition & 0 deletions rust/perspective-viewer/src/rust/components/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
//! `components` contains all Yew `Component` types, but only exports the 4 necessary
//! for public Custom Elements. The rest are internal components of these 4.
pub mod copy_dropdown;
pub mod export_dropdown;
pub mod expression_editor;
pub mod filter_dropdown;
Expand Down
Loading

0 comments on commit 2d0744c

Please sign in to comment.