Skip to content

Commit

Permalink
Implemented Item Properties View
Browse files Browse the repository at this point in the history
Changes made:

- Uses an theia independent react widget for Properties view from traceviewer-react-components
- Proper signal handling between item properties webview and extension

This will add the Item Properties View to the Trace Viewer.

Fixes eclipse-cdt-cloud#62

Signed-off-by: Neel Gondalia ngondalia@blackberry.com
  • Loading branch information
ngondalia committed Feb 15, 2023
1 parent 57c2f7d commit 0d4f389
Show file tree
Hide file tree
Showing 17 changed files with 218 additions and 23 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2022, BlackBerry Limited.
Copyright (c) 2022, 2023 BlackBerry Limited.
Copyright (c) 2020, 2021 École Polytechnique de Montréal, Ericsson

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down
1 change: 1 addition & 0 deletions vscode-trace-extension/LICENSE
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
MIT License

Copyright (c) 2022, 2023 BlackBerry Limited.
Copyright (c) 2020, 2021 École Polytechnique de Montréal, Ericsson

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down
9 changes: 9 additions & 0 deletions vscode-trace-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@
"type": "webview",
"id": "traceExplorer.availableViews",
"name": "Views"
},
{
"type": "webview",
"id": "traceExplorer.itemPropertiesView",
"name": "Item Properties"
}
]
},
Expand All @@ -63,6 +68,10 @@
{
"view": "views",
"contents": "No trace selected [learn more](https://www.eclipse.org/tracecompass/)"
},
{
"view": "item properties",
"contents": "No properties to show"
}
],
"menus": {
Expand Down
13 changes: 12 additions & 1 deletion vscode-trace-extension/src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use strict';
import * as vscode from 'vscode';
import { AnalysisProvider } from './trace-explorer/analysis-tree';
import { TraceExplorerAvailableViewsProvider } from './trace-explorer/views/trace-explorer-available-views-webview-provider';
import { TraceExplorerItemPropertiesProvider } from './trace-explorer/properties/trace-explorer-properties-view-webview-provider';
import { TraceExplorerAvailableViewsProvider } from './trace-explorer/available-views/trace-explorer-available-views-webview-provider';
import { TraceExplorerOpenedTracesViewProvider } from './trace-explorer/opened-traces/trace-explorer-opened-traces-webview-provider';
import { fileHandler, openOverviewHandler } from './trace-explorer/trace-tree';
import { updateTspClient } from './utils/tspClient';
Expand All @@ -16,6 +17,16 @@ export function activate(context: vscode.ExtensionContext): void {
context.subscriptions.push(
vscode.window.registerWebviewViewProvider(TraceExplorerAvailableViewsProvider.viewType, myAnalysisProvider));

const propertiesProvider = new TraceExplorerItemPropertiesProvider(context.extensionUri);
context.subscriptions.push(
vscode.window.registerWebviewViewProvider(TraceExplorerItemPropertiesProvider.viewType, propertiesProvider));

context.subscriptions.push(vscode.commands.registerCommand('messages.post.propertiespanel', (command: string, data) => {
if (propertiesProvider) {
propertiesProvider.postMessagetoWebview(command, data);
}
}));

const analysisProvider = new AnalysisProvider();
// TODO: For now, a different command opens traces from file explorer. Remove when we have a proper trace finder
const fileOpenHandler = fileHandler(analysisProvider);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/***************************************************************************************
* Copyright (c) 2023 BlackBerry Limited and contributors.
*
* Licensed under the MIT license. See LICENSE file in the project root for details.
***************************************************************************************/
import * as vscode from 'vscode';
import { getTraceServerUrl } from 'vscode-trace-extension/src/utils/tspClient';

export class TraceExplorerItemPropertiesProvider implements vscode.WebviewViewProvider {
public static readonly viewType = 'traceExplorer.itemPropertiesView';
private _view?: vscode.WebviewView;
constructor(private readonly _extensionUri: vscode.Uri) {}

resolveWebviewView(
webviewView: vscode.WebviewView,
_context: vscode.WebviewViewResolveContext,
_token: vscode.CancellationToken
): void {
this._view = webviewView;
webviewView.webview.options = {
// Allow scripts in the webview
enableScripts: true,
localResourceRoots: [vscode.Uri.joinPath(this._extensionUri, 'pack')],
};
webviewView.webview.html = this._getHtmlForWebview(webviewView.webview);
}

postMessagetoWebview(_command: string, _data: unknown): void {
if (this._view && _command && _data) {
this._view.webview.postMessage({command: _command, data: _data});
}
}

/* eslint-disable max-len */
private _getHtmlForWebview(webview: vscode.Webview) {
// Get the local path to main script run in the webview, then convert it to a uri we can use in the webview.
const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'pack', 'propertiesPanel.js'));

// Use a nonce to only allow a specific script to be run.
const nonce = getNonce();

return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<title>React App</title>
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${nonce}' 'unsafe-eval';style-src vscode-resource: 'unsafe-inline' http: https: data:;connect-src ${getTraceServerUrl()};">
<base href="${vscode.Uri.joinPath(this._extensionUri, 'pack').with({ scheme: 'vscode-resource' })}/">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script nonce="${nonce}">
const vscode = acquireVsCodeApi();
</script>
<script nonce="${nonce}" src="${scriptUri}"></script>
</body>
</html>`;
}
}

function getNonce() {
let text = '';
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < 32; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ export class TraceViewerPanel {
this.loadTheme();
}
return;
case 'updateProperties':
vscode.commands.executeCommand('messages.post.propertiespanel', 'receivedProperties', message.data);
}
}, undefined, this._disposables);
signalManager().on(Signals.EXPERIMENT_SELECTED, this._onExperimentSelected);
Expand Down Expand Up @@ -182,8 +184,8 @@ export class TraceViewerPanel {
}

loadTheme(): void {
const wrapper = vscode.window.activeColorTheme.kind == 1 ? 'light' : 'dark';
this._panel.webview.postMessage({ command: 'set-theme', data: wrapper });
const wrapper = vscode.window.activeColorTheme.kind === 1 ? 'light' : 'dark';
this._panel.webview.postMessage({ command: 'set-theme', data: wrapper });
}

private _getHtmlForWebview() {
Expand Down
1 change: 1 addition & 0 deletions vscode-trace-webviews/LICENSE
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
MIT License

Copyright (c) 2022, 2023 BlackBerry Limited.
Copyright (c) 2020, 2021 École Polytechnique de Montréal, Ericsson

Permission is hereby granted, free of charge, to any person obtaining a copy
Expand Down
4 changes: 4 additions & 0 deletions vscode-trace-webviews/src/common/vscode-message-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,8 @@ export class VsCodeMessageManager extends Messages.MessageManager {
const descWrapper = JSONBig.stringify(payload.getOutputDescriptor());
vscode.postMessage({command: 'outputAdded', data: {data: expWrapper, descriptor: descWrapper }});
}

propertiesUpdated(properties: { [key: string]: string }): void {
vscode.postMessage({command: 'updateProperties', data: {properties}});
}
}
5 changes: 5 additions & 0 deletions vscode-trace-webviews/src/trace-explorer/properties/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
14 changes: 14 additions & 0 deletions vscode-trace-webviews/src/trace-explorer/properties/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/***************************************************************************************
* Copyright (c) 2023 BlackBerry Limited and contributors.
*
* Licensed under the MIT license. See LICENSE file in the project root for details.
***************************************************************************************/
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import './index.css';
import TraceExplorerProperties from './vscode-trace-explorer-properties-widget';

ReactDOM.render(
<TraceExplorerProperties />,
(document.getElementById('root') as HTMLElement)
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/***************************************************************************************
* Copyright (c) 2023 BlackBerry Limited and contributors.
*
* Licensed under the MIT license. See LICENSE file in the project root for details.
***************************************************************************************/
/* eslint-disable @typescript-eslint/ban-types */
import React from 'react';
import { VsCodeMessageManager } from 'vscode-trace-webviews/src/common/vscode-message-manager';
import { ReactItemPropertiesWidget } from 'traceviewer-react-components/lib/trace-explorer/trace-explorer-properties-widget';
import { signalManager } from 'traceviewer-base/lib/signals/signal-manager';

interface PropertiesViewState {
properties: { [key: string]: string };
}

class TraceExplorerProperties extends React.Component<{}, PropertiesViewState> {
static ID = 'trace-explorer-properties-widget';
static LABEL = 'Item Properties';
private _signalHandler: VsCodeMessageManager;

constructor(props: {}) {
super(props);
this.state = {
properties: {}
};
this._signalHandler = new VsCodeMessageManager();

window.addEventListener('message', event => {
const message = event.data; // The JSON data our extension sent
switch (message.command) {
case 'receivedProperties':
signalManager().fireItemPropertiesSignalUpdated(message.data.properties);
break;
}
});
}

componentDidMount(): void {
this._signalHandler.notifyReady();
}

public render(): React.ReactNode {
return (
<div>
<ReactItemPropertiesWidget
id={TraceExplorerProperties.ID}
title={TraceExplorerProperties.LABEL}
handleSourcecodeLookup={this.handleSourcecodeLookup}
></ReactItemPropertiesWidget>
</div>
);
}

protected handleSourcecodeLookup = (e: React.MouseEvent<HTMLParagraphElement>): void => this.doHandleSourcecodeLookup(e);

private doHandleSourcecodeLookup(e: React.MouseEvent<HTMLParagraphElement>) {
const { fileLocation, line }: { fileLocation: string, line: string } = JSON.parse(`${e.currentTarget.getAttribute('data-id')}`);
console.log('filename: ' + fileLocation + ':' + line);
console.log('Source lookup method not implemented');
}

}

export default TraceExplorerProperties;
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ class App extends React.Component<{}, VscodeAppState> {

private _signalHandler: VsCodeMessageManager;

private _onProperties = (properties: { [key: string]: string }): void => this.doHandlePropertiesSignal(properties);
/** Signal Handlers */
private doHandlePropertiesSignal(properties: { [key: string]: string }) {
this._signalHandler.propertiesUpdated(properties);
}

// TODO add support for marker sets
private selectedMarkerCategoriesMap: Map<string, string[]> = new Map<string, string[]>();
private selectedMarkerSetId = '';
Expand Down Expand Up @@ -93,16 +99,18 @@ class App extends React.Component<{}, VscodeAppState> {

componentDidMount(): void {
this._signalHandler.notifyReady();
signalManager().on(Signals.ITEM_PROPERTIES_UPDATED, this._onProperties);
}

componentWillUnmount(): void {
signalManager().off(Signals.ITEM_PROPERTIES_UPDATED, this._onProperties);
signalManager().off(Signals.OVERVIEW_OUTPUT_SELECTED, this._onOverviewSelected);
window.removeEventListener('resize', this.onResize);
}

private onResize = (): void => {
this.resizeHandlers.forEach(h => h());
}
this.resizeHandlers.forEach(h => h());
};

private onOutputRemoved(outputId: string) {
const outputToKeep = this.state.outputs.filter(output => output.id !== outputId);
Expand Down
37 changes: 20 additions & 17 deletions vscode-trace-webviews/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ module.exports = {
entry: {
trace_panel: "./src/trace-viewer/index.tsx",
openedTracesPanel: "./src/trace-explorer/opened-traces/index.tsx",
analysisPanel: "./src/trace-explorer/views/index.tsx"
analysisPanel: "./src/trace-explorer/available-views/index.tsx",
propertiesPanel: "./src/trace-explorer/properties/index.tsx"
},
output: {
path: path.resolve(__dirname, "../vscode-trace-extension/pack"),
Expand All @@ -21,19 +22,21 @@ module.exports = {
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: [{
loader: 'ts-loader',
use: [
{
loader: "ts-loader",
options: {
compilerOptions: {
"module": "es6" // override `tsconfig.json` so that TypeScript emits native JavaScript modules.
}
compilerOptions: {
module: "es6" // override `tsconfig.json` so that TypeScript emits native JavaScript modules.
}
}
}]
}
]
},
{
test: /\.js$/,
enforce: 'pre',
use: ['source-map-loader'],
enforce: "pre",
use: ["source-map-loader"]
},
{
test: /\.css$/,
Expand All @@ -50,22 +53,22 @@ module.exports = {
test: /\.svg$/,
use: [
{
loader: 'svg-url-loader',
loader: "svg-url-loader",
options: {
limit: 10000,
},
},
],
limit: 10000
}
}
]
}
]
},
performance: {
hints: false
},
plugins: [
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development')
"process.env": {
NODE_ENV: JSON.stringify(process.env.NODE_ENV || "development")
}
}),
new webpack.HotModuleReplacementPlugin()
Expand Down

0 comments on commit 0d4f389

Please # to comment.