Skip to content

Commit 3fcf5a6

Browse files
Akos Kittajbicker
Akos Kitta
authored andcommitted
generalized the boards and the libraries views.
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
1 parent b24d440 commit 3fcf5a6

24 files changed

+303
-443
lines changed

arduino-ide-extension/src/browser/arduino-frontend-module.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { ArduinoLanguageGrammarContribution } from './language/arduino-language-
1313
import { LibraryService, LibraryServicePath } from '../common/protocol/library-service';
1414
import { BoardsService, BoardsServicePath, BoardsServiceClient } from '../common/protocol/boards-service';
1515
import { SketchesService, SketchesServicePath } from '../common/protocol/sketches-service';
16-
import { LibraryListWidgetFrontendContribution } from './library/list-widget-frontend-contribution';
1716
import { CoreService, CoreServicePath } from '../common/protocol/core-service';
1817
import { BoardsListWidget } from './boards/boards-list-widget';
1918
import { BoardsListWidgetFrontendContribution } from './boards/boards-widget-frontend-contribution';
@@ -52,6 +51,9 @@ import { ScmContribution } from '@theia/scm/lib/browser/scm-contribution';
5251
import { SilentScmContribution } from './customization/silent-scm-contribution';
5352
import { SearchInWorkspaceFrontendContribution } from '@theia/search-in-workspace/lib/browser/search-in-workspace-frontend-contribution';
5453
import { SilentSearchInWorkspaceContribution } from './customization/silent-search-in-workspace-contribution';
54+
import { LibraryListWidgetFrontendContribution } from './library/library-widget-frontend-contribution';
55+
import { LibraryItemRenderer } from './library/library-item-renderer';
56+
import { BoardItemRenderer } from './boards/boards-item-renderer';
5557
const ElementQueries = require('css-element-queries/src/ElementQueries');
5658

5759
if (!ARDUINO_PRO_MODE) {
@@ -87,6 +89,7 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un
8789
createWidget: () => context.container.get(LibraryListWidget)
8890
}));
8991
bind(FrontendApplicationContribution).toService(LibraryListWidgetFrontendContribution);
92+
bind(LibraryItemRenderer).toSelf().inSingletonScope();
9093

9194
// Sketch list service
9295
bind(SketchesService).toDynamicValue(context => WebSocketConnectionProvider.createProxy(context.container, SketchesServicePath)).inSingletonScope();
@@ -113,6 +116,7 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un
113116
createWidget: () => context.container.get(BoardsListWidget)
114117
}));
115118
bind(FrontendApplicationContribution).toService(BoardsListWidgetFrontendContribution);
119+
bind(BoardItemRenderer).toSelf().inSingletonScope();
116120

117121
// Board select dialog
118122
bind(BoardsConfigDialogWidget).toSelf().inSingletonScope();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import * as React from 'react';
2+
import { injectable } from 'inversify';
3+
import { ListItemRenderer } from '../components/component-list/list-item-renderer';
4+
import { BoardPackage } from '../../common/protocol/boards-service';
5+
6+
@injectable()
7+
export class BoardItemRenderer extends ListItemRenderer<BoardPackage> {
8+
9+
renderItem(item: BoardPackage, install: (item: BoardPackage) => Promise<void>): React.ReactNode {
10+
const name = <span className='name'>{item.name}</span>;
11+
const author = <span className='author'>{item.author}</span>;
12+
const installedVersion = !!item.installedVersion && <div className='version-info'>
13+
<span className='version'>Version {item.installedVersion}</span>
14+
<span className='installed'>INSTALLED</span>
15+
</div>;
16+
17+
const summary = <div className='summary'>{item.summary}</div>;
18+
19+
const moreInfo = !!item.moreInfoLink && <a href={item.moreInfoLink} onClick={this.onClick}>More info</a>;
20+
const installButton = item.installable && !item.installedVersion &&
21+
<button className='install' onClick={install.bind(this, item)}>INSTALL</button>;
22+
23+
return <div className='component-list-item noselect'>
24+
<div className='header'>
25+
<span>{name} by {author}</span>
26+
{installedVersion}
27+
</div>
28+
<div className='content'>
29+
{summary}
30+
</div>
31+
<div className='footer'>
32+
{moreInfo}
33+
{installButton}
34+
</div>
35+
</div>;
36+
}
37+
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { inject, injectable } from 'inversify';
2+
import { BoardPackage, BoardsService } from '../../common/protocol/boards-service';
3+
import { ListWidget } from '../components/component-list/list-widget';
4+
import { BoardItemRenderer } from './boards-item-renderer';
5+
6+
@injectable()
7+
export class BoardsListWidget extends ListWidget<BoardPackage> {
8+
9+
static WIDGET_ID = 'boards-list-widget';
10+
static WIDGET_LABEL = 'Boards Manager';
11+
12+
constructor(
13+
@inject(BoardsService) protected service: BoardsService,
14+
@inject(BoardItemRenderer) protected itemRenderer: BoardItemRenderer) {
15+
16+
super({
17+
id: BoardsListWidget.WIDGET_ID,
18+
label: BoardsListWidget.WIDGET_LABEL,
19+
iconClass: 'fa fa-microchip',
20+
searchable: service,
21+
installable: service,
22+
itemLabel: (item: BoardPackage) => item.name,
23+
itemRenderer
24+
});
25+
}
26+
27+
}

arduino-ide-extension/src/browser/boards/boards-list-widget.tsx

-16
This file was deleted.

arduino-ide-extension/src/browser/boards/boards-widget-frontend-contribution.ts

+4-14
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,12 @@
11
import { injectable } from 'inversify';
2-
import { FrontendApplicationContribution } from '@theia/core/lib/browser/frontend-application';
3-
import { AbstractViewContribution } from '@theia/core/lib/browser/shell/view-contribution';
4-
import { ListWidget } from './list-widget';
5-
import { BoardsListWidget } from './boards-list-widget';
62
import { MenuModelRegistry } from '@theia/core';
3+
import { BoardsListWidget } from './boards-list-widget';
74
import { ArduinoMenus } from '../arduino-frontend-contribution';
5+
import { BoardPackage } from '../../common/protocol/boards-service';
6+
import { ListWidgetFrontendContribution } from '../components/component-list/list-widget-frontend-contribution';
87

98
@injectable()
10-
export abstract class ListWidgetFrontendContribution extends AbstractViewContribution<ListWidget> implements FrontendApplicationContribution {
11-
12-
async initializeLayout(): Promise<void> {
13-
// await this.openView();
14-
}
15-
16-
}
17-
18-
@injectable()
19-
export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendContribution {
9+
export class BoardsListWidgetFrontendContribution extends ListWidgetFrontendContribution<BoardPackage> {
2010

2111
static readonly OPEN_MANAGER = `${BoardsListWidget.WIDGET_ID}:toggle`;
2212

arduino-ide-extension/src/browser/boards/list-widget.tsx

-76
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,25 @@
11
import * as React from 'react';
2-
import { WindowService } from '@theia/core/lib/browser/window/window-service';
3-
import { ArduinoComponent } from '../../../common/protocol/arduino-component';
2+
import { ListItemRenderer } from './list-item-renderer';
43

5-
export class ComponentListItem extends React.Component<ComponentListItem.Props> {
4+
export class ComponentListItem<T> extends React.Component<ComponentListItem.Props<T>> {
65

7-
protected onClick = (event: React.SyntheticEvent<HTMLAnchorElement, Event>) => {
8-
const { target } = event.nativeEvent;
9-
if (target instanceof HTMLAnchorElement) {
10-
this.props.windowService.openNewWindow(target.href);
11-
event.nativeEvent.preventDefault();
12-
}
13-
}
14-
15-
protected async install(item: ArduinoComponent): Promise<void> {
6+
protected async install(item: T): Promise<void> {
167
await this.props.install(item);
178
}
189

1910
render(): React.ReactNode {
20-
const { item } = this.props;
21-
22-
const style = ComponentListItem.Styles;
23-
const name = <span className={style.NAME_CLASS}>{item.name}</span>;
24-
const author = <span className={style.AUTHOR_CLASS}>{item.author}</span>;
25-
const installedVersion = !!item.installedVersion && <div className={style.VERSION_INFO_CLASS}>
26-
<span className={style.VERSION_CLASS}>Version {item.installedVersion}</span>
27-
<span className={style.INSTALLED_CLASS}>INSTALLED</span>
28-
</div>;
29-
30-
const summary = <div className={style.SUMMARY_CLASS}>{item.summary}</div>;
31-
32-
const moreInfo = !!item.moreInfoLink && <a href={item.moreInfoLink} onClick={this.onClick}>More info</a>;
33-
const install = this.props.install && item.installable && !item.installedVersion &&
34-
<button className={style.INSTALL_BTN_CLASS} onClick={this.install.bind(this, item)}>INSTALL</button>;
35-
36-
return <div className={[style.LIST_ITEM_CLASS, style.NO_SELECT_CLASS].join(' ')}>
37-
<div className={style.HEADER_CLASS}>
38-
<span>{name} by {author}</span>
39-
{installedVersion}
40-
</div>
41-
<div className={style.CONTENT_CLASS}>
42-
{summary}
43-
</div>
44-
<div className={style.FOOTER_CLASS}>
45-
{moreInfo}
46-
{install}
47-
</div>
48-
</div>;
11+
const { item, itemRenderer, install } = this.props;
12+
return itemRenderer.renderItem(item, install.bind(this));
4913
}
5014

5115
}
5216

5317
export namespace ComponentListItem {
5418

55-
export interface Props {
56-
readonly item: ArduinoComponent;
57-
readonly windowService: WindowService;
58-
readonly install: (comp: ArduinoComponent) => Promise<void>;
59-
}
60-
61-
export namespace Styles {
62-
export const LIST_ITEM_CLASS = 'component-list-item';
63-
export const HEADER_CLASS = 'header';
64-
export const VERSION_INFO_CLASS = 'version-info';
65-
export const CONTENT_CLASS = 'content';
66-
export const FOOTER_CLASS = 'footer';
67-
export const INSTALLED_CLASS = 'installed';
68-
export const NO_SELECT_CLASS = 'noselect';
69-
70-
export const NAME_CLASS = 'name';
71-
export const AUTHOR_CLASS = 'author';
72-
export const VERSION_CLASS = 'version';
73-
export const SUMMARY_CLASS = 'summary';
74-
export const DESCRIPTION_CLASS = 'description';
75-
export const INSTALL_BTN_CLASS = 'install';
19+
export interface Props<T> {
20+
readonly item: T;
21+
readonly install: (item: T) => Promise<void>;
22+
readonly itemRenderer: ListItemRenderer<T>;
7623
}
7724

7825
}
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import * as React from 'react';
2-
import { WindowService } from '@theia/core/lib/browser/window/window-service';
32
import { ComponentListItem } from './component-list-item';
4-
import { ArduinoComponent } from '../../../common/protocol/arduino-component';
3+
import { ListItemRenderer } from './list-item-renderer';
54

6-
export class ComponentList extends React.Component<ComponentList.Props> {
5+
export class ComponentList<T> extends React.Component<ComponentList.Props<T>> {
76

87
protected container?: HTMLElement;
98

109
render(): React.ReactNode {
1110
return <div
1211
className={'items-container'}
13-
ref={element => this.container = element || undefined}>
12+
ref={this.setRef}>
1413
{this.props.items.map(item => this.createItem(item))}
1514
</div>;
1615
}
@@ -21,19 +20,28 @@ export class ComponentList extends React.Component<ComponentList.Props> {
2120
}
2221
}
2322

24-
protected createItem(item: ArduinoComponent): React.ReactNode {
25-
return <ComponentListItem key={item.name} item={item} windowService={this.props.windowService} install={this.props.install} />
23+
protected setRef = (element: HTMLElement | null) => {
24+
this.container = element || undefined;
25+
}
26+
27+
protected createItem(item: T): React.ReactNode {
28+
return <ComponentListItem<T>
29+
key={this.props.itemLabel(item)}
30+
item={item}
31+
itemRenderer={this.props.itemRenderer}
32+
install={this.props.install} />
2633
}
2734

2835
}
2936

3037
export namespace ComponentList {
3138

32-
export interface Props {
33-
readonly items: ArduinoComponent[];
34-
readonly windowService: WindowService;
35-
readonly install: (comp: ArduinoComponent) => Promise<void>;
36-
readonly resolveContainer?: (element: HTMLElement) => void;
39+
export interface Props<T> {
40+
readonly items: T[];
41+
readonly itemLabel: (item: T) => string;
42+
readonly itemRenderer: ListItemRenderer<T>;
43+
readonly install: (item: T) => Promise<void>;
44+
readonly resolveContainer: (element: HTMLElement) => void;
3745
}
3846

3947
}

0 commit comments

Comments
 (0)