Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

PerspectiveWorkspace React component#3044

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Draft
sinistersnare wants to merge2 commits intoperspective-dev:master
base:master
Choose a base branch
Loading
fromsinistersnare:feature/react-workspace

Conversation

@sinistersnare
Copy link
Contributor

@sinistersnaresinistersnare commentedJul 29, 2025
edited
Loading

Hello! This PR adds onto ourperspective-react package an API for the<perspective-workspace> custom element in the form of a<PerspectiveWorkspace /> React component. You can use it as such:

import*asWorkspacefrom"@finos/perspective-workspace";consttables={a:client.table("a,b,c\n1,2,3\n4,5,6",{name:"a"})};constbase={sizes:[1],detail:{main:null},viewers:{});constid=Workspace.genId(base);constlayout=Workspace.addViewer(base,{table:"a",title:"View A!"},id);<PerspectiveWorkspacetables={tables}layout={layout}/>

You can see that this PR also adds some free functions (namelyaddViewer andgenId) to assist in the functional style of React.

There are also callbacks that can be passed for theon-layout-update andon-new-view events.

ThePerspectiveWorkspaceConfig interface was updated to better reflect the reality of the current workspace structure.

During the course of this, I encountered a bug of an internal engine message not being swallowed by the engine. That bug is tracked in#3039.

texodus, aszenz, and ahirner reacted with rocket emoji
@sinistersnaresinistersnareforce-pushed thefeature/react-workspace branch 3 times, most recently from90b0462 tob60ab32CompareJuly 29, 2025 18:18
widget:pspWorkspace.PerspectiveViewerWidget;
isGlobalFilter:boolean;
})=>void;
id?:string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

UseReact.HTMLAttributes

sinistersnare reacted with thumbs up emoji
PerspectiveWorkspace,
}from"@finos/perspective-react";

import"@finos/perspective-viewer/dist/css/themes.css";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Don't importthemes.css for viewers within a workspace - use the specific themepro.css (in this case)

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This is for the<PerspectiveViewer /> tests,<PerspectiveWorkspace /> tests usedthemes.css as well though so I removed that line.

awaitnewPromise((r)=>setTimeout(r,delay));
}
returnfalse;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

If every one of Perspective's tests did this, the test suite would run ~2hrs. You have multiple options available:

  • Listen forperspective-config-update
  • Remove the button click from the tests and just await the workspace calls directly (through an imperative handlefor testing only).
  • Awaitworkspace.flush()

master:{sizes:[]},
detail:{sizes:[]},
master:undefined,
detail:{main:null},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This does not look right

sinistersnare reacted with thumbs up emoji
};
}

exportfunctiongenId(workspace:PerspectiveWorkspaceConfig){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Please remove this - IDs are an internal implementation detail, there is no reason to expose this in the public API.

sinistersnare reacted with thumbs up emoji
constexists=document.querySelector("body > perspective-indicator");
if(exists){
returnexistsasHTMLElement;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This smells like a previous<perspective-workspace> that was disconnected leaked this element, not the responsibility of this method to correct.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Sure, I set the constructed indicator to be a child of<perspective-workspace> so that the element is cleaned up when the workspace is unmounted.

}

exportinterfacePerspectiveWorkspaceConfig<T>{
// TODO: I have made some changes to this interface because it seemed to not reflect reality.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Lumino'sDockPanel.saveLayout() does not return string identifiers forwidgets field, ergo the types for e.g.workspace.save() is now notPerspectiveWorkspaceConfig (it's an anonymous struct type). Add the explicit returns types tosave() will show this error.

sinistersnare reacted with thumbs up emoji
if(!newTables[t]){
awaitviewer.eject();
}else{
awaitviewer.load(newTables[t]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Please batch these and await them all at the end usingPromise.all(), so the user does not have to watch a slide show of these elements updating.

sinistersnare reacted with thumbs up emoji
asyncrestore(value:PerspectiveWorkspaceConfig<string>){
asyncrestore(value:PerspectiveWorkspaceConfig){
// bail out early if there is nothing to restore.
constlayout=awaitthis.save();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Why is this necessary? This operation is not free and bothperspective-viewer and luminoDockPanel should do this internally already.

sinistersnare reacted with thumbs up emoji

interfacePerspectiveWorkspaceProps{
tables:Record<string,Promise<psp.Table>>;
layout:PerspectiveWorkspaceConfig;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This is called aconfig in the API docs, examples and the type name itself.Layout is the type of thelayout field within this struct.

sinistersnare reacted with thumbs up emoji
if(viewer){
widget=starting_widgets.find((x)=>x.viewer===viewer);
if(widget){
console.warn("DDD Restore load??? ");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

stray debug print

this.getAllWidgets().forEach((widget)=>{
constpsp_widget=widgetasPerspectiveViewerWidget;
if(psp_widget.viewer.getAttribute("table")===name){
console.warn("DDD Loading...?",table);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

stray debug print

constwidget=newPerspectiveViewerWidget({ node, viewer});
widget.task=(async()=>{
if(table){
console.warn("DDD Loading B?",table);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

stray debug print

@@ -0,0 +1,38 @@
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
Copy link
Contributor

@tomjakubowskitomjakubowskiAug 26, 2025
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

if this workspace-repro example is to repro a bug case, I imagine you want to remove this for the final PR

@sinistersnaresinistersnare marked this pull request as draftAugust 27, 2025 17:47
tomjakubowskiand others added2 commitsAugust 28, 2025 11:44
The ObservableMap's delete listener used to be able to "reject"deletions by returning false.  This is no longer the case; the listenerin Workspace always returns undefined now.  Account for this inobservable map's delete method.Co-authored by: Davis Silverman <davis@prospective.dev>Signed-off-by: Tom Jakubowski <tom@prospective.dev>
Signed-off-by: Davis Silverman <davis@thedav.is>
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@texodustexodustexodus left review comments

@tomjakubowskitomjakubowskitomjakubowski left review comments

At least 1 approving review is required to merge this pull request.

Assignees

No one assigned

Labels

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

3 participants

@sinistersnare@texodus@tomjakubowski

[8]ページ先頭

©2009-2025 Movatter.jp