Add a data grid control and the infrastructure to support it (#4847)
* Initial layout * tabulator and react-data-grid * Implement sorting/filtering/row rendering * Switch to just AdazzleReactDataGrid * Merge data explorer config into original * Fix compilation of webview * Data Explorer coming up * Semi working grid * Use bootstrap to handle correct themeing * Fix styles and layout * Fixup themes for hover and fix title * Fix check datascience dependencies * Fix webpack for packaging * Fix hygiene * Add news entry * Fix webview compile error caused by hygiene changes * Put contributing back to what it was before. * Fix functional tests * Fix dispose to set disposed flag.
This commit is contained in:
Родитель
0268ef41f6
Коммит
0b01e95206
|
@ -29,7 +29,7 @@ typings.json
|
|||
vsc-extension-quickstart.md
|
||||
vscode-python-signing.*
|
||||
webpack.config.js
|
||||
webpack.datascience-ui.config.js
|
||||
webpack.datascience-*.config.js
|
||||
|
||||
.github/**
|
||||
.mocha-reporter/**
|
||||
|
|
58
gulpfile.js
58
gulpfile.js
|
@ -332,36 +332,38 @@ async function checkDatascienceDependencies() {
|
|||
if (modulesInPackageLock.some(dependency => dependency.indexOf('/') !== dependency.lastIndexOf('/'))) {
|
||||
throwAndLogError('Dependencies detected with more than one \'/\', please update this script.');
|
||||
}
|
||||
json.chunks[0].modules.forEach(m => {
|
||||
const name = m.name;
|
||||
if (!name.startsWith('./node_modules')) {
|
||||
return;
|
||||
}
|
||||
const nameWithoutNodeModules = name.substring('./node_modules'.length);
|
||||
let moduleName1 = nameWithoutNodeModules.split('/')[1];
|
||||
moduleName1 = moduleName1.endsWith('!.') ? moduleName1.substring(0, moduleName1.length - 2) : moduleName1;
|
||||
const moduleName2 = `${nameWithoutNodeModules.split('/')[1]}/${nameWithoutNodeModules.split('/')[2]}`;
|
||||
|
||||
const matchedModules = modulesInPackageLock.filter(dependency => dependency === moduleName2 || dependency === moduleName1);
|
||||
switch (matchedModules.length) {
|
||||
case 0:
|
||||
throwAndLogError(`Dependency not found in package-lock.json, Dependency = '${name}, ${moduleName1}, ${moduleName2}'`);
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
default: {
|
||||
throwAndLogError(`Exact Dependency not found in package-lock.json, Dependency = '${name}'`);
|
||||
json.children.forEach(c => {
|
||||
c.chunks[0].modules.forEach(m => {
|
||||
const name = m.name;
|
||||
if (!name.startsWith('./node_modules')) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const nameWithoutNodeModules = name.substring('./node_modules'.length);
|
||||
let moduleName1 = nameWithoutNodeModules.split('/')[1];
|
||||
moduleName1 = moduleName1.endsWith('!.') ? moduleName1.substring(0, moduleName1.length - 2) : moduleName1;
|
||||
const moduleName2 = `${nameWithoutNodeModules.split('/')[1]}/${nameWithoutNodeModules.split('/')[2]}`;
|
||||
|
||||
const moduleName = matchedModules[0];
|
||||
if (existingModulesCopy.has(moduleName)) {
|
||||
existingModulesCopy.delete(moduleName);
|
||||
}
|
||||
if (existingModules.has(moduleName) || newModules.has(moduleName)) {
|
||||
return;
|
||||
}
|
||||
newModules.add(moduleName);
|
||||
const matchedModules = modulesInPackageLock.filter(dependency => dependency === moduleName2 || dependency === moduleName1);
|
||||
switch (matchedModules.length) {
|
||||
case 0:
|
||||
throwAndLogError(`Dependency not found in package-lock.json, Dependency = '${name}, ${moduleName1}, ${moduleName2}'`);
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
default: {
|
||||
throwAndLogError(`Exact Dependency not found in package-lock.json, Dependency = '${name}'`);
|
||||
}
|
||||
}
|
||||
|
||||
const moduleName = matchedModules[0];
|
||||
if (existingModulesCopy.has(moduleName)) {
|
||||
existingModulesCopy.delete(moduleName);
|
||||
}
|
||||
if (existingModules.has(moduleName) || newModules.has(moduleName)) {
|
||||
return;
|
||||
}
|
||||
newModules.add(moduleName);
|
||||
});
|
||||
});
|
||||
|
||||
const errorMessages = [];
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Add a data grid control and web view panel.
|
|
@ -3055,6 +3055,12 @@
|
|||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
|
||||
"dev": true
|
||||
},
|
||||
"bootstrap": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.3.1.tgz",
|
||||
"integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
|
@ -8226,6 +8232,12 @@
|
|||
"integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
|
||||
"dev": true
|
||||
},
|
||||
"immutable": {
|
||||
"version": "4.0.0-rc.12",
|
||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz",
|
||||
"integrity": "sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A==",
|
||||
"dev": true
|
||||
},
|
||||
"import-local": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
|
||||
|
@ -12767,6 +12779,18 @@
|
|||
"tinycolor2": "^1.4.1"
|
||||
}
|
||||
},
|
||||
"react-data-grid": {
|
||||
"version": "6.0.2-0",
|
||||
"resolved": "https://registry.npmjs.org/react-data-grid/-/react-data-grid-6.0.2-0.tgz",
|
||||
"integrity": "sha512-OiE/EevjV70J60OGj2Pcy8P3uRQGvyD0Ata2NbXjE2rKOGUuJ7hau8WcvIFhAMP005LEV+pfqzZpkIYjD1u3OQ==",
|
||||
"dev": true
|
||||
},
|
||||
"react-data-grid-addons": {
|
||||
"version": "6.0.2-0",
|
||||
"resolved": "https://registry.npmjs.org/react-data-grid-addons/-/react-data-grid-addons-6.0.2-0.tgz",
|
||||
"integrity": "sha512-0GXbjMyBrXzQuQOSPltFS7XX4EzODf+THNAXdAIKJvN5nYLW/xyaKbkHnA/X8ydYkwDedYpNV1bHbYJeooViCw==",
|
||||
"dev": true
|
||||
},
|
||||
"react-dev-utils": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-5.0.2.tgz",
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"bail",
|
||||
"base16",
|
||||
"bintrees",
|
||||
"bootstrap",
|
||||
"character-entities-legacy",
|
||||
"character-reference-invalid",
|
||||
"classnames",
|
||||
|
@ -66,6 +67,7 @@
|
|||
"extend",
|
||||
"fbjs",
|
||||
"flat",
|
||||
"immutable",
|
||||
"inherits",
|
||||
"is-alphabetical",
|
||||
"is-alphanumerical",
|
||||
|
@ -106,6 +108,8 @@
|
|||
"react-base16-styling",
|
||||
"react-codemirror",
|
||||
"react-color",
|
||||
"react-data-grid",
|
||||
"react-data-grid-addons",
|
||||
"react-dom",
|
||||
"react-hot-loader",
|
||||
"react-json-tree",
|
||||
|
|
|
@ -2330,6 +2330,7 @@
|
|||
"babel-plugin-inline-json-import": "^0.3.1",
|
||||
"babel-plugin-transform-runtime": "^6.23.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"bootstrap": "^4.3.1",
|
||||
"chai": "^4.1.2",
|
||||
"chai-arrays": "^2.0.0",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
|
@ -2356,6 +2357,7 @@
|
|||
"gulp-typescript": "^4.0.1",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"husky": "^1.1.2",
|
||||
"immutable": "^4.0.0-rc.12",
|
||||
"is-running": "^2.1.0",
|
||||
"istanbul": "^0.4.5",
|
||||
"jsdom": "^12.2.0",
|
||||
|
@ -2368,6 +2370,8 @@
|
|||
"raw-loader": "^0.5.1",
|
||||
"react": "^16.5.2",
|
||||
"react-codemirror": "^1.0.0",
|
||||
"react-data-grid": "^6.0.2-0",
|
||||
"react-data-grid-addons": "^6.0.2-0",
|
||||
"react-dev-utils": "^5.0.2",
|
||||
"react-dom": "^16.5.2",
|
||||
"react-json-tree": "^0.11.0",
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
"LanguageService.lsFailedToExtract": "We encountered an issue extracting the Language Server. Reverting to the alternative, Jedi. Check the Python output panel for details.",
|
||||
"DataScience.unknownMimeTypeFormat": "Mime type {0} is not currently supported.",
|
||||
"DataScience.historyTitle": "Python Interactive",
|
||||
"DataScience.dataExplorerTitle": "Data Viewer",
|
||||
"DataScience.badWebPanelFormatString": "<html><body><h1>{0} is not a valid file name</h1></body></html>",
|
||||
"DataScience.sessionDisposed": "Cannot execute code, session has been disposed.",
|
||||
"DataScience.exportDialogTitle": "Export to Jupyter Notebook",
|
||||
|
|
|
@ -877,7 +877,7 @@ export interface IWebPanelProvider {
|
|||
* @param: mainScriptPath: full path in the output folder to the script
|
||||
* @return A IWebPanel that can be used to show html pages.
|
||||
*/
|
||||
create(listener: IWebPanelMessageListener, title: string, mainScriptPath: string, embeddedCss?: string, settings?: any): IWebPanel;
|
||||
create(viewColumn: ViewColumn, listener: IWebPanelMessageListener, title: string, mainScriptPath: string, embeddedCss?: string, settings?: any): IWebPanel;
|
||||
}
|
||||
|
||||
// Wraps the vsls liveshare API
|
||||
|
|
|
@ -22,6 +22,7 @@ export class WebPanel implements IWebPanel {
|
|||
private rootPath: string;
|
||||
|
||||
constructor(
|
||||
viewColumn: ViewColumn,
|
||||
serviceContainer: IServiceContainer,
|
||||
listener: IWebPanelMessageListener,
|
||||
title: string,
|
||||
|
@ -35,7 +36,7 @@ export class WebPanel implements IWebPanel {
|
|||
this.panel = window.createWebviewPanel(
|
||||
title.toLowerCase().replace(' ', ''),
|
||||
title,
|
||||
{viewColumn: ViewColumn.Two, preserveFocus: true},
|
||||
{viewColumn , preserveFocus: true},
|
||||
{
|
||||
enableScripts: true,
|
||||
retainContextWhenHidden: true,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the MIT License.
|
||||
'use strict';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { ViewColumn } from 'vscode';
|
||||
|
||||
import { IServiceContainer } from '../../ioc/types';
|
||||
import { IWebPanel, IWebPanelMessageListener, IWebPanelProvider } from './types';
|
||||
|
@ -13,7 +14,7 @@ export class WebPanelProvider implements IWebPanelProvider {
|
|||
}
|
||||
|
||||
// tslint:disable-next-line:no-any
|
||||
public create(listener: IWebPanelMessageListener, title: string, mainScriptPath: string, embeddedCss?: string, settings?: any) : IWebPanel {
|
||||
return new WebPanel(this.serviceContainer, listener, title, mainScriptPath, embeddedCss, settings);
|
||||
public create(viewColumn: ViewColumn, listener: IWebPanelMessageListener, title: string, mainScriptPath: string, embeddedCss?: string, settings?: any) : IWebPanel {
|
||||
return new WebPanel(viewColumn, this.serviceContainer, listener, title, mainScriptPath, embeddedCss, settings);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ export namespace DataScienceSurveyBanner {
|
|||
|
||||
export namespace DataScience {
|
||||
export const historyTitle = localize('DataScience.historyTitle', 'Python Interactive');
|
||||
export const dataExplorerTitle = localize('DataScience.dataExplorerTitle', 'Data Viewer');
|
||||
export const badWebPanelFormatString = localize('DataScience.badWebPanelFormatString', '<html><body><h1>{0} is not a valid file name</h1></body></html>');
|
||||
export const sessionDisposed = localize('DataScience.sessionDisposed', 'Cannot execute code, session has been disposed.');
|
||||
export const unknownMimeTypeFormat = localize('DataScience.unknownMimeTypeFormat', 'Mime type {0} is not currently supported');
|
||||
|
|
|
@ -90,7 +90,8 @@ export enum Telemetry {
|
|||
ConnectRemoteFailedJupyter = 'DATASCIENCE.CONNECTREMOTEFAILEDJUPYTER',
|
||||
RemoteAddCode = 'DATASCIENCE.LIVESHARE.ADDCODE',
|
||||
ShiftEnterBannerShown = 'DATASCIENCE.SHIFTENTER_BANNER_SHOWN',
|
||||
EnableInteractiveShiftEnter = 'DATASCIENCE.ENABLE_INTERACTIVE_SHIFT_ENTER'
|
||||
EnableInteractiveShiftEnter = 'DATASCIENCE.ENABLE_INTERACTIVE_SHIFT_ENTER',
|
||||
ShowDataExplorer = 'DATASCIENCE.SHOW_DATA_EXPLORER'
|
||||
}
|
||||
|
||||
export namespace HelpLinks {
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
'use strict';
|
||||
import '../../common/extensions';
|
||||
|
||||
import { inject, injectable } from 'inversify';
|
||||
import * as path from 'path';
|
||||
import { ViewColumn } from 'vscode';
|
||||
|
||||
import { IWebPanel, IWebPanelProvider, IWorkspaceService } from '../../common/application/types';
|
||||
import { EXTENSION_ROOT_DIR } from '../../common/constants';
|
||||
import { IAsyncDisposable, IConfigurationService, IDisposable, ILogger } from '../../common/types';
|
||||
import { createDeferred, Deferred } from '../../common/utils/async';
|
||||
import * as localize from '../../common/utils/localize';
|
||||
import { sendTelemetryEvent } from '../../telemetry';
|
||||
import { Telemetry } from '../constants';
|
||||
import { ICodeCssGenerator, IDataExplorer, IDataExplorerRow, IDataScienceExtraSettings } from '../types';
|
||||
import { DataExplorerMessageListener } from './dataExplorerMessageListener';
|
||||
import { DataExplorerMessages, IDataExplorerMapping } from './types';
|
||||
|
||||
@injectable()
|
||||
export class DataExplorer implements IDataExplorer, IAsyncDisposable {
|
||||
private disposed: boolean = false;
|
||||
private webPanel: IWebPanel | undefined;
|
||||
private webPanelInit: Deferred<void>;
|
||||
private loadPromise: Promise<void>;
|
||||
private messageListener : DataExplorerMessageListener;
|
||||
private changeHandler: IDisposable | undefined;
|
||||
private viewState : { visible: boolean; active: boolean } = { visible: false, active: false };
|
||||
|
||||
constructor(
|
||||
@inject(IWebPanelProvider) private provider: IWebPanelProvider,
|
||||
@inject(IConfigurationService) private configuration: IConfigurationService,
|
||||
@inject(ICodeCssGenerator) private cssGenerator: ICodeCssGenerator,
|
||||
@inject(IWorkspaceService) private workspaceService: IWorkspaceService,
|
||||
@inject(ILogger) private logger: ILogger
|
||||
) {
|
||||
this.changeHandler = this.configuration.getSettings().onDidChange(this.onSettingsChanged.bind(this));
|
||||
|
||||
// Create a message listener to listen to messages from our webpanel (or remote session)
|
||||
this.messageListener = new DataExplorerMessageListener(this.onMessage, this.onViewStateChanged, this.dispose);
|
||||
|
||||
// Setup our init promise for the web panel. We use this to make sure we're in sync with our
|
||||
// react control.
|
||||
this.webPanelInit = createDeferred();
|
||||
|
||||
// Load on a background thread.
|
||||
this.loadPromise = this.loadWebPanel();
|
||||
}
|
||||
|
||||
public get ready() : Promise<void> {
|
||||
// We need this to ensure the history window is up and ready to receive messages.
|
||||
return this.loadPromise;
|
||||
}
|
||||
|
||||
public async show(rows: IDataExplorerRow[]): Promise<void> {
|
||||
if (!this.disposed) {
|
||||
// Make sure we're loaded first
|
||||
await this.loadPromise;
|
||||
|
||||
// Then show our web panel. Eventually we need to consume the data
|
||||
if (this.webPanel) {
|
||||
await this.webPanel.show(true);
|
||||
|
||||
// Send telemetry when it works.
|
||||
sendTelemetryEvent(Telemetry.ShowDataExplorer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public dispose = async () => {
|
||||
if (!this.disposed) {
|
||||
this.disposed = true;
|
||||
if (this.webPanel) {
|
||||
this.webPanel.close();
|
||||
this.webPanel = undefined;
|
||||
}
|
||||
if (this.changeHandler) {
|
||||
this.changeHandler.dispose();
|
||||
this.changeHandler = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async postMessage<M extends IDataExplorerMapping, T extends keyof M>(type: T, payload?: M[T]) : Promise<void> {
|
||||
if (this.webPanel) {
|
||||
// Make sure the webpanel is up before we send it anything.
|
||||
await this.webPanelInit.promise;
|
||||
|
||||
// Then send it the message
|
||||
this.webPanel.postMessage({ type: type.toString(), payload: payload });
|
||||
}
|
||||
}
|
||||
|
||||
// tslint:disable-next-line: no-any no-empty
|
||||
private onMessage = (message: string, payload: any) => {
|
||||
switch (message) {
|
||||
case DataExplorerMessages.Started:
|
||||
this.webPanelRendered();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private onViewStateChanged = (webPanel: IWebPanel) => {
|
||||
this.viewState.active = webPanel.isActive();
|
||||
this.viewState.visible = webPanel.isVisible();
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-any
|
||||
private webPanelRendered() {
|
||||
if (!this.webPanelInit.resolved) {
|
||||
this.webPanelInit.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
// Post a message to our webpanel and update our new datascience settings
|
||||
private onSettingsChanged = () => {
|
||||
// Stringify our settings to send over to the panel
|
||||
const dsSettings = JSON.stringify(this.generateDataScienceExtraSettings());
|
||||
this.postMessage(DataExplorerMessages.UpdateSettings, dsSettings).ignoreErrors();
|
||||
}
|
||||
|
||||
private generateDataScienceExtraSettings() : IDataScienceExtraSettings {
|
||||
const terminal = this.workspaceService.getConfiguration('terminal');
|
||||
const terminalCursor = terminal ? terminal.get<string>('integrated.cursorStyle', 'block') : 'block';
|
||||
return {
|
||||
...this.configuration.getSettings().datascience,
|
||||
extraSettings: {
|
||||
terminalCursor: terminalCursor
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private loadWebPanel = async (): Promise<void> => {
|
||||
this.logger.logInformation(`Loading web panel. Panel is ${this.webPanel ? 'set' : 'notset'}`);
|
||||
|
||||
// Create our web panel (it's the UI that shows up for the history)
|
||||
if (this.webPanel === undefined) {
|
||||
// Figure out the name of our main bundle. Should be in our output directory
|
||||
const mainScriptPath = path.join(EXTENSION_ROOT_DIR, 'out', 'datascience-ui', 'data-explorer', 'index_bundle.js');
|
||||
|
||||
this.logger.logInformation('Generating CSS...');
|
||||
// Generate a css to put into the webpanel for viewing code
|
||||
const css = await this.cssGenerator.generateThemeCss();
|
||||
|
||||
// Get our settings to pass along to the react control
|
||||
const settings = this.generateDataScienceExtraSettings();
|
||||
|
||||
this.logger.logInformation('Loading web view...');
|
||||
// Use this script to create our web view panel. It should contain all of the necessary
|
||||
// script to communicate with this class.
|
||||
this.webPanel = this.provider.create(ViewColumn.One, this.messageListener, localize.DataScience.dataExplorerTitle(), mainScriptPath, css, settings);
|
||||
|
||||
this.logger.logInformation('Web view created.');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
'use strict';
|
||||
import '../../common/extensions';
|
||||
|
||||
import { IWebPanel, IWebPanelMessageListener } from '../../common/application/types';
|
||||
|
||||
// tslint:disable:no-any
|
||||
|
||||
// This class listens to messages that come from the local Data Explorer window
|
||||
export class DataExplorerMessageListener implements IWebPanelMessageListener {
|
||||
private disposedCallback : () => void;
|
||||
private callback : (message: string, payload: any) => void;
|
||||
private viewChanged: (panel: IWebPanel) => void;
|
||||
|
||||
constructor(callback: (message: string, payload: any) => void, viewChanged: (panel: IWebPanel) => void, disposed: () => void) {
|
||||
|
||||
// Save our dispose callback so we remove our history window
|
||||
this.disposedCallback = disposed;
|
||||
|
||||
// Save our local callback so we can handle the non broadcast case(s)
|
||||
this.callback = callback;
|
||||
|
||||
// Save view changed so we can forward view change events.
|
||||
this.viewChanged = viewChanged;
|
||||
}
|
||||
|
||||
public async dispose() {
|
||||
this.disposedCallback();
|
||||
}
|
||||
|
||||
public onMessage(message: string, payload: any) {
|
||||
// Send to just our local callback.
|
||||
this.callback(message, payload);
|
||||
}
|
||||
|
||||
public onChangeViewState(panel: IWebPanel) {
|
||||
// Forward this onto our callback
|
||||
if (this.viewChanged) {
|
||||
this.viewChanged(panel);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
'use strict';
|
||||
import { inject, injectable } from 'inversify';
|
||||
|
||||
import { IAsyncDisposable, IAsyncDisposableRegistry } from '../../common/types';
|
||||
import { IServiceContainer } from '../../ioc/types';
|
||||
import { IDataExplorer, IDataExplorerProvider, IDataExplorerRow } from '../types';
|
||||
|
||||
@injectable()
|
||||
export class DataExplorerProvider implements IDataExplorerProvider, IAsyncDisposable {
|
||||
|
||||
private activeExplorers: IDataExplorer[] = [];
|
||||
constructor(
|
||||
@inject(IServiceContainer) private serviceContainer: IServiceContainer,
|
||||
@inject(IAsyncDisposableRegistry) asyncRegistry : IAsyncDisposableRegistry
|
||||
) {
|
||||
asyncRegistry.push(this);
|
||||
}
|
||||
|
||||
public async dispose() {
|
||||
await Promise.all(this.activeExplorers.map(d => d.dispose()));
|
||||
}
|
||||
|
||||
public async create(rows: IDataExplorerRow[]) : Promise<IDataExplorer>{
|
||||
const dataExplorer = this.serviceContainer.get<IDataExplorer>(IDataExplorer);
|
||||
this.activeExplorers.push(dataExplorer);
|
||||
await dataExplorer.show(rows);
|
||||
return dataExplorer;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
'use strict';
|
||||
|
||||
export namespace DataExplorerMessages {
|
||||
export const Started = 'started';
|
||||
export const UpdateSettings = 'update_settings';
|
||||
}
|
||||
|
||||
// Map all messages to specific payloads
|
||||
export class IDataExplorerMapping {
|
||||
public [DataExplorerMessages.Started]: never | undefined;
|
||||
public [DataExplorerMessages.UpdateSettings]: string;
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
'use strict';
|
||||
import '../common/extensions';
|
||||
import '../../common/extensions';
|
||||
|
||||
import * as fs from 'fs-extra';
|
||||
import { inject, injectable } from 'inversify';
|
||||
|
@ -19,20 +19,20 @@ import {
|
|||
IWebPanel,
|
||||
IWebPanelProvider,
|
||||
IWorkspaceService
|
||||
} from '../common/application/types';
|
||||
import { CancellationError } from '../common/cancellation';
|
||||
import { EXTENSION_ROOT_DIR } from '../common/constants';
|
||||
import { ContextKey } from '../common/contextKey';
|
||||
import { IFileSystem } from '../common/platform/types';
|
||||
import { IConfigurationService, IDisposable, IDisposableRegistry, ILogger } from '../common/types';
|
||||
import { createDeferred, Deferred } from '../common/utils/async';
|
||||
import * as localize from '../common/utils/localize';
|
||||
import { IInterpreterService, PythonInterpreter } from '../interpreter/contracts';
|
||||
import { captureTelemetry, sendTelemetryEvent } from '../telemetry';
|
||||
import { EditorContexts, Identifiers, Telemetry } from './constants';
|
||||
} from '../../common/application/types';
|
||||
import { CancellationError } from '../../common/cancellation';
|
||||
import { EXTENSION_ROOT_DIR } from '../../common/constants';
|
||||
import { ContextKey } from '../../common/contextKey';
|
||||
import { IFileSystem } from '../../common/platform/types';
|
||||
import { IConfigurationService, IDisposable, IDisposableRegistry, ILogger } from '../../common/types';
|
||||
import { createDeferred, Deferred } from '../../common/utils/async';
|
||||
import * as localize from '../../common/utils/localize';
|
||||
import { IInterpreterService, PythonInterpreter } from '../../interpreter/contracts';
|
||||
import { captureTelemetry, sendTelemetryEvent } from '../../telemetry';
|
||||
import { EditorContexts, Identifiers, Telemetry } from '../constants';
|
||||
import { HistoryMessageListener } from './historyMessageListener';
|
||||
import { HistoryMessages, IAddedSysInfo, IGotoCode, IHistoryMapping, IRemoteAddCode, ISubmitNewCell } from './historyTypes';
|
||||
import { JupyterInstallError } from './jupyter/jupyterInstallError';
|
||||
import { JupyterInstallError } from '../jupyter/jupyterInstallError';
|
||||
import {
|
||||
CellState,
|
||||
ICell,
|
||||
|
@ -46,8 +46,9 @@ import {
|
|||
INotebookExporter,
|
||||
INotebookServer,
|
||||
InterruptResult,
|
||||
IStatusProvider
|
||||
} from './types';
|
||||
IStatusProvider,
|
||||
IDataExplorerProvider
|
||||
} from '../types';
|
||||
|
||||
export enum SysInfoReason {
|
||||
Start,
|
||||
|
@ -92,7 +93,8 @@ export class History implements IHistory {
|
|||
@inject(ICommandManager) private commandManager: ICommandManager,
|
||||
@inject(INotebookExporter) private jupyterExporter: INotebookExporter,
|
||||
@inject(IWorkspaceService) private workspaceService: IWorkspaceService,
|
||||
@inject(IHistoryProvider) private historyProvider: IHistoryProvider
|
||||
@inject(IHistoryProvider) private historyProvider: IHistoryProvider,
|
||||
@inject(IDataExplorerProvider) private dataExplorerProvider: IDataExplorerProvider
|
||||
) {
|
||||
|
||||
// Create our unique id. We use this to skip messages we send to other history windows
|
||||
|
@ -235,6 +237,10 @@ export class History implements IHistory {
|
|||
this.dispatchMessage(message, payload, this.onRemoteAddedCode);
|
||||
break;
|
||||
|
||||
case HistoryMessages.ShowDataExplorer:
|
||||
this.showDataExplorer();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -350,6 +356,14 @@ export class History implements IHistory {
|
|||
}
|
||||
}
|
||||
|
||||
private async showDataExplorer() {
|
||||
try {
|
||||
return this.dataExplorerProvider.create([]);
|
||||
} catch (e) {
|
||||
this.applicationShell.showErrorMessage(e);
|
||||
}
|
||||
}
|
||||
|
||||
private onViewStateChanged = (webPanel: IWebPanel) => {
|
||||
const oldActive = this.viewState.active;
|
||||
this.viewState.active = webPanel.isActive();
|
||||
|
@ -881,7 +895,7 @@ export class History implements IHistory {
|
|||
this.logger.logInformation('Loading web view...');
|
||||
// Use this script to create our web view panel. It should contain all of the necessary
|
||||
// script to communicate with this class.
|
||||
this.webPanel = this.provider.create(this.messageListener, localize.DataScience.historyTitle(), mainScriptPath, css, settings);
|
||||
this.webPanel = this.provider.create(ViewColumn.Two, this.messageListener, localize.DataScience.historyTitle(), mainScriptPath, css, settings);
|
||||
|
||||
this.logger.logInformation('Web view created.');
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
'use strict';
|
||||
import '../common/extensions';
|
||||
import '../../common/extensions';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as vsls from 'vsls/vscode';
|
||||
|
||||
import { ILiveShareApi, IWebPanel, IWebPanelMessageListener } from '../common/application/types';
|
||||
import { Identifiers, LiveShare } from './constants';
|
||||
import { ILiveShareApi, IWebPanel, IWebPanelMessageListener } from '../../common/application/types';
|
||||
import { Identifiers, LiveShare } from '../constants';
|
||||
import { HistoryMessages, HistoryRemoteMessages } from './historyTypes';
|
||||
import { PostOffice } from './liveshare/postOffice';
|
||||
import { PostOffice } from '../liveshare/postOffice';
|
||||
|
||||
// tslint:disable:no-any
|
||||
|
|
@ -6,13 +6,13 @@ import * as uuid from 'uuid/v4';
|
|||
import { Disposable, Event, EventEmitter } from 'vscode';
|
||||
import * as vsls from 'vsls/vscode';
|
||||
|
||||
import { ILiveShareApi, IWorkspaceService } from '../common/application/types';
|
||||
import { IAsyncDisposable, IAsyncDisposableRegistry, IConfigurationService, IDisposableRegistry } from '../common/types';
|
||||
import { createDeferred, Deferred } from '../common/utils/async';
|
||||
import { IServiceContainer } from '../ioc/types';
|
||||
import { Identifiers, LiveShare, LiveShareCommands, Settings } from './constants';
|
||||
import { PostOffice } from './liveshare/postOffice';
|
||||
import { IHistory, IHistoryProvider, INotebookServerOptions, IThemeFinder } from './types';
|
||||
import { ILiveShareApi, IWorkspaceService } from '../../common/application/types';
|
||||
import { IAsyncDisposable, IAsyncDisposableRegistry, IConfigurationService, IDisposableRegistry } from '../../common/types';
|
||||
import { createDeferred, Deferred } from '../../common/utils/async';
|
||||
import { IServiceContainer } from '../../ioc/types';
|
||||
import { Identifiers, LiveShare, LiveShareCommands, Settings } from '../constants';
|
||||
import { PostOffice } from '../liveshare/postOffice';
|
||||
import { IHistory, IHistoryProvider, INotebookServerOptions, IThemeFinder } from '../types';
|
||||
|
||||
interface ISyncData {
|
||||
count: number;
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the MIT License.
|
||||
'use strict';
|
||||
|
||||
import { ICell, IHistoryInfo } from './types';
|
||||
import { ICell, IHistoryInfo } from '../types';
|
||||
|
||||
export namespace HistoryMessages {
|
||||
export const StartCell = 'start_cell';
|
||||
|
@ -29,6 +29,7 @@ export namespace HistoryMessages {
|
|||
export const AddedSysInfo = 'added_sys_info';
|
||||
export const RemoteAddCode = 'remote_add_code';
|
||||
export const Activate = 'activate';
|
||||
export const ShowDataExplorer = 'show_data_explorer';
|
||||
}
|
||||
|
||||
// These are the messages that will mirror'd to guest/hosts in
|
||||
|
@ -91,4 +92,5 @@ export class IHistoryMapping {
|
|||
public [HistoryMessages.AddedSysInfo]: IAddedSysInfo;
|
||||
public [HistoryMessages.RemoteAddCode]: IRemoteAddCode;
|
||||
public [HistoryMessages.Activate] : never | undefined;
|
||||
public [HistoryMessages.ShowDataExplorer] : never | undefined; // This is where we'd specify the data for viewing (or perhaps not, just an id?)
|
||||
}
|
|
@ -1,23 +1,23 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
'use strict';
|
||||
import '../common/extensions';
|
||||
import '../../common/extensions';
|
||||
|
||||
import { inject, injectable } from 'inversify';
|
||||
import * as uuid from 'uuid/v4';
|
||||
import { Position, Range, TextDocument, Uri, ViewColumn } from 'vscode';
|
||||
import { CancellationToken, CancellationTokenSource } from 'vscode-jsonrpc';
|
||||
|
||||
import { IApplicationShell, ICommandManager, IDocumentManager } from '../common/application/types';
|
||||
import { CancellationError } from '../common/cancellation';
|
||||
import { PYTHON_LANGUAGE } from '../common/constants';
|
||||
import { IFileSystem } from '../common/platform/types';
|
||||
import { IConfigurationService, IDisposableRegistry, ILogger } from '../common/types';
|
||||
import * as localize from '../common/utils/localize';
|
||||
import { captureTelemetry } from '../telemetry';
|
||||
import { CommandSource } from '../unittests/common/constants';
|
||||
import { generateCellRanges, generateCellsFromDocument } from './cellFactory';
|
||||
import { Commands, Telemetry } from './constants';
|
||||
import { IApplicationShell, ICommandManager, IDocumentManager } from '../../common/application/types';
|
||||
import { CancellationError } from '../../common/cancellation';
|
||||
import { PYTHON_LANGUAGE } from '../../common/constants';
|
||||
import { IFileSystem } from '../../common/platform/types';
|
||||
import { IConfigurationService, IDisposableRegistry, ILogger } from '../../common/types';
|
||||
import * as localize from '../../common/utils/localize';
|
||||
import { captureTelemetry } from '../../telemetry';
|
||||
import { CommandSource } from '../../unittests/common/constants';
|
||||
import { generateCellRanges, generateCellsFromDocument } from '../cellFactory';
|
||||
import { Commands, Telemetry } from '../constants';
|
||||
import {
|
||||
IDataScienceCommandListener,
|
||||
IHistoryProvider,
|
||||
|
@ -26,7 +26,7 @@ import {
|
|||
INotebookImporter,
|
||||
INotebookServer,
|
||||
IStatusProvider
|
||||
} from './types';
|
||||
} from '../types';
|
||||
|
||||
@injectable()
|
||||
export class HistoryCommandListener implements IDataScienceCommandListener {
|
|
@ -13,7 +13,7 @@ import { ILiveShareApi } from '../../../common/application/types';
|
|||
import { IAsyncDisposableRegistry, IConfigurationService, IDisposableRegistry, ILogger } from '../../../common/types';
|
||||
import * as localize from '../../../common/utils/localize';
|
||||
import { Identifiers, LiveShare, LiveShareCommands, RegExpValues } from '../../constants';
|
||||
import { IExecuteInfo } from '../../historyTypes';
|
||||
import { IExecuteInfo } from '../../history/historyTypes';
|
||||
import {
|
||||
ICell,
|
||||
IDataScience,
|
||||
|
|
|
@ -3,12 +3,14 @@
|
|||
'use strict';
|
||||
import { IServiceManager } from '../ioc/types';
|
||||
import { CodeCssGenerator } from './codeCssGenerator';
|
||||
import { DataExplorer } from './data-viewing/dataExplorer';
|
||||
import { DataExplorerProvider } from './data-viewing/dataExplorerProvider';
|
||||
import { DataScience } from './datascience';
|
||||
import { DataScienceCodeLensProvider } from './editor-integration/codelensprovider';
|
||||
import { CodeWatcher } from './editor-integration/codewatcher';
|
||||
import { History } from './history';
|
||||
import { HistoryCommandListener } from './historycommandlistener';
|
||||
import { HistoryProvider } from './historyProvider';
|
||||
import { History } from './history/history';
|
||||
import { HistoryCommandListener } from './history/historycommandlistener';
|
||||
import { HistoryProvider } from './history/historyProvider';
|
||||
import { JupyterCommandFactory } from './jupyter/jupyterCommand';
|
||||
import { JupyterExecutionFactory } from './jupyter/jupyterExecutionFactory';
|
||||
import { JupyterExporter } from './jupyter/jupyterExporter';
|
||||
|
@ -21,6 +23,8 @@ import { ThemeFinder } from './themeFinder';
|
|||
import {
|
||||
ICodeCssGenerator,
|
||||
ICodeWatcher,
|
||||
IDataExplorer,
|
||||
IDataExplorerProvider,
|
||||
IDataScience,
|
||||
IDataScienceCodeLensProvider,
|
||||
IDataScienceCommandListener,
|
||||
|
@ -54,4 +58,6 @@ export function registerTypes(serviceManager: IServiceManager) {
|
|||
serviceManager.add<ICodeWatcher>(ICodeWatcher, CodeWatcher);
|
||||
serviceManager.add<IJupyterCommandFactory>(IJupyterCommandFactory, JupyterCommandFactory);
|
||||
serviceManager.addSingleton<IThemeFinder>(IThemeFinder, ThemeFinder);
|
||||
serviceManager.addSingleton<IDataExplorerProvider>(IDataExplorerProvider, DataExplorerProvider);
|
||||
serviceManager.add<IDataExplorer>(IDataExplorer, DataExplorer);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Disposable, ProgressLocation, ProgressOptions } from 'vscode';
|
|||
|
||||
import { IApplicationShell } from '../common/application/types';
|
||||
import { createDeferred, Deferred } from '../common/utils/async';
|
||||
import { HistoryMessages } from './historyTypes';
|
||||
import { HistoryMessages } from './history/historyTypes';
|
||||
import { IHistoryProvider, IStatusProvider } from './types';
|
||||
|
||||
class StatusItem implements Disposable {
|
||||
|
|
|
@ -272,3 +272,17 @@ export interface IJupyterVariables {
|
|||
getVariables(): Promise<IJupyterVariable[]>;
|
||||
getValue(targetVariable: IJupyterVariable): Promise<IJupyterVariable>;
|
||||
}
|
||||
|
||||
export interface IDataExplorerRow {
|
||||
[column: string] : string | number | {};
|
||||
}
|
||||
|
||||
export const IDataExplorerProvider = Symbol('IDataExplorerProvider');
|
||||
export interface IDataExplorerProvider {
|
||||
create(rows: IDataExplorerRow[]) : Promise<IDataExplorer>;
|
||||
}
|
||||
export const IDataExplorer = Symbol('IDataExplorer');
|
||||
|
||||
export interface IDataExplorer extends IAsyncDisposable {
|
||||
show(rows: IDataExplorerRow[]) : Promise<void>;
|
||||
}
|
||||
|
|
|
@ -344,6 +344,7 @@ export interface IEventNamePropertyMapping {
|
|||
[Telemetry.SetJupyterURIToLocal]: never | undefined;
|
||||
[Telemetry.SetJupyterURIToUserSpecified]: never | undefined;
|
||||
[Telemetry.ShiftEnterBannerShown]: never | undefined;
|
||||
[Telemetry.ShowDataExplorer]: never | undefined;
|
||||
[Telemetry.ShowHistoryPane]: never | undefined;
|
||||
[Telemetry.StartJupyter]: never | undefined;
|
||||
[Telemetry.SubmitCellThroughInput]: never | undefined;
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
'use strict';
|
||||
|
||||
import * as AdazzleReactDataGrid from 'react-data-grid';
|
||||
|
||||
export class DataGridRowRenderer extends AdazzleReactDataGrid.Row {
|
||||
|
||||
// tslint:disable:no-any
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
public render = () => {
|
||||
return super.render();
|
||||
// if (this.props.idx) {
|
||||
// const style: React.CSSProperties = {
|
||||
// color: this.props.idx % 2 ? 'red' : 'blue'
|
||||
// };
|
||||
// return <div id='wrapper' style={style}>{parent}</div>;
|
||||
// }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: sans-serif;
|
||||
}
|
|
@ -0,0 +1,356 @@
|
|||
<!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>
|
||||
<base href="<%= htmlWebpackPlugin.options.indexUrl %>">
|
||||
<style id='default-styles'>
|
||||
:root { --background-color: #ffffff;
|
||||
--comment-color: green;
|
||||
--color: #000000;
|
||||
--font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", HelveticaNeue-Light, Ubuntu, "Droid Sans", sans-serif;
|
||||
--font-size: 13px;
|
||||
--font-weight: normal;
|
||||
--link-active-color: #006ab1;
|
||||
--link-color: #006ab1;
|
||||
--vscode-activityBar-background: #2c2c2c;
|
||||
--vscode-activityBar-dropBackground: rgba(255, 255, 255, 0.12);
|
||||
--vscode-activityBar-foreground: #ffffff;
|
||||
--vscode-activityBar-inactiveForeground: rgba(255, 255, 255, 0.6);
|
||||
--vscode-activityBarBadge-background: #007acc;
|
||||
--vscode-activityBarBadge-foreground: #ffffff;
|
||||
--vscode-badge-background: #c4c4c4;
|
||||
--vscode-badge-foreground: #333333;
|
||||
--vscode-breadcrumb-activeSelectionForeground: #4e4e4e;
|
||||
--vscode-breadcrumb-background: #ffffff;
|
||||
--vscode-breadcrumb-focusForeground: #4e4e4e;
|
||||
--vscode-breadcrumb-foreground: rgba(97, 97, 97, 0.8);
|
||||
--vscode-breadcrumbPicker-background: #f3f3f3;
|
||||
--vscode-button-background: #007acc;
|
||||
--vscode-button-foreground: #ffffff;
|
||||
--vscode-button-hoverBackground: #0062a3;
|
||||
--vscode-debugExceptionWidget-background: #f1dfde;
|
||||
--vscode-debugExceptionWidget-border: #a31515;
|
||||
--vscode-debugToolBar-background: #f3f3f3;
|
||||
--vscode-descriptionForeground: #717171;
|
||||
--vscode-diffEditor-insertedTextBackground: rgba(155, 185, 85, 0.2);
|
||||
--vscode-diffEditor-removedTextBackground: rgba(255, 0, 0, 0.2);
|
||||
--vscode-dropdown-background: #ffffff;
|
||||
--vscode-dropdown-border: #cecece;
|
||||
--vscode-editor-background: #ffffff;
|
||||
--vscode-editor-findMatchBackground: #a8ac94;
|
||||
--vscode-editor-findMatchHighlightBackground: rgba(234, 92, 0, 0.33);
|
||||
--vscode-editor-findRangeHighlightBackground: rgba(180, 180, 180, 0.3);
|
||||
--vscode-editor-font-family: -apple-system, BlinkMacSystemFont, "Segoe WPC", "Segoe UI", HelveticaNeue-Light, Ubuntu, "Droid Sans", sans-serif;
|
||||
--vscode-editor-font-size: 13px;
|
||||
--vscode-editor-font-weight: normal;
|
||||
--vscode-editor-foreground: #000000;
|
||||
--vscode-editor-hoverHighlightBackground: rgba(173, 214, 255, 0.15);
|
||||
--vscode-editor-inactiveSelectionBackground: #e5ebf1;
|
||||
--vscode-editor-lineHighlightBorder: #eeeeee;
|
||||
--vscode-editor-rangeHighlightBackground: rgba(253, 255, 0, 0.2);
|
||||
--vscode-editor-selectionBackground: #add6ff;
|
||||
--vscode-editor-selectionHighlightBackground: rgba(173, 214, 255, 0.3);
|
||||
--vscode-editor-snippetFinalTabstopHighlightBorder: rgba(10, 50, 100, 0.5);
|
||||
--vscode-editor-snippetTabstopHighlightBackground: rgba(10, 50, 100, 0.2);
|
||||
--vscode-editor-wordHighlightBackground: rgba(87, 87, 87, 0.25);
|
||||
--vscode-editor-wordHighlightStrongBackground: rgba(14, 99, 156, 0.25);
|
||||
--vscode-editorActiveLineNumber-foreground: #0b216f;
|
||||
--vscode-editorBracketMatch-background: rgba(0, 100, 0, 0.1);
|
||||
--vscode-editorBracketMatch-border: #b9b9b9;
|
||||
--vscode-editorCodeLens-foreground: #999999;
|
||||
--vscode-editorCursor-foreground: #000000;
|
||||
--vscode-editorError-foreground: #d60a0a;
|
||||
--vscode-editorGroup-border: #e7e7e7;
|
||||
--vscode-editorGroup-dropBackground: rgba(38, 119, 203, 0.18);
|
||||
--vscode-editorGroupHeader-noTabsBackground: #ffffff;
|
||||
--vscode-editorGroupHeader-tabsBackground: #f3f3f3;
|
||||
--vscode-editorGutter-addedBackground: #81b88b;
|
||||
--vscode-editorGutter-background: #ffffff;
|
||||
--vscode-editorGutter-commentRangeForeground: #c5c5c5;
|
||||
--vscode-editorGutter-deletedBackground: #ca4b51;
|
||||
--vscode-editorGutter-modifiedBackground: #66afe0;
|
||||
--vscode-editorHint-foreground: #6c6c6c;
|
||||
--vscode-editorHoverWidget-background: #f3f3f3;
|
||||
--vscode-editorHoverWidget-border: #c8c8c8;
|
||||
--vscode-editorIndentGuide-activeBackground: #939393;
|
||||
--vscode-editorIndentGuide-background: #d3d3d3;
|
||||
--vscode-editorInfo-foreground: #008000;
|
||||
--vscode-editorLineNumber-activeForeground: #0b216f;
|
||||
--vscode-editorLineNumber-foreground: #237893;
|
||||
--vscode-editorLink-activeForeground: #0000ff;
|
||||
--vscode-editorMarkerNavigation-background: #ffffff;
|
||||
--vscode-editorMarkerNavigationError-background: #d60a0a;
|
||||
--vscode-editorMarkerNavigationInfo-background: #008000;
|
||||
--vscode-editorMarkerNavigationWarning-background: #117711;
|
||||
--vscode-editorOverviewRuler-addedForeground: rgba(0, 122, 204, 0.6);
|
||||
--vscode-editorOverviewRuler-border: rgba(127, 127, 127, 0.3);
|
||||
--vscode-editorOverviewRuler-bracketMatchForeground: #a0a0a0;
|
||||
--vscode-editorOverviewRuler-commonContentForeground: rgba(96, 96, 96, 0.4);
|
||||
--vscode-editorOverviewRuler-currentContentForeground: rgba(64, 200, 174, 0.5);
|
||||
--vscode-editorOverviewRuler-deletedForeground: rgba(0, 122, 204, 0.6);
|
||||
--vscode-editorOverviewRuler-errorForeground: rgba(255, 18, 18, 0.7);
|
||||
--vscode-editorOverviewRuler-findMatchForeground: rgba(246, 185, 77, 0.7);
|
||||
--vscode-editorOverviewRuler-incomingContentForeground: rgba(64, 166, 255, 0.5);
|
||||
--vscode-editorOverviewRuler-infoForeground: rgba(18, 18, 136, 0.7);
|
||||
--vscode-editorOverviewRuler-modifiedForeground: rgba(0, 122, 204, 0.6);
|
||||
--vscode-editorOverviewRuler-rangeHighlightForeground: rgba(0, 122, 204, 0.6);
|
||||
--vscode-editorOverviewRuler-selectionHighlightForeground: rgba(160, 160, 160, 0.8);
|
||||
--vscode-editorOverviewRuler-warningForeground: rgba(18, 136, 18, 0.7);
|
||||
--vscode-editorOverviewRuler-wordHighlightForeground: rgba(160, 160, 160, 0.8);
|
||||
--vscode-editorOverviewRuler-wordHighlightStrongForeground: rgba(192, 160, 192, 0.8);
|
||||
--vscode-editorPane-background: #ffffff;
|
||||
--vscode-editorRuler-foreground: #d3d3d3;
|
||||
--vscode-editorSuggestWidget-background: #f3f3f3;
|
||||
--vscode-editorSuggestWidget-border: #c8c8c8;
|
||||
--vscode-editorSuggestWidget-foreground: #000000;
|
||||
--vscode-editorSuggestWidget-highlightForeground: #0066bf;
|
||||
--vscode-editorSuggestWidget-selectedBackground: #d6ebff;
|
||||
--vscode-editorUnnecessaryCode-opacity: rgba(0, 0, 0, 0.47);
|
||||
--vscode-editorWarning-foreground: #117711;
|
||||
--vscode-editorWhitespace-foreground: rgba(51, 51, 51, 0.2);
|
||||
--vscode-editorWidget-background: #f3f3f3;
|
||||
--vscode-editorWidget-border: #c8c8c8;
|
||||
--vscode-errorForeground: #a1260d;
|
||||
--vscode-extensionButton-prominentBackground: #327e36;
|
||||
--vscode-extensionButton-prominentForeground: #ffffff;
|
||||
--vscode-extensionButton-prominentHoverBackground: #28632b;
|
||||
--vscode-focusBorder: rgba(0, 122, 204, 0.4);
|
||||
--vscode-foreground: #616161;
|
||||
--vscode-gitDecoration-addedResourceForeground: #587c0c;
|
||||
--vscode-gitDecoration-conflictingResourceForeground: #6c6cc4;
|
||||
--vscode-gitDecoration-deletedResourceForeground: #ad0707;
|
||||
--vscode-gitDecoration-ignoredResourceForeground: #8e8e90;
|
||||
--vscode-gitDecoration-modifiedResourceForeground: #895503;
|
||||
--vscode-gitDecoration-submoduleResourceForeground: #1258a7;
|
||||
--vscode-gitDecoration-untrackedResourceForeground: #007100;
|
||||
--vscode-input-background: #ffffff;
|
||||
--vscode-input-foreground: #616161;
|
||||
--vscode-input-placeholderForeground: #767676;
|
||||
--vscode-inputOption-activeBorder: #007acc;
|
||||
--vscode-inputValidation-errorBackground: #f2dede;
|
||||
--vscode-inputValidation-errorBorder: #be1100;
|
||||
--vscode-inputValidation-infoBackground: #d6ecf2;
|
||||
--vscode-inputValidation-infoBorder: #007acc;
|
||||
--vscode-inputValidation-warningBackground: #f6f5d2;
|
||||
--vscode-inputValidation-warningBorder: #b89500;
|
||||
--vscode-list-activeSelectionBackground: #2477ce;
|
||||
--vscode-list-activeSelectionForeground: #ffffff;
|
||||
--vscode-list-dropBackground: #d6ebff;
|
||||
--vscode-list-errorForeground: #b01011;
|
||||
--vscode-list-focusBackground: #d6ebff;
|
||||
--vscode-list-highlightForeground: #0066bf;
|
||||
--vscode-list-hoverBackground: #e8e8e8;
|
||||
--vscode-list-inactiveFocusBackground: #d8dae6;
|
||||
--vscode-list-inactiveSelectionBackground: #e4e6f1;
|
||||
--vscode-list-invalidItemForeground: #b89500;
|
||||
--vscode-list-warningForeground: #117711;
|
||||
--vscode-menu-background: #ffffff;
|
||||
--vscode-menu-selectionBackground: #2477ce;
|
||||
--vscode-menu-selectionForeground: #ffffff;
|
||||
--vscode-menu-separatorBackground: #888888;
|
||||
--vscode-menubar-selectionBackground: rgba(0, 0, 0, 0.1);
|
||||
--vscode-menubar-selectionForeground: #333333;
|
||||
--vscode-merge-commonContentBackground: rgba(96, 96, 96, 0.16);
|
||||
--vscode-merge-commonHeaderBackground: rgba(96, 96, 96, 0.4);
|
||||
--vscode-merge-currentContentBackground: rgba(64, 200, 174, 0.2);
|
||||
--vscode-merge-currentHeaderBackground: rgba(64, 200, 174, 0.5);
|
||||
--vscode-merge-incomingContentBackground: rgba(64, 166, 255, 0.2);
|
||||
--vscode-merge-incomingHeaderBackground: rgba(64, 166, 255, 0.5);
|
||||
--vscode-notificationCenterHeader-background: #e7e7e7;
|
||||
--vscode-notificationLink-foreground: #006ab1;
|
||||
--vscode-notifications-background: #f3f3f3;
|
||||
--vscode-notifications-border: #e7e7e7;
|
||||
--vscode-panel-background: #ffffff;
|
||||
--vscode-panel-border: rgba(128, 128, 128, 0.35);
|
||||
--vscode-panel-dropBackground: rgba(38, 119, 203, 0.18);
|
||||
--vscode-panelTitle-activeBorder: rgba(128, 128, 128, 0.35);
|
||||
--vscode-panelTitle-activeForeground: #424242;
|
||||
--vscode-panelTitle-inactiveForeground: rgba(66, 66, 66, 0.75);
|
||||
--vscode-peekView-border: #007acc;
|
||||
--vscode-peekViewEditor-background: #f2f8fc;
|
||||
--vscode-peekViewEditor-matchHighlightBackground: rgba(245, 216, 2, 0.87);
|
||||
--vscode-peekViewEditorGutter-background: #f2f8fc;
|
||||
--vscode-peekViewResult-background: #f3f3f3;
|
||||
--vscode-peekViewResult-fileForeground: #1e1e1e;
|
||||
--vscode-peekViewResult-lineForeground: #646465;
|
||||
--vscode-peekViewResult-matchHighlightBackground: rgba(234, 92, 0, 0.3);
|
||||
--vscode-peekViewResult-selectionBackground: rgba(51, 153, 255, 0.2);
|
||||
--vscode-peekViewResult-selectionForeground: #6c6c6c;
|
||||
--vscode-peekViewTitle-background: #ffffff;
|
||||
--vscode-peekViewTitleDescription-foreground: rgba(108, 108, 108, 0.7);
|
||||
--vscode-peekViewTitleLabel-foreground: #333333;
|
||||
--vscode-pickerGroup-border: #cccedb;
|
||||
--vscode-pickerGroup-foreground: #0066bf;
|
||||
--vscode-progressBar-background: #0e70c0;
|
||||
--vscode-scrollbar-shadow: #dddddd;
|
||||
--vscode-scrollbarSlider-activeBackground: rgba(0, 0, 0, 0.6);
|
||||
--vscode-scrollbarSlider-background: rgba(100, 100, 100, 0.4);
|
||||
--vscode-scrollbarSlider-hoverBackground: rgba(100, 100, 100, 0.7);
|
||||
--vscode-settings-checkboxBackground: #ffffff;
|
||||
--vscode-settings-checkboxBorder: #cecece;
|
||||
--vscode-settings-dropdownBackground: #ffffff;
|
||||
--vscode-settings-dropdownBorder: #cecece;
|
||||
--vscode-settings-dropdownListBorder: #c8c8c8;
|
||||
--vscode-settings-headerForeground: #444444;
|
||||
--vscode-settings-modifiedItemIndicator: #66afe0;
|
||||
--vscode-settings-numberInputBackground: #ffffff;
|
||||
--vscode-settings-numberInputBorder: #cecece;
|
||||
--vscode-settings-numberInputForeground: #616161;
|
||||
--vscode-settings-textInputBackground: #ffffff;
|
||||
--vscode-settings-textInputBorder: #cecece;
|
||||
--vscode-settings-textInputForeground: #616161;
|
||||
--vscode-sideBar-background: #f3f3f3;
|
||||
--vscode-sideBar-dropBackground: rgba(255, 255, 255, 0.12);
|
||||
--vscode-sideBarSectionHeader-background: rgba(128, 128, 128, 0.2);
|
||||
--vscode-sideBarTitle-foreground: #6f6f6f;
|
||||
--vscode-statusBar-background: #007acc;
|
||||
--vscode-statusBar-debuggingBackground: #cc6633;
|
||||
--vscode-statusBar-debuggingForeground: #ffffff;
|
||||
--vscode-statusBar-foreground: #ffffff;
|
||||
--vscode-statusBar-noFolderBackground: #68217a;
|
||||
--vscode-statusBar-noFolderForeground: #ffffff;
|
||||
--vscode-statusBarItem-activeBackground: rgba(255, 255, 255, 0.18);
|
||||
--vscode-statusBarItem-hoverBackground: rgba(255, 255, 255, 0.12);
|
||||
--vscode-statusBarItem-prominentBackground: #388a34;
|
||||
--vscode-statusBarItem-prominentHoverBackground: #369432;
|
||||
--vscode-tab-activeBackground: #ffffff;
|
||||
--vscode-tab-activeForeground: #333333;
|
||||
--vscode-tab-border: #f3f3f3;
|
||||
--vscode-tab-inactiveBackground: #ececec;
|
||||
--vscode-tab-inactiveForeground: rgba(51, 51, 51, 0.5);
|
||||
--vscode-tab-unfocusedActiveForeground: rgba(51, 51, 51, 0.7);
|
||||
--vscode-tab-unfocusedInactiveForeground: rgba(51, 51, 51, 0.25);
|
||||
--vscode-terminal-ansiBlack: #000000;
|
||||
--vscode-terminal-ansiBlue: #0451a5;
|
||||
--vscode-terminal-ansiBrightBlack: #666666;
|
||||
--vscode-terminal-ansiBrightBlue: #0451a5;
|
||||
--vscode-terminal-ansiBrightCyan: #0598bc;
|
||||
--vscode-terminal-ansiBrightGreen: #14ce14;
|
||||
--vscode-terminal-ansiBrightMagenta: #bc05bc;
|
||||
--vscode-terminal-ansiBrightRed: #cd3131;
|
||||
--vscode-terminal-ansiBrightWhite: #a5a5a5;
|
||||
--vscode-terminal-ansiBrightYellow: #b5ba00;
|
||||
--vscode-terminal-ansiCyan: #0598bc;
|
||||
--vscode-terminal-ansiGreen: #00bc00;
|
||||
--vscode-terminal-ansiMagenta: #bc05bc;
|
||||
--vscode-terminal-ansiRed: #cd3131;
|
||||
--vscode-terminal-ansiWhite: #555555;
|
||||
--vscode-terminal-ansiYellow: #949800;
|
||||
--vscode-terminal-background: #ffffff;
|
||||
--vscode-terminal-border: rgba(128, 128, 128, 0.35);
|
||||
--vscode-terminal-foreground: #333333;
|
||||
--vscode-terminal-selectionBackground: rgba(0, 0, 0, 0.25);
|
||||
--vscode-textBlockQuote-background: rgba(127, 127, 127, 0.1);
|
||||
--vscode-textBlockQuote-border: rgba(0, 122, 204, 0.5);
|
||||
--vscode-textCodeBlock-background: rgba(220, 220, 220, 0.4);
|
||||
--vscode-textLink-activeForeground: #006ab1;
|
||||
--vscode-textLink-foreground: #006ab1;
|
||||
--vscode-textPreformat-foreground: #a31515;
|
||||
--vscode-textSeparator-foreground: rgba(0, 0, 0, 0.18);
|
||||
--vscode-titleBar-activeBackground: #dddddd;
|
||||
--vscode-titleBar-activeForeground: #333333;
|
||||
--vscode-titleBar-inactiveBackground: rgba(221, 221, 221, 0.6);
|
||||
--vscode-titleBar-inactiveForeground: rgba(51, 51, 51, 0.6);
|
||||
--vscode-widget-shadow: #a8a8a8;
|
||||
--code-font-family: 'Comic-Sans';
|
||||
--code-font-size: 15px;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--vscode-editor-background);
|
||||
color: var(--vscode-editor-foreground);
|
||||
font-family: var(--vscode-editor-font-family);
|
||||
font-weight: var(--vscode-editor-font-weight);
|
||||
font-size: var(--vscode-editor-font-size);
|
||||
margin: 0;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--vscode-textLink-foreground);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--vscode-textLink-activeForeground);
|
||||
}
|
||||
|
||||
a:focus,
|
||||
input:focus,
|
||||
select:focus,
|
||||
textarea:focus {
|
||||
outline: 1px solid -webkit-focus-ring-color;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
code {
|
||||
color: var(--vscode-textPreformat-foreground);
|
||||
}
|
||||
|
||||
blockquote {
|
||||
background: var(--vscode-textBlockQuote-background);
|
||||
border-color: var(--vscode-textBlockQuote-border);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(121, 121, 121, 0.4);
|
||||
}
|
||||
body.vscode-light::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(100, 100, 100, 0.4);
|
||||
}
|
||||
body.vscode-high-contrast::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(111, 195, 223, 0.3);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(100, 100, 100, 0.7);
|
||||
}
|
||||
body.vscode-light::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(100, 100, 100, 0.7);
|
||||
}
|
||||
body.vscode-high-contrast::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(111, 195, 223, 0.8);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:active {
|
||||
background-color: rgba(85, 85, 85, 0.8);
|
||||
}
|
||||
body.vscode-light::-webkit-scrollbar-thumb:active {
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
body.vscode-high-contrast::-webkit-scrollbar-thumb:active {
|
||||
background-color: rgba(111, 195, 223, 0.8);
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="text/javascript">
|
||||
function resolvePath(relativePath) {
|
||||
if (relativePath && relativePath[0] == '.' && relativePath[1] != '.') {
|
||||
return "<%= htmlWebpackPlugin.options.imageBaseUrl %>" + relativePath.substring(1);
|
||||
}
|
||||
|
||||
return "<%= htmlWebpackPlugin.options.imageBaseUrl %>" + relativePath;
|
||||
}
|
||||
function getInitialSettings() {
|
||||
return { allowInput: true,
|
||||
extraSettings: { terminalCursor: 'block'}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
'use strict';
|
||||
import './index.css';
|
||||
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
|
||||
import { IVsCodeApi } from '../react-common/postOffice';
|
||||
import { MainPanel } from './mainPanel';
|
||||
|
||||
// This special function talks to vscode from a web panel
|
||||
export declare function acquireVsCodeApi(): IVsCodeApi;
|
||||
|
||||
ReactDOM.render(
|
||||
<MainPanel skipDefault={false}/>, // Turn this back off when we have real variable explorer data
|
||||
document.getElementById('root') as HTMLElement
|
||||
);
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
See here for defaults:
|
||||
https://github.com/adazzle/react-data-grid/blob/master/themes
|
||||
|
||||
*/
|
||||
|
||||
.main-panel {
|
||||
font-size: var(--code-font-size);
|
||||
font-family: var(--code-font-family);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0;
|
||||
background-color: var(--vscode-editor-background);
|
||||
}
|
||||
|
||||
.main-panel .form-control {
|
||||
height: auto;
|
||||
padding: 0px;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
line-height: inherit;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.main-panel .react-grid-Toolbar {
|
||||
background-color: var(--vscode-editor-background);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.main-panel .react-grid-Toolbar .btn {
|
||||
background-color: var(--vscode-editor-background);
|
||||
color: var(--vscode-editor-foreground);
|
||||
border-color: var(--vscode-badge-background);
|
||||
}
|
||||
|
||||
.main-panel .react-grid-Main {
|
||||
background-color: var(--vscode-editor-background);
|
||||
color: var(--vscode-editor-foreground);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.main-panel .react-grid-Grid {
|
||||
background-color: var(--vscode-editor-background);
|
||||
color: var(--vscode-editor-foreground);
|
||||
border-color: var(--vscode-badge-background);
|
||||
}
|
||||
|
||||
.main-panel .react-grid-Canvas {
|
||||
background-color: var(--vscode-editor-background);
|
||||
color: var(--vscode-editor-foreground);
|
||||
}
|
||||
|
||||
.main-panel .react-grid-Header {
|
||||
background-color: var(--vscode-notifications-background);
|
||||
}
|
||||
|
||||
.main-panel .react-grid-HeaderCell {
|
||||
background-color: var(--vscode-notifications-background);
|
||||
color: var(--vscode-editor-foreground);
|
||||
border-right-color: var(--vscode-badge-background);
|
||||
border-bottom-color: var(--vscode-badge-background);
|
||||
}
|
||||
|
||||
.main-panel .react-grid-Cell {
|
||||
background-color: var(--vscode-editor-background);
|
||||
color: var(--vscode-editor-foreground);
|
||||
border-right-color: var(--vscode-badge-background);
|
||||
border-bottom-color: var(--vscode-badge-background);
|
||||
}
|
||||
|
||||
.main-panel .react-grid-Cell:hover {
|
||||
background-color: var(--vscode-editor-selectionBackground);
|
||||
}
|
||||
|
||||
.main-panel .react-grid-Row:hover {
|
||||
background-color: var(--vscode-editor-selectionBackground);
|
||||
}
|
||||
|
||||
.main-panel .react-grid-Row:hover .react-grid-Cell {
|
||||
background-color: var(--vscode-editor-selectionBackground);
|
||||
}
|
||||
|
||||
.main-panel .rdg-selected {
|
||||
visibility: hidden;
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
'use strict';
|
||||
|
||||
import * as React from 'react';
|
||||
import * as AdazzleReactDataGrid from 'react-data-grid';
|
||||
import { Data, Toolbar } from 'react-data-grid-addons';
|
||||
|
||||
import { DataExplorerMessages, IDataExplorerMapping } from '../../client/datascience/data-viewing/types';
|
||||
import { IMessageHandler, PostOffice } from '../react-common/postOffice';
|
||||
import { generateTestData } from './testData';
|
||||
|
||||
import 'bootstrap/dist/css/bootstrap.css';
|
||||
|
||||
import './mainPanel.css';
|
||||
|
||||
const selectors = Data.Selectors;
|
||||
|
||||
const defaultColumnProperties = {
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
resizable: true,
|
||||
width: 120
|
||||
};
|
||||
|
||||
export interface IMainPanelProps {
|
||||
skipDefault?: boolean;
|
||||
}
|
||||
|
||||
interface IMainPanelState {
|
||||
gridColumns: AdazzleReactDataGrid.Column<object>[];
|
||||
gridRows: IGridRow[];
|
||||
initialGridRows: IGridRow[];
|
||||
filters: {};
|
||||
gridHeight: number;
|
||||
}
|
||||
|
||||
// tslint:disable:no-any
|
||||
interface IGridRow {
|
||||
[name: string]: any;
|
||||
}
|
||||
|
||||
class DataExplorerPostOffice extends PostOffice<IDataExplorerMapping> { }
|
||||
|
||||
export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState> implements IMessageHandler {
|
||||
private postOffice: DataExplorerPostOffice | undefined;
|
||||
private container: HTMLDivElement | null = null;
|
||||
|
||||
// tslint:disable-next-line:max-func-body-length
|
||||
constructor(props: IMainPanelProps, state: IMainPanelState) {
|
||||
super(props);
|
||||
|
||||
if (!this.props.skipDefault) {
|
||||
const data = generateTestData(5000);
|
||||
this.state = {
|
||||
gridColumns: data.columns.map(c => { return { ...c, ...defaultColumnProperties }; }),
|
||||
gridRows: data.rows,
|
||||
initialGridRows: data.rows,
|
||||
filters: {},
|
||||
gridHeight: 100
|
||||
};
|
||||
} else {
|
||||
this.state = {
|
||||
gridColumns: [],
|
||||
gridRows: [],
|
||||
initialGridRows: [],
|
||||
filters: {},
|
||||
gridHeight: 100
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
window.addEventListener('resize', this.updateDimensions);
|
||||
this.updateDimensions();
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
window.removeEventListener('resize', this.updateDimensions);
|
||||
}
|
||||
|
||||
public render = () => {
|
||||
|
||||
return (
|
||||
<div className='main-panel' ref={this.updateContainer}>
|
||||
<DataExplorerPostOffice messageHandlers={[this]} ref={this.updatePostOffice} />
|
||||
{this.container && this.renderGrid()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-any
|
||||
public handleMessage = (msg: string, payload?: any) => {
|
||||
switch (msg) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private updateDimensions = () => {
|
||||
if (this.container) {
|
||||
const height = this.container.offsetHeight;
|
||||
this.setState({ gridHeight: height - 100 });
|
||||
}
|
||||
}
|
||||
|
||||
private updateContainer = (el: HTMLDivElement) => {
|
||||
this.container = el;
|
||||
}
|
||||
|
||||
private renderGrid() {
|
||||
return (
|
||||
<AdazzleReactDataGrid
|
||||
columns={this.state.gridColumns}
|
||||
rowGetter={this.getRow}
|
||||
rowsCount={this.state.gridRows.length}
|
||||
minHeight={this.state.gridHeight}
|
||||
toolbar={<Toolbar enableFilter={true} />}
|
||||
onAddFilter={this.handleFilterChange}
|
||||
onClearFilters={this.clearFilters}
|
||||
onGridSort={this.sortRows}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
private getRow = (index: number) => {
|
||||
return this.state.gridRows[index];
|
||||
}
|
||||
|
||||
private updatePostOffice = (postOffice: DataExplorerPostOffice) => {
|
||||
if (this.postOffice !== postOffice) {
|
||||
this.postOffice = postOffice;
|
||||
this.sendMessage(DataExplorerMessages.Started);
|
||||
}
|
||||
}
|
||||
|
||||
private sendMessage<M extends IDataExplorerMapping, T extends keyof M>(type: T, payload?: M[T]) {
|
||||
if (this.postOffice) {
|
||||
this.postOffice.sendMessage(type, payload);
|
||||
}
|
||||
}
|
||||
|
||||
// tslint:disable:no-any
|
||||
private handleFilterChange = (filter: any) => {
|
||||
const newFilters: { [key: string]: any } = { ...this.state.filters };
|
||||
if (filter.column.key) {
|
||||
if (filter.filterTerm) {
|
||||
newFilters[filter.column.key] = filter;
|
||||
} else {
|
||||
delete newFilters[filter.column.key];
|
||||
}
|
||||
}
|
||||
this.setState({ filters: newFilters, gridRows: selectors.getRows({rows: this.state.initialGridRows, filters: newFilters})});
|
||||
}
|
||||
|
||||
private clearFilters = () => {
|
||||
this.setState({ filters: {} });
|
||||
}
|
||||
|
||||
private sortRows = (sortColumn: string | number, sortDirection: string) => {
|
||||
if (sortDirection === 'NONE') {
|
||||
sortColumn = 'index';
|
||||
sortDirection = 'ASC';
|
||||
}
|
||||
const comparer = (a: IGridRow, b: IGridRow): number => {
|
||||
if (sortDirection === 'ASC') {
|
||||
return a[sortColumn] > b[sortColumn] ? 1 : -1;
|
||||
} else if (sortDirection === 'DESC') {
|
||||
return a[sortColumn] < b[sortColumn] ? 1 : -1;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
const sorted = this.state.initialGridRows.sort(comparer);
|
||||
this.setState({ gridRows: selectors.getRows({rows: sorted, filters: this.state.filters}) });
|
||||
}
|
||||
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8,7 +8,7 @@ import * as React from 'react';
|
|||
|
||||
import { CellMatcher } from '../../client/datascience/cellMatcher';
|
||||
import { generateMarkdownFromCodeLines } from '../../client/datascience/common';
|
||||
import { HistoryMessages, IHistoryMapping } from '../../client/datascience/historyTypes';
|
||||
import { HistoryMessages, IHistoryMapping } from '../../client/datascience/history/historyTypes';
|
||||
import { CellState, ICell, IHistoryInfo } from '../../client/datascience/types';
|
||||
import { noop } from '../../test/core';
|
||||
import { ErrorBoundary } from '../react-common/errorBoundary';
|
||||
|
@ -30,13 +30,15 @@ export interface IMainPanelProps {
|
|||
codeTheme: string;
|
||||
}
|
||||
|
||||
class HistoryPostOffice extends PostOffice<IHistoryMapping> {}
|
||||
|
||||
export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState> implements IMessageHandler {
|
||||
private stackLimit = 10;
|
||||
private bottom: HTMLDivElement | undefined;
|
||||
private updateCount = 0;
|
||||
private renderCount = 0;
|
||||
private sentStartup = false;
|
||||
private postOffice: PostOffice | undefined;
|
||||
private postOffice: HistoryPostOffice | undefined;
|
||||
private editCellRef: Cell | null = null;
|
||||
private mainPanel: HTMLDivElement | null = null;
|
||||
|
||||
|
@ -84,7 +86,7 @@ export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState>
|
|||
|
||||
return (
|
||||
<div className='main-panel' ref={this.updateSelf}>
|
||||
<PostOffice messageHandlers={[this]} ref={this.updatePostOffice} />
|
||||
<HistoryPostOffice messageHandlers={[this]} ref={this.updatePostOffice} />
|
||||
<MenuBar baseTheme={baseTheme} stylePosition='top-fixed'>
|
||||
{this.renderExtraButtons()}
|
||||
<CellButton baseTheme={baseTheme} onClick={this.collapseAll} disabled={!this.canCollapseAll()} tooltip={getLocString('DataScience.collapseAll', 'Collapse all cell inputs')}>
|
||||
|
@ -472,7 +474,7 @@ export class MainPanel extends React.Component<IMainPanelProps, IMainPanelState>
|
|||
this.mainPanel = r;
|
||||
}
|
||||
|
||||
private updatePostOffice = (postOffice: PostOffice) => {
|
||||
private updatePostOffice = (postOffice: HistoryPostOffice) => {
|
||||
if (this.postOffice !== postOffice) {
|
||||
this.postOffice = postOffice;
|
||||
if (!this.sentStartup) {
|
||||
|
|
|
@ -7,12 +7,16 @@ import * as React from 'react';
|
|||
import * as ReactDOM from 'react-dom';
|
||||
|
||||
import { Identifiers } from '../../client/datascience/constants';
|
||||
import { IVsCodeApi } from '../react-common/postOffice';
|
||||
import { detectBaseTheme } from '../react-common/themeDetector';
|
||||
import { MainPanel } from './MainPanel';
|
||||
|
||||
// This special function talks to vscode from a web panel
|
||||
export declare function acquireVsCodeApi(): IVsCodeApi;
|
||||
const baseTheme = detectBaseTheme();
|
||||
|
||||
// tslint:disable:no-typeof-undefined
|
||||
ReactDOM.render(
|
||||
<MainPanel baseTheme={baseTheme} codeTheme={Identifiers.GeneratedThemeName} skipDefault={true} />,
|
||||
<MainPanel baseTheme={baseTheme} codeTheme={Identifiers.GeneratedThemeName} skipDefault={typeof acquireVsCodeApi !== 'undefined'} />,
|
||||
document.getElementById('root') as HTMLElement
|
||||
);
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
import { WebPanelMessage } from '../../client/common/application/types';
|
||||
import { IHistoryMapping } from '../../client/datascience/historyTypes';
|
||||
|
||||
export interface IVsCodeApi {
|
||||
// tslint:disable-next-line:no-any
|
||||
|
@ -28,7 +26,7 @@ interface IPostOfficeProps {
|
|||
// This special function talks to vscode from a web panel
|
||||
export declare function acquireVsCodeApi(): IVsCodeApi;
|
||||
|
||||
export class PostOffice extends React.Component<IPostOfficeProps> {
|
||||
export class PostOffice<Mapping> extends React.Component<IPostOfficeProps> {
|
||||
|
||||
private vscodeApi : IVsCodeApi | undefined;
|
||||
private registered: boolean = false;
|
||||
|
@ -37,7 +35,7 @@ export class PostOffice extends React.Component<IPostOfficeProps> {
|
|||
super(props);
|
||||
}
|
||||
|
||||
public sendMessage<M extends IHistoryMapping, T extends keyof M>(type: T, payload?: M[T]) {
|
||||
public sendMessage<M extends Mapping, T extends keyof M>(type: T, payload?: M[T]) {
|
||||
const api = this.acquireApi();
|
||||
if (api) {
|
||||
api.postMessage({ type: type.toString(), payload });
|
||||
|
|
|
@ -71,10 +71,12 @@ import { EnvironmentVariablesService } from '../../client/common/variables/envir
|
|||
import { SystemVariables } from '../../client/common/variables/systemVariables';
|
||||
import { IEnvironmentVariablesProvider, IEnvironmentVariablesService } from '../../client/common/variables/types';
|
||||
import { CodeCssGenerator } from '../../client/datascience/codeCssGenerator';
|
||||
import { DataExplorer } from '../../client/datascience/data-viewing/dataExplorer';
|
||||
import { DataExplorerProvider } from '../../client/datascience/data-viewing/dataExplorerProvider';
|
||||
import { CodeWatcher } from '../../client/datascience/editor-integration/codewatcher';
|
||||
import { History } from '../../client/datascience/history';
|
||||
import { HistoryCommandListener } from '../../client/datascience/historycommandlistener';
|
||||
import { HistoryProvider } from '../../client/datascience/historyProvider';
|
||||
import { History } from '../../client/datascience/history/history';
|
||||
import { HistoryCommandListener } from '../../client/datascience/history/historycommandlistener';
|
||||
import { HistoryProvider } from '../../client/datascience/history/historyProvider';
|
||||
import { JupyterCommandFactory } from '../../client/datascience/jupyter/jupyterCommand';
|
||||
import { JupyterExecutionFactory } from '../../client/datascience/jupyter/jupyterExecutionFactory';
|
||||
import { JupyterExporter } from '../../client/datascience/jupyter/jupyterExporter';
|
||||
|
@ -86,6 +88,8 @@ import { ThemeFinder } from '../../client/datascience/themeFinder';
|
|||
import {
|
||||
ICodeCssGenerator,
|
||||
ICodeWatcher,
|
||||
IDataExplorer,
|
||||
IDataExplorerProvider,
|
||||
IDataScience,
|
||||
IDataScienceCommandListener,
|
||||
IHistory,
|
||||
|
@ -210,7 +214,9 @@ export class DataScienceIocContainer extends UnitTestIocContainer {
|
|||
this.registerFileSystemTypes();
|
||||
this.serviceManager.addSingleton<IJupyterExecution>(IJupyterExecution, JupyterExecutionFactory);
|
||||
this.serviceManager.addSingleton<IHistoryProvider>(IHistoryProvider, HistoryProvider);
|
||||
this.serviceManager.addSingleton<IDataExplorerProvider>(IDataExplorerProvider, DataExplorerProvider);
|
||||
this.serviceManager.add<IHistory>(IHistory, History);
|
||||
this.serviceManager.add<IDataExplorer>(IDataExplorer, DataExplorer);
|
||||
this.serviceManager.add<INotebookImporter>(INotebookImporter, JupyterImporter);
|
||||
this.serviceManager.add<INotebookExporter>(INotebookExporter, JupyterExporter);
|
||||
this.serviceManager.addSingleton<ILiveShareApi>(ILiveShareApi, MockLiveShareApi);
|
||||
|
|
|
@ -8,7 +8,7 @@ import * as path from 'path';
|
|||
import * as React from 'react';
|
||||
import { SemVer } from 'semver';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import { Disposable, TextDocument, TextEditor } from 'vscode';
|
||||
import { Disposable, TextDocument, TextEditor, ViewColumn } from 'vscode';
|
||||
|
||||
import {
|
||||
IApplicationShell,
|
||||
|
@ -22,8 +22,8 @@ import { createDeferred, Deferred } from '../../client/common/utils/async';
|
|||
import { noop } from '../../client/common/utils/misc';
|
||||
import { Architecture } from '../../client/common/utils/platform';
|
||||
import { EditorContexts } from '../../client/datascience/constants';
|
||||
import { HistoryMessageListener } from '../../client/datascience/historyMessageListener';
|
||||
import { HistoryMessages } from '../../client/datascience/historyTypes';
|
||||
import { HistoryMessageListener } from '../../client/datascience/history/historyMessageListener';
|
||||
import { HistoryMessages } from '../../client/datascience/history/historyTypes';
|
||||
import { IHistory, IHistoryProvider, IJupyterExecution } from '../../client/datascience/types';
|
||||
import { InterpreterType, PythonInterpreter } from '../../client/interpreter/contracts';
|
||||
import { CellButton } from '../../datascience-ui/history-react/cellButton';
|
||||
|
@ -88,12 +88,13 @@ suite('History output tests', () => {
|
|||
ioc.serviceManager.addSingletonInstance<IWebPanelProvider>(IWebPanelProvider, webPanelProvider.object);
|
||||
|
||||
// Setup the webpanel provider so that it returns our dummy web panel. It will have to talk to our global JSDOM window so that the react components can link into it
|
||||
webPanelProvider.setup(p => p.create(TypeMoq.It.isAny(), TypeMoq.It.isAnyString(), TypeMoq.It.isAnyString(), TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns((listener: IWebPanelMessageListener, title: string, script: string, css: string) => {
|
||||
// Keep track of the current listener. It listens to messages through the vscode api
|
||||
webPanelListener = listener;
|
||||
webPanelProvider.setup(p => p.create(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAnyString(), TypeMoq.It.isAnyString(), TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(
|
||||
(viewColumn: ViewColumn, listener: IWebPanelMessageListener, title: string, script: string, css: string) => {
|
||||
// Keep track of the current listener. It listens to messages through the vscode api
|
||||
webPanelListener = listener;
|
||||
|
||||
// Return our dummy web panel
|
||||
return webPanel.object;
|
||||
// Return our dummy web panel
|
||||
return webPanel.object;
|
||||
});
|
||||
webPanel.setup(p => p.postMessage(TypeMoq.It.isAny())).callback((m: WebPanelMessage) => {
|
||||
window.postMessage(m, '*');
|
||||
|
|
|
@ -18,8 +18,8 @@ import { IFileSystem } from '../../client/common/platform/types';
|
|||
import { IConfigurationService, IDisposable, ILogger } from '../../client/common/types';
|
||||
import { generateCells } from '../../client/datascience/cellFactory';
|
||||
import { Commands } from '../../client/datascience/constants';
|
||||
import { HistoryCommandListener } from '../../client/datascience/historycommandlistener';
|
||||
import { HistoryProvider } from '../../client/datascience/historyProvider';
|
||||
import { HistoryCommandListener } from '../../client/datascience/history/historycommandlistener';
|
||||
import { HistoryProvider } from '../../client/datascience/history/historyProvider';
|
||||
import { JupyterExecutionFactory } from '../../client/datascience/jupyter/jupyterExecutionFactory';
|
||||
import { JupyterExporter } from '../../client/datascience/jupyter/jupyterExporter';
|
||||
import { JupyterImporter } from '../../client/datascience/jupyter/jupyterImporter';
|
||||
|
|
|
@ -10,7 +10,7 @@ import { CancellationToken } from 'vscode';
|
|||
|
||||
import { EXTENSION_ROOT_DIR } from '../../client/common/constants';
|
||||
import { IDataScienceSettings } from '../../client/common/types';
|
||||
import { HistoryMessages } from '../../client/datascience/historyTypes';
|
||||
import { HistoryMessages } from '../../client/datascience/history/historyTypes';
|
||||
import { IHistory } from '../../client/datascience/types';
|
||||
import { CellButton } from '../../datascience-ui/history-react/cellButton';
|
||||
import { MainPanel } from '../../datascience-ui/history-react/MainPanel';
|
||||
|
|
|
@ -6,7 +6,7 @@ import { mount, ReactWrapper } from 'enzyme';
|
|||
import * as React from 'react';
|
||||
import { SemVer } from 'semver';
|
||||
import * as TypeMoq from 'typemoq';
|
||||
import { Disposable, Uri } from 'vscode';
|
||||
import { Disposable, Uri, ViewColumn } from 'vscode';
|
||||
import * as vsls from 'vsls/vscode';
|
||||
|
||||
import {
|
||||
|
@ -23,8 +23,8 @@ import { IFileSystem } from '../../client/common/platform/types';
|
|||
import { createDeferred, Deferred } from '../../client/common/utils/async';
|
||||
import { Architecture } from '../../client/common/utils/platform';
|
||||
import { Commands } from '../../client/datascience/constants';
|
||||
import { HistoryMessageListener } from '../../client/datascience/historyMessageListener';
|
||||
import { HistoryMessages } from '../../client/datascience/historyTypes';
|
||||
import { HistoryMessageListener } from '../../client/datascience/history/historyMessageListener';
|
||||
import { HistoryMessages } from '../../client/datascience/history/historyTypes';
|
||||
import {
|
||||
ICodeWatcher,
|
||||
IDataScienceCommandListener,
|
||||
|
@ -117,7 +117,8 @@ suite('LiveShare tests', () => {
|
|||
result.ioc.serviceManager.addSingletonInstance<IWebPanelProvider>(IWebPanelProvider, webPanelProvider.object);
|
||||
|
||||
// Setup the webpanel provider so that it returns our dummy web panel. It will have to talk to our global JSDOM window so that the react components can link into it
|
||||
webPanelProvider.setup(p => p.create(TypeMoq.It.isAny(), TypeMoq.It.isAnyString(), TypeMoq.It.isAnyString(), TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns((listener: IWebPanelMessageListener, title: string, script: string, css: string) => {
|
||||
webPanelProvider.setup(p => p.create(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAnyString(), TypeMoq.It.isAnyString(), TypeMoq.It.isAnyString(), TypeMoq.It.isAny())).returns(
|
||||
(viewColumn: ViewColumn, listener: IWebPanelMessageListener, title: string, script: string, css: string) => {
|
||||
// Keep track of the current listener. It listens to messages through the vscode api
|
||||
result.webPanelListener = listener;
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ import { Uri } from 'vscode';
|
|||
|
||||
import { IProcessServiceFactory } from '../../client/common/process/types';
|
||||
import { CodeCssGenerator } from '../../client/datascience/codeCssGenerator';
|
||||
import { History } from '../../client/datascience/history';
|
||||
import { HistoryProvider } from '../../client/datascience/historyProvider';
|
||||
import { History } from '../../client/datascience/history/history';
|
||||
import { HistoryProvider } from '../../client/datascience/history/historyProvider';
|
||||
import { JupyterExecutionFactory } from '../../client/datascience/jupyter/jupyterExecutionFactory';
|
||||
import { JupyterImporter } from '../../client/datascience/jupyter/jupyterImporter';
|
||||
import { JupyterServerFactory } from '../../client/datascience/jupyter/jupyterServerFactory';
|
||||
|
|
|
@ -0,0 +1,708 @@
|
|||
// Type definitions for react-data-grid 4.0
|
||||
// Project: https://github.com/adazzle/react-data-grid.git
|
||||
// Definitions by: Simon Gellis <https://github.com/SupernaviX>, Kieran Peat <https://github.com/KieranPeat>, Martin Novak <https://github.com/martinnov92>, Sebastijan Grabar <https://github.com/baso53>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
// TypeScript Version: 2.8
|
||||
|
||||
// Copied here so that could fix this to work with an older version of React.
|
||||
|
||||
/// <reference types="react" />
|
||||
|
||||
declare namespace AdazzleReactDataGrid {
|
||||
interface ExcelColumn {
|
||||
editable: boolean;
|
||||
name: any;
|
||||
key: string;
|
||||
width: number;
|
||||
resizeable: boolean;
|
||||
filterable: boolean;
|
||||
}
|
||||
|
||||
interface EditorBaseProps {
|
||||
value: any;
|
||||
column: ExcelColumn;
|
||||
height: number;
|
||||
onBlur: () => void;
|
||||
onCommit: () => void;
|
||||
onCommitCancel: () => void;
|
||||
rowData: any;
|
||||
rowMetaData: any;
|
||||
}
|
||||
|
||||
interface SelectionParams<T> {
|
||||
rowIdx: number;
|
||||
row: T;
|
||||
}
|
||||
|
||||
interface GridProps<T> {
|
||||
/**
|
||||
* Gets the data to render in each row. Required.
|
||||
* Can be an array or a function that takes an index and returns an object.
|
||||
*/
|
||||
rowGetter: Array<T> | ((rowIdx: number) => T)
|
||||
/**
|
||||
* The total number of rows to render. Required.
|
||||
*/
|
||||
rowsCount: number
|
||||
/**
|
||||
* The columns to render.
|
||||
*/
|
||||
columns?: Array<Column<T>>
|
||||
|
||||
/**
|
||||
* Invoked when the user changes the value of a single cell.
|
||||
* Should update that cell's value.
|
||||
* @param e Information about the event
|
||||
*/
|
||||
onRowUpdated?: (e: RowUpdateEvent<T>) => void
|
||||
/**
|
||||
* Invoked when the user pulls down the drag handle of an editable cell.
|
||||
* Should update the values of the selected cells.
|
||||
* @param e Information about the event
|
||||
*/
|
||||
onCellsDragged?: (e: CellDragEvent) => void
|
||||
/**
|
||||
* Invoked when the user double clicks on the drag handle of an editable cell.
|
||||
* Should update the values of the cells beneath the selected cell.
|
||||
* @param e Information about the event
|
||||
*/
|
||||
onDragHandleDoubleClick?: (e: DragHandleDoubleClickEvent<T>) => void
|
||||
/**
|
||||
* Invoked when the user copies a value from one cell and pastes it into another (in the same column).
|
||||
* Should update the value of the cell in row e.toRow.
|
||||
* @param e Information about the event
|
||||
*/
|
||||
onCellCopyPaste?: (e: CellCopyPasteEvent) => void
|
||||
/**
|
||||
* Invoked after the user updates the grid rows in any way.
|
||||
* @param e Information about the event
|
||||
*/
|
||||
onGridRowsUpdated?: (e: GridRowsUpdatedEvent<T>) => void
|
||||
|
||||
/**
|
||||
* A toolbar to display above the grid.
|
||||
* Consider using the toolbar included in "react-data-grid/addons".
|
||||
*/
|
||||
toolbar?: React.ReactElement<any>
|
||||
/**
|
||||
* A context menu to disiplay when the user right-clicks a cell.
|
||||
* Consider using "react-contextmenu", included in "react-data-grid/addons".
|
||||
*/
|
||||
contextMenu?: React.ReactElement<any>
|
||||
/**
|
||||
* A react component to customize how rows are rendered.
|
||||
* If you want to define your own, consider extending ReactDataGrid.Row.
|
||||
*/
|
||||
rowRenderer?: React.ReactElement<any> | React.ComponentClass<any> | React.StatelessComponent<any>
|
||||
/**
|
||||
* A component to display when there are no rows to render.
|
||||
*/
|
||||
emptyRowsView?: React.ComponentClass<any> | React.StatelessComponent<any>
|
||||
|
||||
/**
|
||||
* The minimum width of the entire grid in pixels.
|
||||
*/
|
||||
minWidth?: number
|
||||
/**
|
||||
* The minimum height of the entire grid in pixels.
|
||||
* @default 350
|
||||
*/
|
||||
minHeight?: number
|
||||
/**
|
||||
* The height of each individual row in pixels.
|
||||
* @default 35
|
||||
*/
|
||||
rowHeight?: number
|
||||
/**
|
||||
* The height of the header row in pixels.
|
||||
* @default rowHeight
|
||||
*/
|
||||
headerRowHeight?: number
|
||||
/**
|
||||
* The height of the header filter row in pixels.
|
||||
* @default 45
|
||||
*/
|
||||
headerFiltersHeight?: number
|
||||
/**
|
||||
* The minimum width of each column in pixels.
|
||||
* @default 80
|
||||
*/
|
||||
minColumnWidth?: number
|
||||
/**
|
||||
* Invoked when a column has been resized.
|
||||
* @param index The index of the column
|
||||
* @param width The new width of the column
|
||||
*/
|
||||
onColumnResize?: (index: number, width: number) => void
|
||||
|
||||
/**
|
||||
* Controls what happens when the user navigates beyond the first or last cells.
|
||||
* 'loopOverRow' will navigate to the beginning/end of the current row.
|
||||
* 'changeRow' will navigate to the beginning of the next row or the end of the last.
|
||||
* 'none' will do nothing.
|
||||
* @default none
|
||||
*/
|
||||
cellNavigationMode?: 'none' | 'loopOverRow' | 'changeRow'
|
||||
|
||||
/**
|
||||
* Called when the user sorts the grid by some column.
|
||||
* Should update the order of the rows returned by rowGetter.
|
||||
* @param sortColumn The name of the column being sorted by
|
||||
* @param sortDirection The direction to sort ('ASC'/'DESC'/'NONE')
|
||||
*/
|
||||
onGridSort?: (sortColumn: string, sortDirection: 'ASC' | 'DESC' | 'NONE') => void
|
||||
|
||||
/**
|
||||
* Initial sorting direction
|
||||
*/
|
||||
sortDirection?: 'ASC' | 'DESC' | 'NONE'
|
||||
|
||||
/**
|
||||
* key of the initial sorted column
|
||||
*/
|
||||
sortColumn?: string
|
||||
|
||||
/**
|
||||
* Called when the user filters a column by some value.
|
||||
* Should restrict the rows in rowGetter to only things that match the filter.
|
||||
* @param filter The filter being added
|
||||
*/
|
||||
onAddFilter?: (filter: Filter) => void
|
||||
/**
|
||||
* Called when the user clears all filters.
|
||||
* Should restore the rows in rowGetter to their original state.
|
||||
*/
|
||||
onClearFilters?: () => void
|
||||
|
||||
/**
|
||||
* When set to true or 'multi', enables multiple row select.
|
||||
* When set to 'single', enables single row select.
|
||||
* When set to false or not set, disables row select.
|
||||
* @default false
|
||||
*/
|
||||
enableRowSelect?: boolean | 'single' | 'multi'
|
||||
/**
|
||||
* Called when a row is selected.
|
||||
* @param rows The (complete) current selection of rows.
|
||||
*/
|
||||
onRowSelect?: (rows: Array<T>) => void
|
||||
/**
|
||||
* A property that's unique to every row.
|
||||
* This property is required to enable row selection.
|
||||
* @default 'id'
|
||||
*/
|
||||
rowKey?: string
|
||||
|
||||
/**
|
||||
* Enables cells to be selected when clicked.
|
||||
* @default false
|
||||
*/
|
||||
enableCellSelect?: boolean
|
||||
|
||||
/**
|
||||
* Enables cells to be dragged and dropped
|
||||
* @default false
|
||||
*/
|
||||
enableDragAndDrop?: boolean
|
||||
|
||||
/**
|
||||
* Called when a cell is selected.
|
||||
* @param coordinates The row and column indices of the selected cell.
|
||||
*/
|
||||
onCellSelected?: (coordinates: {rowIdx: number, idx: number}) => void
|
||||
/**
|
||||
* Called when a cell is deselected.
|
||||
* @param coordinates The row and column indices of the deselected cell.
|
||||
*/
|
||||
onCellDeSelected?: (coordinates: {rowIdx: number, idx: number}) => void
|
||||
|
||||
/**
|
||||
* How long to wait before rendering a new row while scrolling in milliseconds.
|
||||
* @default 0
|
||||
*/
|
||||
rowScrollTimeout?: number
|
||||
/**
|
||||
* Options object for selecting rows
|
||||
*/
|
||||
rowSelection?: {
|
||||
showCheckbox?: boolean
|
||||
enableShiftSelect?: boolean
|
||||
onRowsSelected?: (rows: Array<SelectionParams<T>>) => void,
|
||||
onRowsDeselected?: (rows: Array<SelectionParams<T>>) => void,
|
||||
selectBy?: {
|
||||
indexes?: Array<number>;
|
||||
keys?: { rowKey: string, values: Array<any> };
|
||||
isSelectedKey?: string;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* A custom formatter for the select all checkbox cell
|
||||
* @default react-data-grid/src/formatters/SelectAll.js
|
||||
*/
|
||||
selectAllRenderer?: React.ComponentClass<any> | React.StatelessComponent<any>;
|
||||
/**
|
||||
* A custom formatter for select row column
|
||||
* @default AdazzleReactDataGridPlugins.Editors.CheckboxEditor
|
||||
*/
|
||||
rowActionsCell?: React.ComponentClass<any> | React.StatelessComponent<any>;
|
||||
/**
|
||||
* An event function called when a row is clicked.
|
||||
* Clicking the header row will trigger a call with -1 for the rowIdx.
|
||||
* @param rowIdx zero index number of row clicked
|
||||
* @param row object behind the row
|
||||
*/
|
||||
onRowClick?: (rowIdx: number, row: T) => void
|
||||
|
||||
/**
|
||||
* An event function called when a row is expanded with the toggle
|
||||
* @param props OnRowExpandToggle object
|
||||
*/
|
||||
onRowExpandToggle?: (props: OnRowExpandToggle ) => void
|
||||
|
||||
/**
|
||||
* Responsible for returning an Array of values that can be used for filtering
|
||||
* a column that is column.filterable and using a column.filterRenderer that
|
||||
* displays a list of options.
|
||||
* @param columnKey the column key that we are looking to pull values from
|
||||
*/
|
||||
getValidFilterValues?: (columnKey: string) => Array<any>
|
||||
|
||||
getCellActions?: (column: Column<T>, row: T) => (ActionButton | ActionMenu)[]
|
||||
}
|
||||
|
||||
type ActionButton = {
|
||||
icon: string;
|
||||
callback: () => void;
|
||||
}
|
||||
|
||||
type ActionMenu = {
|
||||
icon: string;
|
||||
actions: {
|
||||
icon: string;
|
||||
text: string;
|
||||
callback: () => void;
|
||||
}[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a specific column to be rendered.
|
||||
*/
|
||||
interface Column<T> {
|
||||
/**
|
||||
* A unique key for this column. Required.
|
||||
* Each row should have a property with this name, which contains this column's value.
|
||||
*/
|
||||
key: string
|
||||
/**
|
||||
* This column's display name. Required.
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* A custom width for this specific column.
|
||||
* @default minColumnWidth from the ReactDataGrid
|
||||
*/
|
||||
width?: number
|
||||
/**
|
||||
* Whether this column can be resized by the user.
|
||||
* @default false
|
||||
*/
|
||||
resizable?: boolean
|
||||
/**
|
||||
* Whether this column should stay fixed on the left as the user scrolls horizontally.
|
||||
* @default false
|
||||
*/
|
||||
locked?: boolean
|
||||
/**
|
||||
* Whether this column can be edited.
|
||||
* @default false
|
||||
*/
|
||||
editable?: boolean
|
||||
/**
|
||||
* Whether the rows in the grid can be sorted by this column.
|
||||
* @default false
|
||||
*/
|
||||
sortable?: boolean
|
||||
/**
|
||||
* Whether the rows in the grid can be filtered by this column.
|
||||
* @default false
|
||||
*/
|
||||
filterable?: boolean;
|
||||
/**
|
||||
* A custom formatter for this column's filter.
|
||||
*/
|
||||
filterRenderer?: React.ReactElement<any> | React.ComponentClass<any> | React.StatelessComponent<any>;
|
||||
/**
|
||||
* The editor for this column. Several editors are available in "react-data-grid/addons".
|
||||
* @default A simple text editor
|
||||
*/
|
||||
editor?:
|
||||
| React.ReactElement<EditorBaseProps>
|
||||
| React.ComponentClass<EditorBaseProps>
|
||||
| React.StatelessComponent<EditorBaseProps>;
|
||||
/**
|
||||
* A custom read-only formatter for this column. An image formatter is available in "react-data-grid/addons".
|
||||
*/
|
||||
formatter?: React.ReactElement<any> | React.ComponentClass<any> | React.StatelessComponent<any>
|
||||
/**
|
||||
* A custom formatter for this column's header.
|
||||
*/
|
||||
headerRenderer?: React.ReactElement<any> | React.ComponentClass<any> | React.StatelessComponent<any>
|
||||
/**
|
||||
* Events to be bound to the cells in this specific column.
|
||||
* Each event must respect this standard in order to work correctly:
|
||||
* @example
|
||||
* function onXxx(ev :SyntheticEvent, (rowIdx, idx, name): args)
|
||||
*/
|
||||
events?: {
|
||||
[name: string]: ColumnEventCallback
|
||||
};
|
||||
/**
|
||||
* Retrieve meta data about the row, optionally provide column as a second argument
|
||||
*/
|
||||
getRowMetaData?: (rowdata: T, column?: Column<T>) => any;
|
||||
/**
|
||||
* A class name to be applied to the cells in the column
|
||||
*/
|
||||
cellClass?: string;
|
||||
/**
|
||||
* Whether this column can be dragged (re-arranged).
|
||||
* @default false
|
||||
*/
|
||||
draggable?: boolean;
|
||||
}
|
||||
|
||||
interface ColumnEventCallback {
|
||||
/**
|
||||
* A callback for a native react event on a specific cell.
|
||||
* @param ev The react event
|
||||
* @param args The row and column coordinates of the cell, and the name of the event.
|
||||
*/
|
||||
(ev: React.SyntheticEvent<any>, args: {rowIdx: number, idx: number, name: string}): void
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a row update. Generic event type returns untyped row, use parameterized type with the row type as the parameter
|
||||
* @default T = any
|
||||
*/
|
||||
interface RowUpdateEvent<T = any> {
|
||||
/**
|
||||
* The index of the updated row.
|
||||
*/
|
||||
rowIdx: number
|
||||
/**
|
||||
* The columns that were updated and their values.
|
||||
*/
|
||||
updated: T
|
||||
/**
|
||||
* The name of the column that was updated.
|
||||
*/
|
||||
cellKey: string
|
||||
/**
|
||||
* The name of the key pressed to trigger the event ('Tab', 'Enter', etc.).
|
||||
*/
|
||||
key: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a cell drag
|
||||
*/
|
||||
interface CellDragEvent {
|
||||
/**
|
||||
* The name of the column that was dragged.
|
||||
*/
|
||||
cellKey: string
|
||||
/**
|
||||
* The row where the drag began.
|
||||
*/
|
||||
fromRow: number
|
||||
/**
|
||||
* The row where the drag ended.
|
||||
*/
|
||||
toRow: number
|
||||
/**
|
||||
* The value of the cell that was dragged.
|
||||
*/
|
||||
value: any
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a drag handle double click. Generic event type returns untyped row, use parameterized type with the row type as the parameter
|
||||
* @default T = any
|
||||
*/
|
||||
interface DragHandleDoubleClickEvent<T = any> {
|
||||
/**
|
||||
* The row where the double click occurred.
|
||||
*/
|
||||
rowIdx: number
|
||||
/**
|
||||
* The column where the double click occurred.
|
||||
*/
|
||||
idx: number
|
||||
/**
|
||||
* The values of the row.
|
||||
*/
|
||||
rowData: T
|
||||
/**
|
||||
* The double click event.
|
||||
*/
|
||||
e: React.SyntheticEvent<any>
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about a copy paste
|
||||
*/
|
||||
interface CellCopyPasteEvent {
|
||||
/**
|
||||
* The row that was pasted to.
|
||||
*/
|
||||
rowIdx: number
|
||||
/**
|
||||
* The value that was pasted.
|
||||
*/
|
||||
value: any
|
||||
/**
|
||||
* The row that was copied from.
|
||||
*/
|
||||
fromRow: number
|
||||
/**
|
||||
* The row that was pasted to.
|
||||
*/
|
||||
toRow: number
|
||||
/**
|
||||
* The key of the column where the copy paste occurred.
|
||||
*/
|
||||
cellKey: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about some update to the grid's contents. Generic event type returns untyped row, use parameterized type with the row type as the parameter
|
||||
* @default T = any
|
||||
*/
|
||||
interface GridRowsUpdatedEvent<T = any> {
|
||||
/**
|
||||
* The key of the column where the event occurred.
|
||||
*/
|
||||
cellKey: string
|
||||
/**
|
||||
* The top row affected by the event.
|
||||
*/
|
||||
fromRow: number
|
||||
/**
|
||||
* The bottom row affected by the event.
|
||||
*/
|
||||
toRow: number
|
||||
/**
|
||||
* The columns that were updated and their values.
|
||||
*/
|
||||
updated: T
|
||||
/**
|
||||
* The action that occurred to trigger this event.
|
||||
* One of 'cellUpdate', 'cellDrag', 'columnFill', or 'copyPaste'.
|
||||
*/
|
||||
action: 'cellUpdate' | 'cellDrag' | 'columnFill' | 'copyPaste'
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about the row toggler
|
||||
*/
|
||||
interface OnRowExpandToggle {
|
||||
/**
|
||||
* The name of the column group the row is in
|
||||
*/
|
||||
columnGroupName: string
|
||||
/**
|
||||
* The name of the expanded row
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* If it should expand or not
|
||||
*/
|
||||
shouldExpand: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Some filter to be applied to the grid's contents
|
||||
*/
|
||||
interface Filter {
|
||||
/**
|
||||
* The key of the column being filtered.
|
||||
*/
|
||||
columnKey: string
|
||||
/**
|
||||
* The term to filter by.
|
||||
*/
|
||||
filterTerm: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Excel-like grid component built with React, with editors, keyboard navigation, copy & paste, and the like
|
||||
* http://adazzle.github.io/react-data-grid/
|
||||
*/
|
||||
export class ReactDataGrid<T> extends React.Component<GridProps<T>> {
|
||||
/**
|
||||
* Opens the editor for the cell (idx) in the given row (rowIdx). If the column is not editable then nothing will happen.
|
||||
*/
|
||||
openCellEditor(rowIdx: number, idx: number): void;
|
||||
}
|
||||
export namespace ReactDataGrid {
|
||||
// Useful types
|
||||
export import Column = AdazzleReactDataGrid.Column;
|
||||
export import Filter = AdazzleReactDataGrid.Filter;
|
||||
|
||||
// Various events
|
||||
export import RowUpdateEvent = AdazzleReactDataGrid.RowUpdateEvent;
|
||||
export import SelectionParams = AdazzleReactDataGrid.SelectionParams;
|
||||
export import CellDragEvent = AdazzleReactDataGrid.CellDragEvent;
|
||||
export import DragHandleDoubleClickEvent = AdazzleReactDataGrid.DragHandleDoubleClickEvent;
|
||||
export import CellCopyPasteEvent = AdazzleReactDataGrid.CellCopyPasteEvent;
|
||||
export import GridRowsUpdatedEvent = AdazzleReactDataGrid.GridRowsUpdatedEvent;
|
||||
export import OnRowExpandToggle = AdazzleReactDataGrid.OnRowExpandToggle;
|
||||
|
||||
export namespace editors {
|
||||
class EditorBase<P = {}, S = {}> extends React.Component<P & EditorBaseProps, S> {
|
||||
getStyle(): { width: string };
|
||||
|
||||
getValue(): any;
|
||||
|
||||
getInputNode(): Element | null | Text;
|
||||
|
||||
inheritContainerStyles(): boolean;
|
||||
}
|
||||
}
|
||||
|
||||
// Actual classes exposed on module.exports
|
||||
/**
|
||||
* A react component that renders a row of the grid
|
||||
*/
|
||||
export class Row extends React.Component<any> { }
|
||||
/**
|
||||
* A react coponent that renders a cell of the grid
|
||||
*/
|
||||
export class Cell extends React.Component<any> { }
|
||||
}
|
||||
}
|
||||
|
||||
declare namespace AdazzleReactDataGridPlugins {
|
||||
interface AutoCompleteEditorProps {
|
||||
onCommit?: () => void;
|
||||
options?: Array<{ id: any; title: string }>;
|
||||
label?: any;
|
||||
value?: any;
|
||||
height?: number;
|
||||
valueParams?: string[];
|
||||
column?: AdazzleReactDataGrid.ExcelColumn;
|
||||
resultIdentifier?: string;
|
||||
search?: string;
|
||||
onKeyDown?: () => void;
|
||||
onFocus?: () => void;
|
||||
editorDisplayValue?: (column: AdazzleReactDataGrid.ExcelColumn, value: any) => string;
|
||||
}
|
||||
|
||||
interface AutoCompleteTokensEditorProps {
|
||||
options: Array<string | { id: number; caption: string }>;
|
||||
column?: AdazzleReactDataGrid.ExcelColumn;
|
||||
value?: any[];
|
||||
}
|
||||
|
||||
interface DropDownEditorProps {
|
||||
options:
|
||||
Array<string | {
|
||||
id: string;
|
||||
title: string;
|
||||
value: string;
|
||||
text: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export namespace Editors {
|
||||
export class AutoComplete extends React.Component<AutoCompleteEditorProps> {}
|
||||
export class AutoCompleteTokensEditor extends React.Component<AutoCompleteTokensEditorProps> {}
|
||||
export class DropDownEditor extends React.Component<DropDownEditorProps> {}
|
||||
|
||||
// TODO: refine types for these addons
|
||||
export class SimpleTextEditor extends React.Component<any> {}
|
||||
export class CheckboxEditor extends React.Component<any> {}
|
||||
}
|
||||
export namespace Filters {
|
||||
export class NumericFilter extends React.Component<any> { }
|
||||
export class AutoCompleteFilter extends React.Component<any> { }
|
||||
export class MultiSelectFilter extends React.Component<any> { }
|
||||
export class SingleSelectFilter extends React.Component<any> { }
|
||||
}
|
||||
export namespace Formatters {
|
||||
export class ImageFormatter extends React.Component<any> { }
|
||||
export class DropDownFormatter extends React.Component<any> { }
|
||||
}
|
||||
export class Toolbar extends React.Component<any> {}
|
||||
export namespace DraggableHeader {
|
||||
export class DraggableContainer extends React.Component<any>{ }
|
||||
}
|
||||
export namespace Data {
|
||||
export const Selectors: {
|
||||
getRows: (state: object) => object[];
|
||||
getSelectedRowsByKey: (state: object) => object[];
|
||||
}
|
||||
}
|
||||
// TODO: re-export the react-contextmenu typings once those exist
|
||||
// https://github.com/vkbansal/react-contextmenu/issues/10
|
||||
export namespace Menu {
|
||||
export class ContextMenu extends React.Component<any> { }
|
||||
export class MenuHeader extends React.Component<any> { }
|
||||
export class MenuItem extends React.Component<any> { }
|
||||
export class SubMenu extends React.Component<any> { }
|
||||
export const monitor: {
|
||||
getItem(): any
|
||||
getPosition(): any
|
||||
hideMenu(): void
|
||||
};
|
||||
export function connect(Menu: any): any;
|
||||
export function ContextMenuLayer(
|
||||
identifier: any,
|
||||
configure?: (props: any) => any
|
||||
): (Component: any) => any
|
||||
}
|
||||
}
|
||||
|
||||
declare module "react-data-grid" {
|
||||
import ReactDataGrid = AdazzleReactDataGrid.ReactDataGrid;
|
||||
|
||||
// commonjs export
|
||||
export = ReactDataGrid;
|
||||
}
|
||||
|
||||
declare module "react-data-grid-addons" {
|
||||
import Plugins = AdazzleReactDataGridPlugins;
|
||||
import Editors = Plugins.Editors;
|
||||
import Filters = Plugins.Filters;
|
||||
import Formatters = Plugins.Formatters;
|
||||
import Toolbar = Plugins.Toolbar;
|
||||
import Menu = Plugins.Menu;
|
||||
import Data = Plugins.Data;
|
||||
import DraggableHeader = Plugins.DraggableHeader;
|
||||
|
||||
// ES6 named exports
|
||||
export {
|
||||
Editors,
|
||||
Filters,
|
||||
Formatters,
|
||||
Toolbar,
|
||||
Menu,
|
||||
Data,
|
||||
DraggableHeader
|
||||
}
|
||||
|
||||
// attach to window
|
||||
global {
|
||||
interface Window {
|
||||
ReactDataGridPlugins: {
|
||||
Editors: typeof Editors,
|
||||
Filters: typeof Filters,
|
||||
Formatters: typeof Formatters,
|
||||
Toolbar: typeof Toolbar,
|
||||
Menu: typeof Menu,
|
||||
Data: typeof Data,
|
||||
DraggableHeader: typeof DraggableHeader
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
declare module 'react-tabulator' {
|
||||
export class React15Tabulator {
|
||||
constructor(...args: any[]);
|
||||
componentDidMount(): void;
|
||||
componentDidUpdate(): void;
|
||||
forceUpdate(callback: any): void;
|
||||
render(): any;
|
||||
setState(partialState: any, callback: any): void;
|
||||
shouldComponentUpdate(nextProps: any): any;
|
||||
props: any;
|
||||
state: any;
|
||||
context: any;
|
||||
refs: any;
|
||||
}
|
||||
export default class _default {
|
||||
constructor(...args: any[]);
|
||||
componentDidMount(): void;
|
||||
componentDidUpdate(): void;
|
||||
forceUpdate(callback: any): void;
|
||||
render(): any;
|
||||
setState(partialState: any, callback: any): void;
|
||||
shouldComponentUpdate(nextProps: any): any;
|
||||
props: any;
|
||||
state: any;
|
||||
context: any;
|
||||
refs: any;
|
||||
}
|
||||
}
|
|
@ -8,7 +8,10 @@ const datascience = require('./webpack.datascience-ui.config.js');
|
|||
const extensionDependencies = require('./build/webpack/webpack.extension.dependencies.config.js').default;
|
||||
|
||||
module.exports = [
|
||||
merge(datascience, {
|
||||
merge(datascience[0], {
|
||||
devtool: 'eval'
|
||||
}),
|
||||
merge(datascience[1], {
|
||||
devtool: 'eval'
|
||||
}),
|
||||
merge(extensionDependencies, {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
|
||||
const webpack = require('webpack');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const FixDefaultImportPlugin = require('webpack-fix-default-import-plugin');
|
||||
const path = require('path');
|
||||
|
@ -5,86 +7,176 @@ const CopyWebpackPlugin = require('copy-webpack-plugin')
|
|||
|
||||
const configFileName = 'tsconfig.datascience-ui.json';
|
||||
|
||||
module.exports = {
|
||||
entry: ['babel-polyfill', './src/datascience-ui/history-react/index.tsx'],
|
||||
output: {
|
||||
path: path.join(__dirname, 'out'),
|
||||
filename: 'datascience-ui/history-react/index_bundle.js',
|
||||
publicPath: './'
|
||||
},
|
||||
module.exports = [
|
||||
{
|
||||
entry: ['babel-polyfill', './src/datascience-ui/history-react/index.tsx'],
|
||||
output: {
|
||||
path: path.join(__dirname, 'out'),
|
||||
filename: 'datascience-ui/history-react/index_bundle.js',
|
||||
publicPath: './'
|
||||
},
|
||||
|
||||
mode: 'development', // Leave as is, we'll need to see stack traces when there are errors.
|
||||
// Use 'eval' for release and `eval-source-map` for development.
|
||||
// We need to use one where source is embedded, due to webviews (they restrict resources to specific schemes,
|
||||
// this seems to prevent chrome from downloading the source maps)
|
||||
devtool: 'eval-source-map',
|
||||
node: {
|
||||
fs: 'empty'
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({ template: 'src/datascience-ui/history-react/index.html', imageBaseUrl: `${__dirname.replace(/\\/g, '/')}/out/datascience-ui/history-react`, indexUrl: `${__dirname}/out/1`, filename: './datascience-ui/history-react/index.html' }),
|
||||
new FixDefaultImportPlugin(),
|
||||
new CopyWebpackPlugin([
|
||||
{ from: './**/*.png', to: '.' },
|
||||
{ from: './**/*.svg', to: '.' },
|
||||
{ from: './**/*.css', to: '.' },
|
||||
{ from: './**/*theme*.json', to: '.' }
|
||||
], { context: 'src' }),
|
||||
],
|
||||
resolve: {
|
||||
// Add '.ts' and '.tsx' as resolvable extensions.
|
||||
extensions: [".ts", ".tsx", ".js", ".json", ".svg"]
|
||||
},
|
||||
mode: 'development', // Leave as is, we'll need to see stack traces when there are errors.
|
||||
// Use 'eval' for release and `eval-source-map` for development.
|
||||
// We need to use one where source is embedded, due to webviews (they restrict resources to specific schemes,
|
||||
// this seems to prevent chrome from downloading the source maps)
|
||||
devtool: 'eval-source-map',
|
||||
node: {
|
||||
fs: 'empty'
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({ template: 'src/datascience-ui/history-react/index.html', imageBaseUrl: `${__dirname.replace(/\\/g, '/')}/out/datascience-ui/history-react`, indexUrl: `${__dirname}/out/1`, filename: './datascience-ui/history-react/index.html' }),
|
||||
new FixDefaultImportPlugin(),
|
||||
new CopyWebpackPlugin([
|
||||
{ from: './**/*.png', to: '.' },
|
||||
{ from: './**/*.svg', to: '.' },
|
||||
{ from: './**/*.css', to: '.' },
|
||||
{ from: './**/*theme*.json', to: '.' }
|
||||
], { context: 'src' }),
|
||||
],
|
||||
resolve: {
|
||||
// Add '.ts' and '.tsx' as resolvable extensions.
|
||||
extensions: [".ts", ".tsx", ".js", ".json", ".svg"]
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: {
|
||||
loader: "awesome-typescript-loader",
|
||||
options: {
|
||||
configFileName,
|
||||
reportFiles: [
|
||||
'src/datascience-ui/**/*.{ts,tsx}'
|
||||
]
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: {
|
||||
loader: "awesome-typescript-loader",
|
||||
options: {
|
||||
configFileName,
|
||||
reportFiles: [
|
||||
'src/datascience-ui/**/*.{ts,tsx}'
|
||||
]
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
use: [
|
||||
'svg-inline-loader'
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
'css-loader'
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
include: /node_modules.*remark.*default.*js/,
|
||||
use: [
|
||||
{
|
||||
loader: path.resolve('./build/webpack/loaders/remarkLoader.js'),
|
||||
options: {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
type: 'javascript/auto',
|
||||
include: /node_modules.*remark.*/,
|
||||
use: [
|
||||
{
|
||||
loader: path.resolve('./build/webpack/loaders/jsonloader.js'),
|
||||
options: {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
use: [
|
||||
'svg-inline-loader'
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
'css-loader'
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
include: /node_modules.*remark.*default.*js/,
|
||||
use: [
|
||||
{
|
||||
loader: path.resolve('./build/webpack/loaders/remarkLoader.js'),
|
||||
options: {}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
entry: ['babel-polyfill', './src/datascience-ui/data-explorer/index.tsx'],
|
||||
output: {
|
||||
path: path.join(__dirname, 'out'),
|
||||
filename: 'datascience-ui/data-explorer/index_bundle.js',
|
||||
publicPath: './'
|
||||
},
|
||||
|
||||
mode: 'development', // Leave as is, we'll need to see stack traces when there are errors.
|
||||
// Use 'eval' for release and `eval-source-map` for development.
|
||||
// We need to use one where source is embedded, due to webviews (they restrict resources to specific schemes,
|
||||
// this seems to prevent chrome from downloading the source maps)
|
||||
devtool: 'eval-source-map',
|
||||
node: {
|
||||
fs: 'empty'
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({ template: 'src/datascience-ui/data-explorer/index.html', imageBaseUrl: `${__dirname.replace(/\\/g, '/')}/out/datascience-ui/data-explorer`, indexUrl: `${__dirname}/out/1`, filename: './datascience-ui/data-explorer/index.html' }),
|
||||
new FixDefaultImportPlugin(),
|
||||
new CopyWebpackPlugin([
|
||||
{ from: './**/*.png', to: '.' },
|
||||
{ from: './**/*.svg', to: '.' },
|
||||
{ from: './**/*.css', to: '.' },
|
||||
{ from: './**/*theme*.json', to: '.' }
|
||||
], { context: 'src' }),
|
||||
new webpack.DefinePlugin({
|
||||
"process.env": {
|
||||
NODE_ENV: JSON.stringify("production")
|
||||
}
|
||||
})
|
||||
],
|
||||
resolve: {
|
||||
// Add '.ts' and '.tsx' as resolvable extensions.
|
||||
extensions: [".ts", ".tsx", ".js", ".json", ".svg"]
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: {
|
||||
loader: "awesome-typescript-loader",
|
||||
options: {
|
||||
configFileName,
|
||||
reportFiles: [
|
||||
'src/datascience-ui/**/*.{ts,tsx}'
|
||||
]
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
type: 'javascript/auto',
|
||||
include: /node_modules.*remark.*/,
|
||||
use: [
|
||||
{
|
||||
loader: path.resolve('./build/webpack/loaders/jsonloader.js'),
|
||||
options: {}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
use: [
|
||||
'svg-inline-loader'
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
'style-loader',
|
||||
'css-loader'
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
include: /node_modules.*remark.*default.*js/,
|
||||
use: [
|
||||
{
|
||||
loader: path.resolve('./build/webpack/loaders/remarkLoader.js'),
|
||||
options: {}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
type: 'javascript/auto',
|
||||
include: /node_modules.*remark.*/,
|
||||
use: [
|
||||
{
|
||||
loader: path.resolve('./build/webpack/loaders/jsonloader.js'),
|
||||
options: {}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
];
|
||||
|
|
Загрузка…
Ссылка в новой задаче