Update webview create-react-app framework and IDE support

feature/ssh-config
Kelvin Schoofs 4 years ago
parent c0f77bf11e
commit b071a32ed4

66
.vscode/tasks.json vendored

@ -37,30 +37,52 @@
"cwd": "./webview" "cwd": "./webview"
}, },
"group": "build", "group": "build",
"problemMatcher": { "problemMatcher": [
"source": "react-dev-utils", {
"severity": "error", "source": "parser",
"fileLocation": "absolute", "owner": "react",
"applyTo": "closedDocuments", "fileLocation": "absolute",
"background": { "applyTo": "allDocuments",
"activeOnStart": true, "pattern": [
"beginsPattern": "Compiling.*?|Compilation .*?starting", {
"endsPattern": "Compiled .*?successfully|Failed .*?to.*?compile.*?" "regexp": "^SyntaxError: (.*): (.+) \\((\\d+):(\\d+)\\)$",
"file": 1,
"message": 2,
"line": 3,
"column": 4
}
],
"background": {
"activeOnStart": true,
"beginsPattern": "^Compiling.*",
"endsPattern": "^(Compiled successfully|Failed to compile)"
}
}, },
"pattern": [ {
{ "source": "typescript",
"regexp": "^(.+)$", "owner": "react",
"file": 1 "fileLocation": "absolute",
}, "applyTo": "allDocuments",
{ "pattern": [
"regexp": "\\((\\d+),(\\d+)\\):\\s*(.+)", {
"line": 1, "regexp": "^TypeScript error in (.*)\\((\\d+),(\\d+)\\):",
"column": 2, "file": 1,
"message": 3, "line": 2,
"loop": true "column": 3
},
{
"regexp": "^(.{5,})$",
"message": 1,
"loop": true
}
],
"background": {
"activeOnStart": true,
"beginsPattern": "^Compiling.*",
"endsPattern": "^(Compiled successfully|Failed to compile)"
} }
] }
}, ],
"isBackground": true "isBackground": true
} }
] ]

@ -110,6 +110,6 @@ export interface FileSystemConfig extends ConnectConfig {
export function invalidConfigName(name: string) { export function invalidConfigName(name: string) {
if (!name) return 'Missing a name for this SSH FS'; if (!name) return 'Missing a name for this SSH FS';
if (name.match(/^[\w_\\\/\.@\-+]+$/)) return null; if (name.match(/^[\w_\\/.@\-+]+$/)) return null;
return `A SSH FS name can only exists of lowercase alphanumeric characters, slashes and any of these: _.+-@`; return `A SSH FS name can only exists of lowercase alphanumeric characters, slashes and any of these: _.+-@`;
} }

@ -31,6 +31,7 @@ async function getDebugContent(): Promise<string | false> {
// Make sure the CSP meta tag also includes the React dev server (including connect-src for the socket, which uses both http:// and ws://) // Make sure the CSP meta tag also includes the React dev server (including connect-src for the socket, which uses both http:// and ws://)
body = body.replace(/\$WEBVIEW_CSPSOURCE/g, `$WEBVIEW_CSPSOURCE ${URL}`); body = body.replace(/\$WEBVIEW_CSPSOURCE/g, `$WEBVIEW_CSPSOURCE ${URL}`);
body = body.replace(/\$WEBVIEW_CSPEXTRA/g, `connect-src ${URL} ${URL.replace('http://', 'ws://')};`); body = body.replace(/\$WEBVIEW_CSPEXTRA/g, `connect-src ${URL} ${URL.replace('http://', 'ws://')};`);
body = body.replace(/src="\/static\//g, `src="${URL}/static/`);
cb(null, body); cb(null, body);
}).on('error', err => { }).on('error', err => {
Logging.warning(`Error connecting to React dev server: ${err}`); Logging.warning(`Error connecting to React dev server: ${err}`);

@ -0,0 +1,4 @@
WDS_SOCKET_HOST=localhost
WDS_SOCKET_PORT=3000
BROWSER=none
SKIP_PREFLIGHT_CHECK=true

@ -15,6 +15,7 @@ build
.env.development.local .env.development.local
.env.test.local .env.test.local
.env.production.local .env.production.local
.eslintcache
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*

@ -9,18 +9,30 @@
"redux": "^4.0.5" "redux": "^4.0.5"
}, },
"scripts": { "scripts": {
"start": "cross-env BROWSER=none react-scripts-ts start", "start": "react-scripts start",
"build": "react-scripts-ts build", "build": "react-scripts build",
"test": "react-scripts-ts test --env=jsdom", "test": "react-scripts test",
"eject": "react-scripts-ts eject" "eject": "react-scripts eject"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^25.1.4", "@types/jest": "^25.1.4",
"@types/react": "^16.9.23", "@types/react": "^16.9.23",
"@types/react-dom": "^16.9.5", "@types/react-dom": "^16.9.5",
"@types/react-redux": "^7.1.7", "@types/react-redux": "^7.1.7",
"cross-env": "^7.0.3", "react-scripts": "^4.0.1",
"react-scripts-ts": "^3.1.0",
"typescript": "^4.0.2" "typescript": "^4.0.2"
},
"browserslist": [
"Electron >= 9.0.0"
],
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
],
"rules": {
"no-sparse-arrays": 0,
"no-sequences": 0
}
} }
} }

@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src $WEBVIEW_CSPSOURCE; style-src 'unsafe-inline' $WEBVIEW_CSPSOURCE; $WEBVIEW_CSPEXTRA"> <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'unsafe-inline' $WEBVIEW_CSPSOURCE; style-src 'unsafe-inline' $WEBVIEW_CSPSOURCE; $WEBVIEW_CSPEXTRA">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!--<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">--> <!--<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">-->
<!-- <!--

@ -26,7 +26,7 @@ class ConfigList extends React.Component<StateProps & DispatchProps & OwnProps>
} }
public editConfigClickHandler(config: FileSystemConfig) { public editConfigClickHandler(config: FileSystemConfig) {
const { displayName } = this.props; const { displayName } = this.props;
const name = displayName && displayName(config) || config.label || config.name; const name = displayName?.(config) || config.label || config.name;
const onClick = () => this.props.editConfig(config); const onClick = () => this.props.editConfig(config);
return <li key={config.name} onClick={onClick}>{name}</li>; return <li key={config.name} onClick={onClick}>{name}</li>;
} }

@ -64,7 +64,7 @@ export abstract class FieldBase<T, P = {}, S = {}> extends React.Component<Props
const error = this.getError(); const error = this.getError();
const { description, label, optional } = this.props; const { description, label, optional } = this.props;
return <div className="Field"> return <div className="Field">
<FieldGroup.Consumer>{group => (group && group.register(this), [])}</FieldGroup.Consumer> <FieldGroup.Consumer>{group => (group?.register(this), [])}</FieldGroup.Consumer>
<div className="label">{label}</div>{optional && <div className="optional">Optional</div>} <div className="label">{label}</div>{optional && <div className="optional">Optional</div>}
{description && <div className="description">{description}</div>} {description && <div className="description">{description}</div>}
{error && <div className="error">{error}</div>} {error && <div className="error">{error}</div>}

@ -6,10 +6,10 @@ interface Props<T> {
displayName?(item: T): string; displayName?(item: T): string;
displayStyle?(item: T): React.CSSProperties; displayStyle?(item: T): React.CSSProperties;
} }
interface State<T> { interface State {
open: boolean; open: boolean;
} }
export class FieldDropdown<T> extends FieldBase<T, Props<T>, State<T>> { export class FieldDropdown<T> extends FieldBase<T, Props<T>, State> {
public mainDivRef = React.createRef<HTMLDivElement>(); public mainDivRef = React.createRef<HTMLDivElement>();
public componentDidMount() { public componentDidMount() {
window.addEventListener('click', this.onGlobalClick); window.addEventListener('click', this.onGlobalClick);
@ -17,7 +17,7 @@ export class FieldDropdown<T> extends FieldBase<T, Props<T>, State<T>> {
public componentWillUnmount() { public componentWillUnmount() {
window.removeEventListener('click', this.onGlobalClick); window.removeEventListener('click', this.onGlobalClick);
} }
public getInitialSubState(props: Props<T>): State<T> { public getInitialSubState(props: Props<T>): State {
return { open: false }; return { open: false };
} }
public renderInput() { public renderInput() {
@ -39,7 +39,7 @@ export class FieldDropdown<T> extends FieldBase<T, Props<T>, State<T>> {
</li> </li>
}; };
return <ul className="list"> return <ul className="list">
{this.props.optional && <li onClick={this.select.bind(this, null)} />} {this.props.optional && <li onClick={this.select.bind(this, null as any as T)} />}
{values.map(generateItem)} {values.map(generateItem)}
</ul>; </ul>;
} }

@ -44,7 +44,7 @@ export class FieldDropdownWithInput extends FieldBase<string | undefined, Props,
{values.map(generateItem)} {values.map(generateItem)}
</ul>; </ul>;
} }
public select(newValue: string) { public select(newValue: string | undefined) {
this.setState({ newValue, open: false }, () => this.props.onChange(newValue)); this.setState({ newValue, open: false }, () => this.props.onChange(newValue));
} }
public toggle = () => this.setState({ open: !this.state.open }); public toggle = () => this.setState({ open: !this.state.open });

@ -2,9 +2,6 @@ import * as React from 'react';
import { FieldBase } from './base'; import { FieldBase } from './base';
export class FieldString extends FieldBase<string | undefined> { export class FieldString extends FieldBase<string | undefined> {
constructor(props: FieldString['props']) {
super(props);
}
public getInitialSubState({ value }: FieldString['props']): FieldString['state'] { public getInitialSubState({ value }: FieldString['props']): FieldString['state'] {
value = value || undefined; value = value || undefined;
return { oldValue: value, newValue: value }; return { oldValue: value, newValue: value };

@ -50,6 +50,9 @@ export default connect(Startscreen)<StateProps, DispatchProps>(
dispatch => ({ dispatch => ({
add: () => dispatch(openNewConfig()), add: () => dispatch(openNewConfig()),
changeGroupBy: (current: string) => dispatch(openStartScreen(current === 'group' ? 'location' : 'group')), changeGroupBy: (current: string) => dispatch(openStartScreen(current === 'group' ? 'location' : 'group')),
refresh: () => (dispatch(receivedData([], [])), API.postMessage({ type: 'requestData' })), refresh: () => {
dispatch(receivedData([], []));
API.postMessage({ type: 'requestData' });
},
}), }),
); );

@ -0,0 +1 @@
/// <reference types="react-scripts" />

@ -110,6 +110,6 @@ export interface FileSystemConfig extends ConnectConfig {
export function invalidConfigName(name: string) { export function invalidConfigName(name: string) {
if (!name) return 'Missing a name for this SSH FS'; if (!name) return 'Missing a name for this SSH FS';
if (name.match(/^[\w_\\\/\.@\-+]+$/)) return null; if (name.match(/^[\w_\\/.@\-+]+$/)) return null;
return `A SSH FS name can only exists of lowercase alphanumeric characters, slashes and any of these: _.+-@`; return `A SSH FS name can only exists of lowercase alphanumeric characters, slashes and any of these: _.+-@`;
} }

@ -21,7 +21,7 @@ export function addListener<T extends Message = Message>(listener: Listener<T>,
export function addListener(listener: Listener, filter?: Filter) { export function addListener(listener: Listener, filter?: Filter) {
LISTENERS.push([listener, filter]); LISTENERS.push([listener, filter]);
} }
export function removeListener(listener: Listener) { export function removeListener<T extends Message = Message>(listener: Listener<T>) {
LISTENERS = LISTENERS.filter(([l]) => l !== listener); LISTENERS = LISTENERS.filter(([l]) => l !== listener);
} }

@ -3,7 +3,10 @@
"outDir": "build/dist", "outDir": "build/dist",
"module": "esnext", "module": "esnext",
"target": "es5", "target": "es5",
"lib": ["es6", "dom"], "lib": [
"es6",
"dom"
],
"sourceMap": true, "sourceMap": true,
"allowJs": true, "allowJs": true,
"jsx": "react", "jsx": "react",
@ -16,19 +19,18 @@
"importHelpers": true, "importHelpers": true,
"strictNullChecks": true, "strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true, "suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true "noUnusedLocals": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"noFallthroughCasesInSwitch": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
}, },
"include": [ "include": [
"src", "src",
"public" "public"
],
"exclude": [
"node_modules",
"build",
"scripts",
"acceptance-tests",
"webpack",
"jest",
"src/setupTests.ts"
] ]
} }

@ -1,3 +0,0 @@
{
"extends": "./tsconfig.json"
}

@ -1,6 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs"
}
}

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save