eclipse-theia / theia-website

Theia's Website
https://theia-ide.org/
Other
34 stars 72 forks source link

Document how to integrate React widget #26

Open akosyakov opened 5 years ago

akosyakov commented 5 years ago

it should cover using dependency injection.

Motivation: https://github.com/theia-ide/theia/issues/1251#issuecomment-475450068

dmarhas commented 5 years ago

It took me some time but I was able to get a very basic widget up. Still having trouble with sytles though. Was not able to include/import css files. I ended up using embedded styles for now. Must be something to do with Webpack configuration?

Here are the steps I followed:

  1. Created Hello World extension as described in https://www.theia-ide.org/doc/Authoring_Extensions.html - I used the following commands:
mkdir test-extension3
cd test-extension3
yo theia-extension hello-world
  1. Added the following files to test-extension3\hello-world\src\browser

Widget

//hello-world-widget.tsx
import { ReactWidget } from '@theia/core/lib/browser/widgets/react-widget';
import * as React from 'react';
import { injectable, postConstruct, inject } from 'inversify';
import { EditorManager } from "@theia/editor/lib/browser";

@injectable()
export class HelloWorldWidget extends ReactWidget {

    constructor(    @inject(EditorManager) readonly editorManager: EditorManager ) {
        super();
        this.id = 'hello-world-widget';
        this.title.label = 'Hello React World';
        this.title.closable = true;
        this.addClass('hello-world-widget');
    }

    protected render(): React.ReactNode {
        let styles = {
            backgroundColor: 'yellow',
          };
        return <React.Fragment>
                <div className="hello-world-widget" style={styles} >
                 {'Hello React World!'}
                </div>
            </React.Fragment>;
    }

    @postConstruct()
    protected init(): void {
        this.update();
    }
}

View Contribution

//hello-world-view-contribution.ts
import { injectable } from "inversify";
import { AbstractViewContribution } from '@theia/core/lib/browser';
import { HelloWorldWidget } from './hello-world-widget';

export const HELLO_WORLD_VIEW_WIDGET_FACTORY_ID = 'hello-world-widget';

@injectable()
export class HelloWorldViewContribution extends AbstractViewContribution<HelloWorldWidget> {

    constructor() {
        super({
            widgetId: HELLO_WORLD_VIEW_WIDGET_FACTORY_ID,
            widgetName: 'Hello World View',
            defaultWidgetOptions: {
                area: 'right',
                rank: 100,
            },
            toggleCommandId: 'helloWorldView:toggle',
            toggleKeybinding: 'ctrlcmd+alt+h'
        });
    }
}
  1. Modified the following files

Frontend Module

//hello-world-frontend-module.ts
/**
 * Generated using theia-extension-generator
 */

import { HelloWorldCommandContribution, HelloWorldMenuContribution } from './hello-world-contribution';
import {
    CommandContribution,
    MenuContribution
} from "@theia/core/lib/common";

import { ContainerModule } from "inversify";
import { HelloWorldWidget } from './hello-world-widget';
import { WidgetFactory, bindViewContribution } from '@theia/core/lib/browser';
import { HELLO_WORLD_VIEW_WIDGET_FACTORY_ID, HelloWorldViewContribution } from './hello-world-view-contribution';

export default new ContainerModule(bind => {

    // add your contribution bindings here
    bind(HelloWorldWidget).toSelf();
    bind(WidgetFactory).toDynamicValue(context => ({
        id: HELLO_WORLD_VIEW_WIDGET_FACTORY_ID,
        createWidget: () => context.container.get<HelloWorldWidget>(HelloWorldWidget)
    }));
    bindViewContribution(bind, HelloWorldViewContribution);
  // Added  code above

    bind(CommandContribution).to(HelloWorldCommandContribution);
    bind(MenuContribution).to(HelloWorldMenuContribution);

});

test-extension3\hello-world\tsconfig.json

{
    "compilerOptions": {
        "skipLibCheck": true,
        "declaration": true,
        "declarationMap": true,
        "noImplicitAny": true,
        "noEmitOnError": false,
        "noImplicitThis": true,
        "strictNullChecks": true,
        "esModuleInterop": true,
        "strict": true,
        "experimentalDecorators": true,
        "noUnusedLocals": true,
        "emitDecoratorMetadata": true,
        "downlevelIteration": true,
        "module": "commonjs",
        "moduleResolution": "node",
        "target": "es5",
        "lib": [
            "es6",
            "dom"
        ],
        "sourceMap": true,
        "rootDir": "src",
        "outDir": "lib",
        "jsx": "react"
    },
    "include": [
        "src"
    ],
    "files": [
        "../node_modules/@theia/monaco/src/typings/monaco/index.d.ts"
    ]
}

test-extension3\browser-app\package.json

{
  "private": true,
  "name": "browser-app",
  "version": "0.0.0",
  "dependencies": {
    "@theia/callhierarchy": "latest",
    "@theia/core": "latest",
    "@theia/cpp": "latest",
    "@theia/editor": "latest",
    "@theia/editorconfig": "latest",
    "@theia/extension-manager": "latest",
    "@theia/file-search": "latest",
    "@theia/filesystem": "latest",
    "@theia/git": "latest",
    "@theia/java": "latest",
    "@theia/keymaps": "latest",
    "@theia/languages": "latest",
    "@theia/markers": "latest",
    "@theia/merge-conflicts": "latest",
    "@theia/messages": "latest",
    "@theia/metrics": "latest",
    "@theia/mini-browser": "latest",
    "@theia/monaco": "latest",
    "@theia/navigator": "latest",
    "@theia/outline-view": "latest",
    "@theia/output": "latest",
    "@theia/plugin-ext": "latest",
    "@theia/plugin-ext-vscode": "latest",
    "@theia/preferences": "latest",
    "@theia/preview": "latest",
    "@theia/process": "latest",
    "@theia/python": "latest",
    "@theia/search-in-workspace": "latest",
    "@theia/task": "latest",
    "@theia/terminal": "latest",
    "@theia/textmate-grammars": "latest",
    "@theia/typescript": "latest",
    "@theia/userstorage": "latest",
    "@theia/variable-resolver": "latest",
    "@theia/workspace": "latest",
    "hello-world": "0.0.0"
  },
  "devDependencies": {
    "raw-loader": "^0.5.1",
    "less": "^2.7.2",
    "less-loader": "^4.0.5",
    "style-loader": "^0.23.1",
    "css-loader": "^2.1.1",
    "@theia/cli": "latest"
  },
  "scripts": {
    "prepare": "theia build --mode development",    
    "start": "theia start",
    "watch": "theia build --watch --mode development"
  },
  "theia": {
    "target": "browser"
  }
}
  1. Run the build from extension root directory (test-extension3)
    
    yarn install
    cd browser-app
    yarn start --startup-timeout 10000
ghewadesumit commented 4 years ago

Is there a document available to create a react application in theia ide