mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-07-24 11:46:32 +00:00
Implemented the Widget
Re-introduced bottom panel tabs Signed-off-by: jbicker <jan.bicker@typefox.io>
This commit is contained in:
parent
206b65f138
commit
76d0f5a464
@ -23,7 +23,9 @@
|
||||
"@theia/search-in-workspace": "next",
|
||||
"@types/ps-tree": "^1.1.0",
|
||||
"@types/which": "^1.3.1",
|
||||
"@types/react-select": "^3.0.0",
|
||||
"css-element-queries": "^1.2.0",
|
||||
"react-select": "^3.0.4",
|
||||
"p-queue": "^5.0.0",
|
||||
"ps-tree": "^1.2.0",
|
||||
"tree-kill": "^1.2.1",
|
||||
|
@ -47,6 +47,7 @@ import { BoardsToolBarItem } from './boards/boards-toolbar-item';
|
||||
import { BoardsConfig } from './boards/boards-config';
|
||||
import { MonitorService } from '../common/protocol/monitor-service';
|
||||
import { ConfigService } from '../common/protocol/config-service';
|
||||
import { MonitorConnection } from './monitor/monitor-connection';
|
||||
|
||||
export namespace ArduinoMenus {
|
||||
export const SKETCH = [...MAIN_MENU_BAR, '3_sketch'];
|
||||
@ -143,6 +144,8 @@ export class ArduinoFrontendContribution implements TabBarToolbarContribution, C
|
||||
|
||||
@inject(ConfigService)
|
||||
protected readonly configService: ConfigService;
|
||||
@inject(MonitorConnection)
|
||||
protected readonly monitorConnection: MonitorConnection;
|
||||
|
||||
protected boardsToolbarItem: BoardsToolBarItem | null;
|
||||
protected wsSketchCount: number = 0;
|
||||
@ -244,6 +247,9 @@ export class ArduinoFrontendContribution implements TabBarToolbarContribution, C
|
||||
return;
|
||||
}
|
||||
|
||||
const connectionConfig = this.monitorConnection.connectionConfig;
|
||||
await this.monitorConnection.disconnect();
|
||||
|
||||
try {
|
||||
const { boardsConfig } = this.boardsServiceClient;
|
||||
if (!boardsConfig || !boardsConfig.selectedBoard) {
|
||||
@ -256,6 +262,10 @@ export class ArduinoFrontendContribution implements TabBarToolbarContribution, C
|
||||
await this.coreService.upload({ uri: uri.toString(), board: boardsConfig.selectedBoard, port: selectedPort });
|
||||
} catch (e) {
|
||||
await this.messageService.error(e.toString());
|
||||
} finally {
|
||||
if (connectionConfig) {
|
||||
await this.monitorConnection.connect(connectionConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -57,12 +57,12 @@ import { BoardItemRenderer } from './boards/boards-item-renderer';
|
||||
import { MonitorServiceClientImpl } from './monitor/monitor-service-client-impl';
|
||||
import { MonitorServicePath, MonitorService, MonitorServiceClient } from '../common/protocol/monitor-service';
|
||||
import { ConfigService, ConfigServicePath } from '../common/protocol/config-service';
|
||||
import { MonitorWidget } from './monitor/monitor-widget';
|
||||
import { MonitorViewContribution } from './monitor/monitor-view-contribution';
|
||||
import { MonitorConnection } from './monitor/monitor-connection';
|
||||
import { MonitorModel } from './monitor/monitor-model';
|
||||
const ElementQueries = require('css-element-queries/src/ElementQueries');
|
||||
|
||||
if (!ARDUINO_PRO_MODE) {
|
||||
require('../../src/browser/style/silent-bottom-panel-tabs.css');
|
||||
}
|
||||
|
||||
export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Unbind, isBound: interfaces.IsBound, rebind: interfaces.Rebind) => {
|
||||
ElementQueries.listen();
|
||||
ElementQueries.init();
|
||||
@ -155,12 +155,23 @@ export default new ContainerModule((bind: interfaces.Bind, unbind: interfaces.Un
|
||||
return workspaceServiceExt;
|
||||
});
|
||||
|
||||
// Serial Monitor
|
||||
bind(MonitorModel).toSelf().inSingletonScope();
|
||||
bind(MonitorWidget).toSelf();
|
||||
bindViewContribution(bind, MonitorViewContribution);
|
||||
bind(TabBarToolbarContribution).toService(MonitorViewContribution);
|
||||
bind(WidgetFactory).toDynamicValue(context => ({
|
||||
id: MonitorWidget.ID,
|
||||
createWidget: () => context.container.get(MonitorWidget)
|
||||
}));
|
||||
// Frontend binding for the monitor service.
|
||||
bind(MonitorService).toDynamicValue(context => {
|
||||
const connection = context.container.get(WebSocketConnectionProvider);
|
||||
const client = context.container.get(MonitorServiceClientImpl);
|
||||
return connection.createProxy(MonitorServicePath, client);
|
||||
}).inSingletonScope();
|
||||
// MonitorConnection
|
||||
bind(MonitorConnection).toSelf().inSingletonScope();
|
||||
// Monitor service client to receive and delegate notifications from the backend.
|
||||
bind(MonitorServiceClientImpl).toSelf().inSingletonScope();
|
||||
bind(MonitorServiceClient).toDynamicValue(context => {
|
||||
|
@ -0,0 +1,60 @@
|
||||
import { injectable, inject } from "inversify";
|
||||
import { MonitorService, ConnectionConfig } from "../../common/protocol/monitor-service";
|
||||
import { Emitter, Event } from "@theia/core";
|
||||
|
||||
@injectable()
|
||||
export class MonitorConnection {
|
||||
|
||||
@inject(MonitorService)
|
||||
protected readonly monitorService: MonitorService;
|
||||
|
||||
protected _connectionId: string | undefined;
|
||||
|
||||
protected _connectionConfig: ConnectionConfig;
|
||||
|
||||
protected readonly onConnectionChangedEmitter = new Emitter<string | undefined>();
|
||||
readonly onConnectionChanged: Event<string | undefined> = this.onConnectionChangedEmitter.event;
|
||||
|
||||
get connectionId(): string | undefined {
|
||||
return this._connectionId;
|
||||
}
|
||||
|
||||
set connectionId(cid: string | undefined) {
|
||||
this._connectionId = cid;
|
||||
}
|
||||
|
||||
get connectionConfig(): ConnectionConfig {
|
||||
return this._connectionConfig;
|
||||
}
|
||||
|
||||
async connect(config: ConnectionConfig): Promise<string | undefined> {
|
||||
if (this._connectionId) {
|
||||
await this.disconnect();
|
||||
}
|
||||
const { connectionId } = await this.monitorService.connect(config);
|
||||
this._connectionId = connectionId;
|
||||
this._connectionConfig = config;
|
||||
|
||||
this.onConnectionChangedEmitter.fire(this._connectionId);
|
||||
|
||||
return connectionId;
|
||||
}
|
||||
|
||||
async disconnect(): Promise<boolean> {
|
||||
let result = true;
|
||||
const connections = await this.monitorService.getConnectionIds();
|
||||
if (this._connectionId && connections.findIndex(id => id === this._connectionId) >= 0) {
|
||||
console.log('>>> Disposing existing monitor connection before establishing a new one...');
|
||||
result = await this.monitorService.disconnect(this._connectionId);
|
||||
if (!result) {
|
||||
// TODO: better!!!
|
||||
console.error(`Could not close connection: ${this._connectionId}. Check the backend logs.`);
|
||||
} else {
|
||||
console.log(`<<< Disposed ${this._connectionId} connection.`);
|
||||
this._connectionId = undefined;
|
||||
}
|
||||
this.onConnectionChangedEmitter.fire(this._connectionId);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
31
arduino-ide-extension/src/browser/monitor/monitor-model.ts
Normal file
31
arduino-ide-extension/src/browser/monitor/monitor-model.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { injectable } from "inversify";
|
||||
import { Emitter } from "@theia/core";
|
||||
|
||||
@injectable()
|
||||
export class MonitorModel {
|
||||
|
||||
protected readonly onChangeEmitter = new Emitter<void>();
|
||||
|
||||
readonly onChange = this.onChangeEmitter.event;
|
||||
|
||||
protected _autoscroll: boolean = true;
|
||||
protected _timestamp: boolean = false;
|
||||
|
||||
get autoscroll(): boolean {
|
||||
return this._autoscroll;
|
||||
}
|
||||
|
||||
get timestamp(): boolean {
|
||||
return this._timestamp;
|
||||
}
|
||||
|
||||
toggleAutoscroll(): void {
|
||||
this._autoscroll = !this._autoscroll;
|
||||
this.onChangeEmitter.fire(undefined);
|
||||
}
|
||||
|
||||
toggleTimestamp(): void {
|
||||
this._timestamp = !this._timestamp;
|
||||
this.onChangeEmitter.fire(undefined);
|
||||
}
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
import * as React from 'react';
|
||||
import { injectable, inject } from "inversify";
|
||||
import { AbstractViewContribution } from "@theia/core/lib/browser";
|
||||
import { MonitorWidget } from "./monitor-widget";
|
||||
import { MenuModelRegistry, Command, CommandRegistry } from "@theia/core";
|
||||
import { ArduinoMenus } from "../arduino-frontend-contribution";
|
||||
import { TabBarToolbarContribution, TabBarToolbarRegistry } from "@theia/core/lib/browser/shell/tab-bar-toolbar";
|
||||
import { MonitorModel } from './monitor-model';
|
||||
|
||||
export namespace SerialMonitor {
|
||||
export namespace Commands {
|
||||
export const AUTOSCROLL: Command = {
|
||||
id: 'serial-monitor-autoscroll',
|
||||
label: 'Autoscroll'
|
||||
}
|
||||
export const TIMESTAMP: Command = {
|
||||
id: 'serial-monitor-timestamp',
|
||||
label: 'Timestamp'
|
||||
}
|
||||
export const CLEAR_OUTPUT: Command = {
|
||||
id: 'serial-monitor-clear-output',
|
||||
label: 'Clear Output',
|
||||
iconClass: 'clear-all'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class MonitorViewContribution extends AbstractViewContribution<MonitorWidget> implements TabBarToolbarContribution {
|
||||
|
||||
static readonly OPEN_SERIAL_MONITOR = MonitorWidget.ID + ':toggle';
|
||||
|
||||
@inject(MonitorModel) protected readonly model: MonitorModel;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
widgetId: MonitorWidget.ID,
|
||||
widgetName: 'Serial Monitor',
|
||||
defaultWidgetOptions: {
|
||||
area: 'bottom'
|
||||
},
|
||||
toggleCommandId: MonitorViewContribution.OPEN_SERIAL_MONITOR,
|
||||
toggleKeybinding: 'ctrl+shift+m'
|
||||
})
|
||||
}
|
||||
|
||||
registerMenus(menus: MenuModelRegistry): void {
|
||||
if (this.toggleCommand) {
|
||||
menus.registerMenuAction(ArduinoMenus.TOOLS, {
|
||||
commandId: this.toggleCommand.id,
|
||||
label: 'Serial Monitor'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async registerToolbarItems(registry: TabBarToolbarRegistry) {
|
||||
registry.registerItem({
|
||||
id: 'monitor-autoscroll',
|
||||
tooltip: 'Toggle Autoscroll',
|
||||
render: () => this.renderAutoScrollButton(),
|
||||
isVisible: widget => widget instanceof MonitorWidget,
|
||||
onDidChange: this.model.onChange
|
||||
});
|
||||
registry.registerItem({
|
||||
id: 'monitor-timestamp',
|
||||
tooltip: 'Toggle Timestamp',
|
||||
render: () => this.renderTimestampButton(),
|
||||
isVisible: widget => widget instanceof MonitorWidget,
|
||||
onDidChange: this.model.onChange
|
||||
});
|
||||
registry.registerItem({
|
||||
id: SerialMonitor.Commands.CLEAR_OUTPUT.id,
|
||||
command: SerialMonitor.Commands.CLEAR_OUTPUT.id,
|
||||
tooltip: 'Clear Output'
|
||||
});
|
||||
}
|
||||
|
||||
registerCommands(commands: CommandRegistry): void {
|
||||
super.registerCommands(commands);
|
||||
commands.registerCommand(SerialMonitor.Commands.CLEAR_OUTPUT, {
|
||||
isEnabled: widget => widget instanceof MonitorWidget,
|
||||
isVisible: widget => widget instanceof MonitorWidget,
|
||||
execute: widget => {
|
||||
if (widget instanceof MonitorWidget) {
|
||||
widget.clear();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected renderAutoScrollButton(): React.ReactNode {
|
||||
|
||||
return <React.Fragment>
|
||||
<div
|
||||
className={`item enabled fa fa-angle-double-down arduino-monitor ${this.model.autoscroll ? 'toggled' : ''}`}
|
||||
onClick={this.toggleAutoScroll}
|
||||
></div>
|
||||
</React.Fragment>;
|
||||
}
|
||||
|
||||
protected readonly toggleAutoScroll = () => this.doToggleAutoScroll();
|
||||
protected async doToggleAutoScroll() {
|
||||
this.model.toggleAutoscroll();
|
||||
}
|
||||
|
||||
protected renderTimestampButton(): React.ReactNode {
|
||||
|
||||
return <React.Fragment>
|
||||
<div
|
||||
className={`item enabled fa fa-clock-o arduino-monitor ${this.model.timestamp ? 'toggled' : ''}`}
|
||||
onClick={this.toggleTimestamp}
|
||||
></div>
|
||||
</React.Fragment>;
|
||||
}
|
||||
|
||||
protected readonly toggleTimestamp = () => this.doToggleTimestamp();
|
||||
protected async doToggleTimestamp() {
|
||||
this.model.toggleTimestamp();
|
||||
}
|
||||
}
|
346
arduino-ide-extension/src/browser/monitor/monitor-widget.tsx
Normal file
346
arduino-ide-extension/src/browser/monitor/monitor-widget.tsx
Normal file
@ -0,0 +1,346 @@
|
||||
import { ReactWidget, Message } from "@theia/core/lib/browser";
|
||||
import { postConstruct, injectable, inject } from "inversify";
|
||||
import * as React from 'react';
|
||||
import Select, { components } from 'react-select';
|
||||
import { Styles } from "react-select/src/styles";
|
||||
import { ThemeConfig } from "react-select/src/theme";
|
||||
import { OptionsType } from "react-select/src/types";
|
||||
import { MonitorServiceClientImpl } from "./monitor-service-client-impl";
|
||||
import { MessageService } from "@theia/core";
|
||||
import { ConnectionConfig, MonitorService } from "../../common/protocol/monitor-service";
|
||||
import { MonitorConnection } from "./monitor-connection";
|
||||
import { BoardsServiceClientImpl } from "../boards/boards-service-client-impl";
|
||||
import { AttachedSerialBoard, BoardsService, Board } from "../../common/protocol/boards-service";
|
||||
import { BoardsConfig } from "../boards/boards-config";
|
||||
import { MonitorModel } from "./monitor-model";
|
||||
|
||||
export namespace SerialMonitorSendField {
|
||||
export interface Props {
|
||||
onSend: (text: string) => void
|
||||
}
|
||||
|
||||
export interface State {
|
||||
value: string;
|
||||
}
|
||||
}
|
||||
|
||||
export class SerialMonitorSendField extends React.Component<SerialMonitorSendField.Props, SerialMonitorSendField.State> {
|
||||
constructor(props: SerialMonitorSendField.Props) {
|
||||
super(props);
|
||||
this.state = { value: '' };
|
||||
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <React.Fragment>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<input type='text' id='serial-monitor-send' autoComplete='off' value={this.state.value} onChange={this.handleChange} />
|
||||
<input className="btn" type="submit" value="Submit" />
|
||||
</form>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
||||
protected handleChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
this.setState({ value: event.target.value });
|
||||
}
|
||||
|
||||
protected handleSubmit(event: React.FormEvent<HTMLFormElement>) {
|
||||
this.props.onSend(this.state.value);
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
export namespace SerialMonitorOutput {
|
||||
export interface Props {
|
||||
lines: string[];
|
||||
model: MonitorModel;
|
||||
}
|
||||
}
|
||||
|
||||
export class SerialMonitorOutput extends React.Component<SerialMonitorOutput.Props> {
|
||||
protected theEnd: HTMLDivElement | null;
|
||||
|
||||
render() {
|
||||
let result = '';
|
||||
|
||||
const style: React.CSSProperties = {
|
||||
whiteSpace: 'pre',
|
||||
fontFamily: 'monospace',
|
||||
};
|
||||
|
||||
for (let text of this.props.lines) {
|
||||
result += text;
|
||||
}
|
||||
if (result.length === 0) {
|
||||
result = '';
|
||||
}
|
||||
return <React.Fragment>
|
||||
<div style={style}>{result}</div>
|
||||
<div style={{ float: "left", clear: "both" }}
|
||||
ref={(el) => { this.theEnd = el; }}>
|
||||
</div>
|
||||
</React.Fragment>;
|
||||
}
|
||||
|
||||
protected scrollToBottom() {
|
||||
if (this.theEnd) {
|
||||
this.theEnd.scrollIntoView();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.model.autoscroll) {
|
||||
this.scrollToBottom();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.props.model.autoscroll) {
|
||||
this.scrollToBottom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface SelectOption {
|
||||
label: string;
|
||||
value: string | number;
|
||||
}
|
||||
|
||||
@injectable()
|
||||
export class MonitorWidget extends ReactWidget {
|
||||
|
||||
static readonly ID = 'serial-monitor';
|
||||
|
||||
protected lines: string[];
|
||||
protected tempData: string;
|
||||
protected _baudRate: number;
|
||||
protected _lineEnding: string;
|
||||
|
||||
constructor(
|
||||
@inject(MonitorServiceClientImpl) protected readonly serviceClient: MonitorServiceClientImpl,
|
||||
@inject(MonitorConnection) protected readonly connection: MonitorConnection,
|
||||
@inject(MonitorService) protected readonly monitorService: MonitorService,
|
||||
@inject(BoardsServiceClientImpl) protected readonly boardsServiceClient: BoardsServiceClientImpl,
|
||||
@inject(MessageService) protected readonly messageService: MessageService,
|
||||
@inject(BoardsService) protected readonly boardsService: BoardsService,
|
||||
@inject(MonitorModel) protected readonly model: MonitorModel
|
||||
) {
|
||||
super();
|
||||
|
||||
this.id = MonitorWidget.ID;
|
||||
this.title.label = 'Serial Monitor';
|
||||
|
||||
this.lines = [];
|
||||
this.tempData = '';
|
||||
this._lineEnding = '\n';
|
||||
|
||||
this.toDisposeOnDetach.push(serviceClient.onRead(({ data, connectionId }) => {
|
||||
this.tempData += data;
|
||||
if (this.tempData.endsWith('\n')) {
|
||||
if (this.model.timestamp) {
|
||||
const nu = new Date();
|
||||
this.tempData = `${nu.getHours()}:${nu.getMinutes()}:${nu.getSeconds()}.${nu.getMilliseconds()} -> ` + this.tempData;
|
||||
}
|
||||
this.lines.push(this.tempData);
|
||||
this.tempData = '';
|
||||
this.update();
|
||||
}
|
||||
}));
|
||||
|
||||
// TODO onError
|
||||
}
|
||||
|
||||
@postConstruct()
|
||||
protected init(): void {
|
||||
this.update();
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.lines = [];
|
||||
this.update();
|
||||
}
|
||||
|
||||
get baudRate(): number | undefined {
|
||||
return this._baudRate;
|
||||
}
|
||||
|
||||
protected onAfterAttach(msg: Message) {
|
||||
super.onAfterAttach(msg);
|
||||
this.clear();
|
||||
this.connect();
|
||||
this.toDisposeOnDetach.push(this.boardsServiceClient.onBoardsChanged(async states => {
|
||||
const currentConnectionConfig = this.connection.connectionConfig;
|
||||
const connectedBoard = states.newState.boards
|
||||
.filter(AttachedSerialBoard.is)
|
||||
.find(board => {
|
||||
const potentiallyConnected = currentConnectionConfig && currentConnectionConfig.board;
|
||||
if (AttachedSerialBoard.is(potentiallyConnected)) {
|
||||
return Board.equals(board, potentiallyConnected) && board.port === potentiallyConnected.port;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (!connectedBoard) {
|
||||
this.close();
|
||||
}
|
||||
}));
|
||||
|
||||
this.toDisposeOnDetach.push(this.connection.onConnectionChanged(() => {
|
||||
this.clear();
|
||||
}));
|
||||
}
|
||||
|
||||
protected onBeforeDetach(msg: Message) {
|
||||
super.onBeforeDetach(msg);
|
||||
this.connection.disconnect();
|
||||
}
|
||||
|
||||
protected async connect() {
|
||||
const config = await this.getConnectionConfig();
|
||||
if (config) {
|
||||
this.connection.connect(config);
|
||||
}
|
||||
}
|
||||
|
||||
protected async getConnectionConfig(): Promise<ConnectionConfig | undefined> {
|
||||
const baudRate = this.baudRate;
|
||||
const { boardsConfig } = this.boardsServiceClient;
|
||||
const { selectedBoard, selectedPort } = boardsConfig;
|
||||
if (!selectedBoard) {
|
||||
this.messageService.warn('No boards selected.');
|
||||
return;
|
||||
}
|
||||
const { name } = selectedBoard;
|
||||
if (!selectedPort) {
|
||||
this.messageService.warn(`No ports selected for board: '${name}'.`);
|
||||
return;
|
||||
}
|
||||
const attachedBoards = await this.boardsService.getAttachedBoards();
|
||||
const connectedBoard = attachedBoards.boards.filter(AttachedSerialBoard.is).find(board => BoardsConfig.Config.sameAs(boardsConfig, board));
|
||||
if (!connectedBoard) {
|
||||
this.messageService.warn(`The selected '${name}' board is not connected on ${selectedPort}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
baudRate,
|
||||
board: selectedBoard,
|
||||
port: selectedPort
|
||||
}
|
||||
}
|
||||
|
||||
protected getLineEndings(): OptionsType<SelectOption> {
|
||||
return [
|
||||
{
|
||||
label: 'No Line Ending',
|
||||
value: ''
|
||||
},
|
||||
{
|
||||
label: 'Newline',
|
||||
value: '\n'
|
||||
},
|
||||
{
|
||||
label: 'Carriage Return',
|
||||
value: '\r'
|
||||
},
|
||||
{
|
||||
label: 'Both NL & CR',
|
||||
value: '\r\n'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
protected getBaudRates(): OptionsType<SelectOption> {
|
||||
const baudRates = [300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200];
|
||||
return baudRates.map<SelectOption>(baudRate => ({ label: baudRate + ' baud', value: baudRate }))
|
||||
}
|
||||
|
||||
protected render(): React.ReactNode {
|
||||
const le = this.getLineEndings();
|
||||
const br = this.getBaudRates();
|
||||
return <React.Fragment>
|
||||
<div className='serial-monitor-container'>
|
||||
<div className='head'>
|
||||
<div className='send'>
|
||||
<SerialMonitorSendField onSend={this.onSend} />
|
||||
</div>
|
||||
<div className='config'>
|
||||
{this.renderSelectField('arduino-serial-monitor-line-endings', le, le[1], this.onChangeLineEnding)}
|
||||
{this.renderSelectField('arduino-serial-monitor-baud-rates', br, br[4], this.onChangeBaudRate)}
|
||||
</div>
|
||||
</div>
|
||||
<div id='serial-monitor-output-container'>
|
||||
<SerialMonitorOutput model={this.model} lines={this.lines} />
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>;
|
||||
}
|
||||
|
||||
protected readonly onSend = (value: string) => this.doSend(value);
|
||||
protected async doSend(value: string) {
|
||||
const { connectionId } = this.connection;
|
||||
if (connectionId) {
|
||||
this.monitorService.send(connectionId, value + this._lineEnding);
|
||||
}
|
||||
}
|
||||
|
||||
protected readonly onChangeLineEnding = (le: SelectOption) => {
|
||||
this._lineEnding = typeof le.value === 'string' ? le.value : '\n';
|
||||
}
|
||||
|
||||
protected readonly onChangeBaudRate = (br: SelectOption) => {
|
||||
this._baudRate = typeof br.value === 'number' ? br.value : 9600;
|
||||
}
|
||||
|
||||
protected renderSelectField(id: string, options: OptionsType<SelectOption>, defaultVal: SelectOption, onChange: (v: SelectOption) => void): React.ReactNode {
|
||||
const height = 25;
|
||||
const selectStyles: Styles = {
|
||||
control: (provided, state) => ({
|
||||
...provided,
|
||||
width: 200
|
||||
}),
|
||||
dropdownIndicator: (p, s) => ({
|
||||
...p,
|
||||
padding: 0
|
||||
}),
|
||||
indicatorSeparator: (p, s) => ({
|
||||
display: 'none'
|
||||
}),
|
||||
indicatorsContainer: (p, s) => ({
|
||||
padding: '0 5px'
|
||||
}),
|
||||
menu: (p, s) => ({
|
||||
...p,
|
||||
marginTop: 0
|
||||
})
|
||||
};
|
||||
const theme: ThemeConfig = theme => ({
|
||||
...theme,
|
||||
borderRadius: 0,
|
||||
spacing: {
|
||||
controlHeight: height,
|
||||
baseUnit: 2,
|
||||
menuGutter: 4
|
||||
}
|
||||
});
|
||||
const DropdownIndicator = (
|
||||
props: React.Props<typeof components.DropdownIndicator>
|
||||
) => {
|
||||
return (
|
||||
<span className='fa fa-caret-down caret'></span>
|
||||
);
|
||||
};
|
||||
return <Select
|
||||
options={options}
|
||||
defaultValue={defaultVal}
|
||||
onChange={onChange}
|
||||
components={{ DropdownIndicator }}
|
||||
theme={theme}
|
||||
styles={selectStyles}
|
||||
classNamePrefix='sms'
|
||||
className='serial-monitor-select'
|
||||
id={id}
|
||||
/>
|
||||
}
|
||||
}
|
@ -196,6 +196,7 @@ button.theia-button.main {
|
||||
background: #f7f7f7;
|
||||
border: 3px solid var(--theia-border-color2);
|
||||
margin: -3px;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.arduino-boards-dropdown-item {
|
||||
|
@ -1,4 +1,5 @@
|
||||
@import './list-widget.css';
|
||||
@import './board-select-dialog.css';
|
||||
@import './main.css';
|
||||
@import './editor.css';
|
||||
@import './editor.css';
|
||||
@import './serial-monitor.css';
|
86
arduino-ide-extension/src/browser/style/serial-monitor.css
Normal file
86
arduino-ide-extension/src/browser/style/serial-monitor.css
Normal file
@ -0,0 +1,86 @@
|
||||
.serial-monitor-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.serial-monitor-container .head {
|
||||
display: flex;
|
||||
padding: 5px;
|
||||
background: var(--theia-brand-color2);
|
||||
height: 27px;
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .send {
|
||||
display: flex;
|
||||
flex:1;
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .send .btn {
|
||||
display: flex;
|
||||
padding: 0 5px;
|
||||
align-items: center;
|
||||
background: var(--theia-brand-color3);
|
||||
color: var(--theia-ui-dialog-font-color);
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .send form {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .send input#serial-monitor-send {
|
||||
background: var(--theia-layout-color0);
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .send input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .config {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.serial-monitor-container .head .config .serial-monitor-select {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#serial-monitor-output-container {
|
||||
overflow: auto;
|
||||
flex: 1;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
.p-TabBar-toolbar .item.arduino-monitor {
|
||||
width: 24px;
|
||||
justify-content: center;
|
||||
font-size: medium;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.p-TabBar-toolbar .item.arduino-monitor.toggled {
|
||||
border: var(--theia-ui-button-color-hover) var(--theia-border-width) solid;
|
||||
}
|
||||
|
||||
.p-TabBar-toolbar .item .clear-all {
|
||||
background: var(--theia-icon-clear) no-repeat;
|
||||
}
|
||||
|
||||
/* React Select Styles */
|
||||
.serial-monitor-select .sms__control {
|
||||
border: var(--theia-border-color1) var(--theia-border-width) solid;
|
||||
}
|
||||
|
||||
.serial-monitor-select .sms__option--is-selected {
|
||||
background-color: var(--theia-ui-button-color-secondary-hover);
|
||||
color: var(--theia-content-font-color0);
|
||||
}
|
||||
|
||||
.serial-monitor-select .sms__option--is-focused {
|
||||
background-color: var(--theia-ui-button-color-secondary-hover);
|
||||
}
|
||||
|
||||
.serial-monitor-select .sms__menu {
|
||||
background-color: var(--theia-layout-color1);
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
.p-Widget.p-TabBar.theia-app-centers.theia-app-bottom .p-TabBar-content-container.ps {
|
||||
display: none;
|
||||
}
|
@ -23,6 +23,7 @@ export interface MonitorService extends JsonRpcServer<MonitorServiceClient> {
|
||||
connect(config: ConnectionConfig): Promise<{ connectionId: string }>;
|
||||
disconnect(connectionId: string): Promise<boolean>;
|
||||
send(connectionId: string, data: string | Uint8Array): Promise<void>;
|
||||
getConnectionIds(): Promise<string[]>;
|
||||
}
|
||||
|
||||
export interface ConnectionConfig {
|
||||
|
@ -59,6 +59,10 @@ export class MonitorServiceImpl implements MonitorService {
|
||||
}
|
||||
}
|
||||
|
||||
async getConnectionIds(): Promise<string[]> {
|
||||
return Array.from(this.connections.keys());
|
||||
}
|
||||
|
||||
async connect(config: ConnectionConfig): Promise<{ connectionId: string }> {
|
||||
const client = await this.monitorClientProvider.client;
|
||||
const duplex = client.streamingOpen();
|
||||
@ -122,11 +126,12 @@ export class MonitorServiceImpl implements MonitorService {
|
||||
return result;
|
||||
}
|
||||
|
||||
protected async doDisconnect(connectionId: string, duplex: MonitorDuplex): Promise<boolean> {
|
||||
const { toDispose } = duplex;
|
||||
protected async doDisconnect(connectionId: string, monitorDuplex: MonitorDuplex): Promise<boolean> {
|
||||
const { duplex } = monitorDuplex;
|
||||
this.logger.info(`>>> Disposing monitor connection: ${connectionId}...`);
|
||||
try {
|
||||
toDispose.dispose();
|
||||
duplex.cancel();
|
||||
this.connections.delete(connectionId);
|
||||
this.logger.info(`<<< Connection disposed: ${connectionId}.`);
|
||||
return true;
|
||||
} catch (e) {
|
||||
|
219
yarn.lock
219
yarn.lock
@ -9,6 +9,13 @@
|
||||
dependencies:
|
||||
"@babel/highlight" "^7.0.0"
|
||||
|
||||
"@babel/helper-module-imports@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d"
|
||||
integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==
|
||||
dependencies:
|
||||
"@babel/types" "^7.0.0"
|
||||
|
||||
"@babel/highlight@^7.0.0":
|
||||
version "7.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540"
|
||||
@ -18,13 +25,99 @@
|
||||
esutils "^2.0.2"
|
||||
js-tokens "^4.0.0"
|
||||
|
||||
"@babel/runtime@^7.1.2":
|
||||
"@babel/runtime@^7.1.2", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.3", "@babel/runtime@^7.4.4":
|
||||
version "7.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.5.5.tgz#74fba56d35efbeca444091c7850ccd494fd2f132"
|
||||
integrity sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.2"
|
||||
|
||||
"@babel/types@^7.0.0":
|
||||
version "7.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a"
|
||||
integrity sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
lodash "^4.17.13"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@emotion/cache@^10.0.14", "@emotion/cache@^10.0.9":
|
||||
version "10.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.14.tgz#56093cff025c04b0330bdd92afe8335ed326dd18"
|
||||
integrity sha512-HNGEwWnPlNyy/WPXBXzbjzkzeZFV657Z99/xq2xs5yinJHbMfi3ioCvBJ6Y8Zc8DQzO9F5jDmVXJB41Ytx3QMw==
|
||||
dependencies:
|
||||
"@emotion/sheet" "0.9.3"
|
||||
"@emotion/stylis" "0.8.4"
|
||||
"@emotion/utils" "0.11.2"
|
||||
"@emotion/weak-memoize" "0.2.3"
|
||||
|
||||
"@emotion/core@^10.0.9":
|
||||
version "10.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.14.tgz#cac5c334b278d5b7688cfff39e460a5b50abb71c"
|
||||
integrity sha512-G9FbyxLm3lSnPfLDcag8fcOQBKui/ueXmWOhV+LuEQg9HrqExuWnWaO6gm6S5rNe+AMcqLXVljf8pYgAdFLNSg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.4.3"
|
||||
"@emotion/cache" "^10.0.14"
|
||||
"@emotion/css" "^10.0.14"
|
||||
"@emotion/serialize" "^0.11.8"
|
||||
"@emotion/sheet" "0.9.3"
|
||||
"@emotion/utils" "0.11.2"
|
||||
|
||||
"@emotion/css@^10.0.14", "@emotion/css@^10.0.9":
|
||||
version "10.0.14"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/css/-/css-10.0.14.tgz#95dacabdd0e22845d1a1b0b5968d9afa34011139"
|
||||
integrity sha512-MozgPkBEWvorcdpqHZE5x1D/PLEHUitALQCQYt2wayf4UNhpgQs2tN0UwHYS4FMy5ROBH+0ALyCFVYJ/ywmwlg==
|
||||
dependencies:
|
||||
"@emotion/serialize" "^0.11.8"
|
||||
"@emotion/utils" "0.11.2"
|
||||
babel-plugin-emotion "^10.0.14"
|
||||
|
||||
"@emotion/hash@0.7.2":
|
||||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.2.tgz#53211e564604beb9befa7a4400ebf8147473eeef"
|
||||
integrity sha512-RMtr1i6E8MXaBWwhXL3yeOU8JXRnz8GNxHvaUfVvwxokvayUY0zoBeWbKw1S9XkufmGEEdQd228pSZXFkAln8Q==
|
||||
|
||||
"@emotion/memoize@0.7.2":
|
||||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.2.tgz#7f4c71b7654068dfcccad29553520f984cc66b30"
|
||||
integrity sha512-hnHhwQzvPCW1QjBWFyBtsETdllOM92BfrKWbUTmh9aeOlcVOiXvlPsK4104xH8NsaKfg86PTFsWkueQeUfMA/w==
|
||||
|
||||
"@emotion/serialize@^0.11.8":
|
||||
version "0.11.8"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-0.11.8.tgz#e41dcf7029e45286a3e0cf922933e670fe05402c"
|
||||
integrity sha512-Qb6Us2Yk1ZW8SOYH6s5z7qzXXb2iHwVeqc6FjXtac0vvxC416ki0eTtHNw4Q5smoyxdyZh3519NKGrQvvvrZ/Q==
|
||||
dependencies:
|
||||
"@emotion/hash" "0.7.2"
|
||||
"@emotion/memoize" "0.7.2"
|
||||
"@emotion/unitless" "0.7.4"
|
||||
"@emotion/utils" "0.11.2"
|
||||
csstype "^2.5.7"
|
||||
|
||||
"@emotion/sheet@0.9.3":
|
||||
version "0.9.3"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-0.9.3.tgz#689f135ecf87d3c650ed0c4f5ddcbe579883564a"
|
||||
integrity sha512-c3Q6V7Df7jfwSq5AzQWbXHa5soeE4F5cbqi40xn0CzXxWW9/6Mxq48WJEtqfWzbZtW9odZdnRAkwCQwN12ob4A==
|
||||
|
||||
"@emotion/stylis@0.8.4":
|
||||
version "0.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.4.tgz#6c51afdf1dd0d73666ba09d2eb6c25c220d6fe4c"
|
||||
integrity sha512-TLmkCVm8f8gH0oLv+HWKiu7e8xmBIaokhxcEKPh1m8pXiV/akCiq50FvYgOwY42rjejck8nsdQxZlXZ7pmyBUQ==
|
||||
|
||||
"@emotion/unitless@0.7.4":
|
||||
version "0.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.4.tgz#a87b4b04e5ae14a88d48ebef15015f6b7d1f5677"
|
||||
integrity sha512-kBa+cDHOR9jpRJ+kcGMsysrls0leukrm68DmFQoMIWQcXdr2cZvyvypWuGYT7U+9kAExUE7+T7r6G3C3A6L8MQ==
|
||||
|
||||
"@emotion/utils@0.11.2":
|
||||
version "0.11.2"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.11.2.tgz#713056bfdffb396b0a14f1c8f18e7b4d0d200183"
|
||||
integrity sha512-UHX2XklLl3sIaP6oiMmlVzT0J+2ATTVpf0dHQVyPJHTkOITvXfaSqnRk6mdDhV9pR8T/tHc3cex78IKXssmzrA==
|
||||
|
||||
"@emotion/weak-memoize@0.2.3":
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.3.tgz#dfa0c92efe44a1d1a7974fb49ffeb40ef2da5a27"
|
||||
integrity sha512-zVgvPwGK7c1aVdUVc9Qv7SqepOGRDrqCw7KZPSZziWGxSlbII3gmvGLPzLX4d0n0BMbamBacUrN22zOMyFFEkQ==
|
||||
|
||||
"@evocateur/libnpmaccess@^3.1.2":
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz#ecf7f6ce6b004e9f942b098d92200be4a4b1c845"
|
||||
@ -1503,6 +1596,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c"
|
||||
integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==
|
||||
|
||||
"@types/react-dom@*":
|
||||
version "16.8.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.5.tgz#3e3f4d99199391a7fb40aa3a155c8dd99b899cbd"
|
||||
integrity sha512-idCEjROZ2cqh29+trmTmZhsBAUNQuYrF92JHKzZ5+aiFM1mlSk3bb23CK7HhYuOY75Apgap5y2jTyHzaM2AJGA==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-dom@^16.0.6":
|
||||
version "16.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.8.4.tgz#7fb7ba368857c7aa0f4e4511c4710ca2c5a12a88"
|
||||
@ -1510,6 +1610,22 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-select@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-select/-/react-select-3.0.0.tgz#d8e2fa078099963d2f33bea20b735a962799015a"
|
||||
integrity sha512-eu+4qdByhx1Szqtpqke/7Bwhl5B1cWm47ojlYKp+PR2x9eVnzoytRoi2FNthQxCTQor4t81xgqY/8X4Naf2rKQ==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
"@types/react-dom" "*"
|
||||
"@types/react-transition-group" "*"
|
||||
|
||||
"@types/react-transition-group@*":
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.2.0.tgz#86ddb509ce3de27341c7cb7797abb99b1c4676bf"
|
||||
integrity sha512-8KkpFRwqS9U1dtVVw1kt/MmWgLmbd5iK5TgqsaeC7fAm74J4j/HiBiRC8eETvwjGGju48RAwyZ3l5iv1H1x93Q==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-virtualized@^9.18.3":
|
||||
version "9.21.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-virtualized/-/react-virtualized-9.21.3.tgz#79a44b870a4848cbc7cc04ff4bc06e5a10955262"
|
||||
@ -2557,6 +2673,31 @@ babel-plugin-check-es2015-constants@^6.22.0:
|
||||
dependencies:
|
||||
babel-runtime "^6.22.0"
|
||||
|
||||
babel-plugin-emotion@^10.0.14:
|
||||
version "10.0.14"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-emotion/-/babel-plugin-emotion-10.0.14.tgz#c1d0e4621e303507ea7da57daa3cd771939d6df4"
|
||||
integrity sha512-T7hdxJ4xXkKW3OXcizK0pnUJlBeNj/emjQZPDIZvGOuwl2adIgicQWRNkz6BuwKdDTrqaXQn1vayaL6aL8QW5A==
|
||||
dependencies:
|
||||
"@babel/helper-module-imports" "^7.0.0"
|
||||
"@emotion/hash" "0.7.2"
|
||||
"@emotion/memoize" "0.7.2"
|
||||
"@emotion/serialize" "^0.11.8"
|
||||
babel-plugin-macros "^2.0.0"
|
||||
babel-plugin-syntax-jsx "^6.18.0"
|
||||
convert-source-map "^1.5.0"
|
||||
escape-string-regexp "^1.0.5"
|
||||
find-root "^1.1.0"
|
||||
source-map "^0.5.7"
|
||||
|
||||
babel-plugin-macros@^2.0.0:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.6.1.tgz#41f7ead616fc36f6a93180e89697f69f51671181"
|
||||
integrity sha512-6W2nwiXme6j1n2erPOnmRiWfObUhWH7Qw1LMi9XZy8cj+KtESu3T6asZvtk5bMQQjX8te35o7CFueiSdL/2NmQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.4.2"
|
||||
cosmiconfig "^5.2.0"
|
||||
resolve "^1.10.0"
|
||||
|
||||
babel-plugin-syntax-async-functions@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
|
||||
@ -2602,6 +2743,11 @@ babel-plugin-syntax-flow@^6.18.0:
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d"
|
||||
integrity sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=
|
||||
|
||||
babel-plugin-syntax-jsx@^6.18.0:
|
||||
version "6.18.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
|
||||
integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=
|
||||
|
||||
babel-plugin-syntax-object-rest-spread@^6.8.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
|
||||
@ -3674,6 +3820,11 @@ class-utils@^0.3.5:
|
||||
isobject "^3.0.0"
|
||||
static-extend "^0.1.1"
|
||||
|
||||
classnames@^2.2.5:
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
|
||||
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
|
||||
|
||||
cli-cursor@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
|
||||
@ -4073,7 +4224,7 @@ conventional-recommended-bump@^5.0.0:
|
||||
meow "^4.0.0"
|
||||
q "^1.5.1"
|
||||
|
||||
convert-source-map@^1.5.1:
|
||||
convert-source-map@^1.5.0, convert-source-map@^1.5.1:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20"
|
||||
integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==
|
||||
@ -4131,7 +4282,7 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
cosmiconfig@^5.1.0:
|
||||
cosmiconfig@^5.1.0, cosmiconfig@^5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
|
||||
integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
|
||||
@ -4343,7 +4494,7 @@ csso@~2.3.1:
|
||||
clap "^1.0.9"
|
||||
source-map "^0.5.3"
|
||||
|
||||
csstype@^2.2.0:
|
||||
csstype@^2.2.0, csstype@^2.5.7:
|
||||
version "2.6.6"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.6.tgz#c34f8226a94bbb10c32cc0d714afdf942291fc41"
|
||||
integrity sha512-RpFbQGUE74iyPgvr46U9t1xoQBM8T4BL8SxrN66Le2xYAPSaDJJKeztV3awugusb3g3G9iL8StmkBBXhcbbXhg==
|
||||
@ -4682,7 +4833,7 @@ dir-glob@^2.0.0, dir-glob@^2.2.2:
|
||||
dependencies:
|
||||
path-type "^3.0.0"
|
||||
|
||||
"dom-helpers@^2.4.0 || ^3.0.0":
|
||||
"dom-helpers@^2.4.0 || ^3.0.0", dom-helpers@^3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8"
|
||||
integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==
|
||||
@ -5545,6 +5696,10 @@ find-git-repositories@^0.1.0:
|
||||
integrity sha512-v3Z6lE2+6Kat5ujOLucCGyijJ6yfv1/V7uauRYQshlSjv9177Rk3Eg8J6x2C/zAsQHJym4HHHLuOoy3Sl5KqzQ==
|
||||
dependencies:
|
||||
nan "^2.0.0"
|
||||
find-root@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
|
||||
integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
|
||||
|
||||
find-up@^1.0.0:
|
||||
version "1.1.2"
|
||||
@ -7611,7 +7766,7 @@ lodash.uniq@^4.5.0:
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
|
||||
|
||||
lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0:
|
||||
lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.3.0:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
@ -7849,6 +8004,11 @@ mem@^4.0.0:
|
||||
mimic-fn "^2.0.0"
|
||||
p-is-promise "^2.0.0"
|
||||
|
||||
memoize-one@^5.0.0:
|
||||
version "5.0.5"
|
||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.5.tgz#8cd3809555723a07684afafcd6f756072ac75d7e"
|
||||
integrity sha512-ey6EpYv0tEaIbM/nTDOpHciXUvd+ackQrJgEzBwemhZZIWZjcyodqEcrmqDy2BKRTM3a65kKBV4WtLXJDt26SQ==
|
||||
|
||||
memory-fs@^0.4.0, memory-fs@~0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
|
||||
@ -9561,7 +9721,7 @@ promzard@^0.3.0:
|
||||
dependencies:
|
||||
read "1"
|
||||
|
||||
prop-types@^15.5.6, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
|
||||
prop-types@^15.5.6, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
@ -9724,6 +9884,13 @@ quick-lru@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8"
|
||||
integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=
|
||||
|
||||
raf@^3.4.0:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
|
||||
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
|
||||
dependencies:
|
||||
performance-now "^2.1.0"
|
||||
|
||||
randomatic@^3.0.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed"
|
||||
@ -9792,6 +9959,13 @@ react-dom@^16.4.1:
|
||||
prop-types "^15.6.2"
|
||||
scheduler "^0.13.6"
|
||||
|
||||
react-input-autosize@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.1.tgz#ec428fa15b1592994fb5f9aa15bb1eb6baf420f8"
|
||||
integrity sha512-3+K4CD13iE4lQQ2WlF8PuV5htfmTRLH6MDnfndHM6LuBRszuXnuyIfE7nhSKt8AzRBZ50bu0sAhkNMeS5pxQQA==
|
||||
dependencies:
|
||||
prop-types "^15.5.8"
|
||||
|
||||
react-is@^16.8.1:
|
||||
version "16.8.6"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
|
||||
@ -9802,6 +9976,32 @@ react-lifecycles-compat@^3.0.4:
|
||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||
|
||||
react-select@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.0.4.tgz#16bde37c24fd4f6444914d4681e78f15ffbc86d3"
|
||||
integrity sha512-fbVISKa/lSUlLsltuatfUiKcWCNvdLXxFFyrzVQCBUsjxJZH/m7UMPdw/ywmRixAmwXAP++MdbNNZypOsiDEfA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.4.4"
|
||||
"@emotion/cache" "^10.0.9"
|
||||
"@emotion/core" "^10.0.9"
|
||||
"@emotion/css" "^10.0.9"
|
||||
classnames "^2.2.5"
|
||||
memoize-one "^5.0.0"
|
||||
prop-types "^15.6.0"
|
||||
raf "^3.4.0"
|
||||
react-input-autosize "^2.2.1"
|
||||
react-transition-group "^2.2.1"
|
||||
|
||||
react-transition-group@^2.2.1:
|
||||
version "2.9.0"
|
||||
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"
|
||||
integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==
|
||||
dependencies:
|
||||
dom-helpers "^3.4.0"
|
||||
loose-envify "^1.4.0"
|
||||
prop-types "^15.6.2"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
|
||||
react-virtualized@^9.20.0:
|
||||
version "9.21.1"
|
||||
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.1.tgz#4dbbf8f0a1420e2de3abf28fbb77120815277b3a"
|
||||
@ -11296,6 +11496,11 @@ to-fast-properties@^1.0.3:
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
|
||||
integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=
|
||||
|
||||
to-fast-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||
integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
|
||||
|
||||
to-gfm-code-block@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/to-gfm-code-block/-/to-gfm-code-block-0.1.1.tgz#25d045a5fae553189e9637b590900da732d8aa82"
|
||||
|
Loading…
x
Reference in New Issue
Block a user