Skip to content

Commit

Permalink
Optional lazy-load monaco
Browse files Browse the repository at this point in the history
  • Loading branch information
texodus committed Jun 1, 2021
1 parent 4fd5ad9 commit 1d4ba84
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 132 deletions.
70 changes: 35 additions & 35 deletions packages/perspective-viewer/test/js/expressions.spec.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions packages/perspective-viewer/test/results/linux.docker.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"Computed_Expressions_On_restore,_computed_expressions_in_classic_syntax_are_parsed_correctly_": "563f8c45e0ec32bc4b07d30ed5f0086e",
"superstore_adds_computed_column_via_attribute": "f2fa526d6f0c168a47ab272bb7ae5771",
"superstore_user_defined_aggregates_maintained_on_computed_columns": "c7aa2902feb512ceb1e1487de80878ff",
"__GIT_COMMIT__": "c77ae83b4a840f9c60ba3da34ea90c1feaee38cd",
"__GIT_COMMIT__": "4fd5ad95a4963f7b3107ee30e57cacf9873cf315",
"blank_Handles_reloading_with_a_schema_": "2f23d1416fc97e07a3a21e318411e0d1",
"superstore_doesn_t_leak_tables_": "5bb762b2860eb5af067bb83afbca3264",
"superstore_doesn_t_leak_elements_": "b8a3a84406fede4823cd51e07b817752",
Expand Down Expand Up @@ -102,8 +102,8 @@
"Expressions_Should_show_the_help_panel": "dc16ac2736a46205fa13a30cc2842510",
"Expressions_Non-aliased_expressions_should_have_autogenerated_alias": "0478c89a614c402083c7bf0eca48a66d",
"Expressions_Should_skip_if_trying_to_set_an_expression_without_an_alias": "d13e8556321b0a8bbbf5122ce4f95754",
"Expressions_Should_prevent_saving_a_duplicate_expression_alias": "c81d4acdf520022350547c4840e54cd0",
"Expressions_Should_not_prevent_saving_a_duplicate_expression_with_a_different_alias": "ba4431523a591e5043517e4c21407efb",
"Expressions_Should_prevent_saving_a_duplicate_expression_alias": "e41844fdfdc7f649e9b4c4335438c183",
"Expressions_Should_not_prevent_saving_a_duplicate_expression_with_a_different_alias": "af4df1a2574f31d11887e142dd292f8d",
"Expressions_Should_prevent_saving_a_duplicate_expression": "81726370ce7b0df8f31ed5ab2bdcb57f",
"Expressions_Removing_expressions_should_reset_active_columns,_pivots,_sort,_and_filter_": "e31a7da6f65bf5edc7d6582a4514a069",
"Expressions_Resetting_the_viewer_with_expressions_should_place_columns_in_the_inactive_list_": "17722593bb3bc9564a29edf1859c6951",
Expand Down
14 changes: 14 additions & 0 deletions packages/perspective-webpack-plugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,20 @@ class PerspectiveWebpackPlugin {
if (this.options.inline || this.options.inlineWorker) {
rules[rules.length - 2].use.options.inline = "no-fallback";
rules[rules.length - 1].use.options.inline = "no-fallback";
} else {
rules.push({
test: /\.js$/,
include: /@finos\/perspective\-vieux/,
use: [
{
loader: "string-replace-loader",
options: {
search: /webpackMode:\s*?"eager"/g,
replace: ""
}
}
]
});
}

if (!(this.options.inline || this.options.inlineWasm)) {
Expand Down
1 change: 0 additions & 1 deletion rust/perspective-vieux/src/js/vieux.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

import init, * as internal from "../../pkg/perspective_vieux.js";
import wasm_internal from "../../pkg/perspective_vieux_bg.wasm";
import "./monaco.js";

export const wasm = init(wasm_internal).then(() => {
internal.set_panic_hook();
Expand Down
108 changes: 65 additions & 43 deletions rust/perspective-vieux/src/rust/components/expression_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
use crate::utils::monaco::*;
use crate::{exprtk::*, session::Session};

use std::rc::Rc;
use std::{cell::RefCell, rc::Rc};

use wasm_bindgen::{prelude::*, JsCast};
use wasm_bindgen_futures::future_to_promise;
Expand All @@ -29,22 +29,25 @@ pub enum ExpressionEditorMsg {

#[derive(Properties, Clone)]
pub struct ExpressionEditorProps {
pub callback: Rc<dyn Fn(JsValue)>,
pub on_save_callback: Rc<dyn Fn(JsValue)>,
pub on_init_callback: Rc<dyn Fn()>,
pub on_validate_callback: Rc<dyn Fn(bool)>,
pub session: Session,
}

/// A label widget which displays a row count and a "projection" count, the number of
/// rows in the `View` which includes aggregate rows.
#[derive(Clone)]
pub struct ExpressionEditor {
top: u32,
left: u32,
container: NodeRef,
editor: Option<MonacoEditor>,
editor: Rc<RefCell<Option<MonacoEditor>>>,
props: ExpressionEditorProps,
link: ComponentLink<Self>,
save_enabled: bool,
on_validate_callback: Closure<dyn Fn(JsValue)>,
on_save_callback: Closure<dyn Fn(JsValue)>,
on_validate_callback: Rc<Closure<dyn Fn(JsValue)>>,
on_save_callback: Rc<Closure<dyn Fn(JsValue)>>,
}

async fn proc(
Expand All @@ -65,20 +68,22 @@ impl Component for ExpressionEditor {

fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
let cb = link.callback(|x| ExpressionEditorMsg::Validate(x));
let on_validate_callback = Closure::wrap(Box::new(move |x| {
let on_validate_callback = Rc::new(Closure::wrap(Box::new(move |x| {
cb.emit(x);
}) as Box<dyn Fn(JsValue)>);
})
as Box<dyn Fn(JsValue)>));

let cb = link.callback(|_| ExpressionEditorMsg::SaveExpr);
let on_save_callback = Closure::wrap(Box::new(move |x| {
let on_save_callback = Rc::new(Closure::wrap(Box::new(move |x| {
cb.emit(x);
}) as Box<dyn Fn(JsValue)>);
})
as Box<dyn Fn(JsValue)>));

ExpressionEditor {
top: 0,
left: 0,
container: NodeRef::default(),
editor: None,
editor: Rc::new(RefCell::new(None)),
props,
link,
save_enabled: false,
Expand All @@ -92,7 +97,7 @@ impl Component for ExpressionEditor {
ExpressionEditorMsg::SetPos(top, left) => {
self.top = top;
self.left = left;
match self.editor.as_ref() {
match self.editor.borrow().as_ref() {
Some(x) => x.set_value(""),
None => {}
}
Expand All @@ -101,7 +106,8 @@ impl Component for ExpressionEditor {
}
ExpressionEditorMsg::Validate(_val) => {
// web_sys::console::log_1(&val);
let expr = self.editor.as_ref().unwrap().get_value();
let expr = self.editor.borrow().as_ref().unwrap().get_value();
(self.props.on_validate_callback)(true);
let callback = self
.link
.callback_once(|x| ExpressionEditorMsg::EnableSave(x));
Expand All @@ -110,16 +116,17 @@ impl Component for ExpressionEditor {
false
}
ExpressionEditorMsg::EnableSave(x) => {
(self.props.on_validate_callback)(false);
self.save_enabled = x;
true
}
ExpressionEditorMsg::SaveExpr => {
if self.save_enabled {
match self.editor.as_ref() {
match self.editor.borrow().as_ref() {
None => {}
Some(x) => {
let expr = x.get_value();
(self.props.callback)(expr);
(self.props.on_save_callback)(expr);
x.set_value("");
}
}
Expand All @@ -135,35 +142,50 @@ impl Component for ExpressionEditor {

fn rendered(&mut self, first_render: bool) {
if first_render {
init_monaco().unwrap();
let args = EditorArgs {
theme: "exprtk-theme",
value: "",
language: "exprtk",
automatic_layout: true,
minimap: MinimapArgs { enabled: false },
};

let container = self.container.cast::<HtmlElement>().unwrap();
let editor = Editor::create(container, JsValue::from_serde(&args).unwrap());
editor.add_command(
(KeyMod::Shift as u32) | (KeyCode::Enter as u32),
self.on_save_callback.as_ref().unchecked_ref(),
);

let model = editor.get_model();
model.on_did_change_content(
self.on_validate_callback.as_ref().unchecked_ref(),
);

self.editor = Some(editor.clone());
let on_init = Closure::once_into_js(move || editor.focus());
web_sys::window()
.unwrap()
.request_animation_frame(on_init.unchecked_ref())
.unwrap();
} else {
self.editor.as_ref().unwrap().focus();
let this = self.clone();
let _ = future_to_promise(async move {
let editor = init_monaco().await.unwrap();
let args = EditorArgs {
theme: "exprtk-theme",
value: "",
language: "exprtk",
automatic_layout: true,
minimap: MinimapArgs { enabled: false },
};

let container = this.container.cast::<HtmlElement>().unwrap();
let editor =
editor.create(container, JsValue::from_serde(&args).unwrap());
editor.add_command(
(KeyMod::Shift as u32) | (KeyCode::Enter as u32),
this.on_save_callback.as_ref().as_ref().unchecked_ref(),
);

let model = editor.get_model();
model.on_did_change_content(
this.on_validate_callback.as_ref().as_ref().unchecked_ref(),
);

*this.editor.borrow_mut() = Some(editor.clone());
let on_init_callback = this.props.on_init_callback.clone();
let on_init = Closure::once_into_js(move || {
editor.focus();
web_sys::window()
.unwrap()
.request_animation_frame(
Closure::once_into_js(move || on_init_callback())
.unchecked_ref(),
)
.unwrap();
});

web_sys::window()
.unwrap()
.request_animation_frame(on_init.unchecked_ref())
.map(JsValue::from)
});
} else if self.editor.borrow().is_some() {
self.editor.borrow().as_ref().unwrap().focus();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,21 @@ impl ResizableMessage for <ExpressionEditor as Component>::Message {

impl PerspectiveExpressionEditorElement {
pub fn new(
target: HtmlElement,
custom_element: HtmlElement,
session: Session,
callback: Rc<dyn Fn(JsValue)>,
on_save_callback: Rc<dyn Fn(JsValue)>,
on_init_callback: Rc<dyn Fn()>,
on_validate_callback: Rc<dyn Fn(bool)>,
) -> PerspectiveExpressionEditorElement {
let props = ExpressionEditorProps { callback, session };
let modal = ModalElement::new(target, props);
PerspectiveExpressionEditorElement {
modal,
}
let props = ExpressionEditorProps {
on_save_callback,
on_init_callback,
on_validate_callback,
session,
};

let modal = ModalElement::new(custom_element, props);
PerspectiveExpressionEditorElement { modal }
}

pub fn open(&mut self, target: HtmlElement) -> Result<(), JsValue> {
Expand Down
32 changes: 17 additions & 15 deletions rust/perspective-vieux/src/rust/custom_elements/modal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use yew::prelude::*;
/// to any existing on-page elements, accounting for viewport, scroll position, etc.
pub struct ModalElement<T: Component> {
root: ComponentLink<T>,
elem: HtmlElement,
custom_element: HtmlElement,
target: Rc<RefCell<Option<HtmlElement>>>,
blurhandler: Rc<RefCell<Option<Closure<dyn FnMut(FocusEvent)>>>>,
}
Expand All @@ -33,7 +33,7 @@ where
fn clone(&self) -> Self {
ModalElement {
root: self.root.clone(),
elem: self.elem.clone(),
custom_element: self.custom_element.clone(),
target: self.target.clone(),
blurhandler: self.blurhandler.clone(),
}
Expand Down Expand Up @@ -135,10 +135,13 @@ where
T: Component,
<T as Component>::Message: ResizableMessage,
{
pub fn new(elem: web_sys::HtmlElement, props: T::Properties) -> ModalElement<T> {
elem.set_attribute("tabindex", "0").unwrap();
pub fn new(
custom_element: web_sys::HtmlElement,
props: T::Properties,
) -> ModalElement<T> {
custom_element.set_attribute("tabindex", "0").unwrap();
let init = web_sys::ShadowRootInit::new(web_sys::ShadowRootMode::Open);
let shadow_root = elem
let shadow_root = custom_element
.attach_shadow(&init)
.unwrap()
.unchecked_into::<web_sys::Element>();
Expand All @@ -148,7 +151,7 @@ where
let blurhandler = Rc::new(RefCell::new(None));
ModalElement {
root,
elem,
custom_element,
target: Rc::new(RefCell::new(None)),
blurhandler,
}
Expand All @@ -170,10 +173,10 @@ where
.unwrap()
.body()
.unwrap()
.append_child(&self.elem)?;
.append_child(&self.custom_element)?;

// Check if the modal has been positioned off-screen and re-locate if necessary
match calc_relative_position(&self.elem, top, left, height, width) {
match calc_relative_position(&self.custom_element, top, left, height, width) {
None => (),
Some((top, left)) => {
let msg = T::Message::resize(top as u32, left as u32);
Expand All @@ -187,7 +190,7 @@ where
this.close().unwrap();
}) as Box<dyn FnMut(FocusEvent)>));

self.elem.add_event_listener_with_callback(
self.custom_element.add_event_listener_with_callback(
"blur",
self.blurhandler
.borrow()
Expand All @@ -197,7 +200,7 @@ where
.unchecked_ref(),
)?;

self.elem.focus()
self.custom_element.focus()
}

/// Open this modal by attaching directly to `document.body` with position
Expand All @@ -207,7 +210,7 @@ where
/// Because the Custom Element has a `blur` handler, we must invoke this before
/// attempting to re-parent the element.
pub fn open(&mut self, target: web_sys::HtmlElement) -> Result<(), JsValue> {
self.elem.blur().unwrap();
self.custom_element.blur().unwrap();
let window = web_sys::window().unwrap();
let mut this = self.clone();
window.request_animation_frame(
Expand All @@ -219,7 +222,7 @@ where

/// Remove from document and cleanup.
pub fn close(&mut self) -> Result<(), JsValue> {
self.elem.remove_event_listener_with_callback(
self.custom_element.remove_event_listener_with_callback(
"blur",
self.blurhandler
.borrow()
Expand All @@ -236,11 +239,10 @@ where
.unwrap()
.body()
.unwrap()
.remove_child(&self.elem)?;
.remove_child(&self.custom_element)?;


let target = self.target.borrow_mut().take().unwrap();
let event = web_sys::CustomEvent::new("-perspective-close-expression")?;
let event = web_sys::CustomEvent::new("-perspective-close-expression")?;
target.dispatch_event(&event)?;
Ok(())
}
Expand Down
Loading

0 comments on commit 1d4ba84

Please sign in to comment.