Skip to content

Commit 19bae06

Browse files
authored
Adding react and table designer to the extension (#17914)
* Update dependencies and add new files * fix builds * chore: Add gulp task to compile mssql-react-app * Adding react web view controller * chore: Update dependencies and remove unused packages * chore: Update dependencies and remove unused packages * Update dependencies and fix build * Add table designer service and contracts * Initializing service on startup * Refactor table designer service and contracts * Refactor table designer service and contracts * Adding table errors * Code cleanup and finishing callouts * Fixing divider visibility in results * adding drag and drop to table * Fixing gulp watch and compilation errors * Fixing yarn install script * chore: Add 'ext:compile-mssql-react-app' task to 'ext:build' gulp task * Hacky fix for showing table designer on right node * Adding ability to edit tables * Removing table designer from command pallette. * adding copyright * more copyright * fixing eslint * Adding preview flag * chore: Remove commented out code in vite.config.ts
1 parent ddd08d8 commit 19bae06

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+8149
-6
lines changed

.vscode/launch.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
{
33
"version": "0.1.0",
44
"configurations": [
5+
6+
7+
58
{
69
"type": "node",
710
"request": "launch",
@@ -30,7 +33,8 @@
3033
],
3134
"sourceMaps": true,
3235
"outFiles": [
33-
"${workspaceRoot}/out/src/**/*.js"
36+
"${workspaceRoot}/out/src/**/*.js",
37+
"${workspaceRoot}/myssql-react-app/dist/**/*.js"
3438
],
3539
"preLaunchTask": "build",
3640
"env": {

gulpfile.js

+22-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var nls = require('vscode-nls-dev');
1212
var argv = require('yargs').argv;
1313
var min = (argv.min === undefined) ? false : true;
1414
var vscodeTest = require('@vscode/test-electron');
15+
var { exec } = require('child_process');
1516
const gulpESLintNew = require('gulp-eslint-new');
1617

1718
require('./tasks/packagetasks');
@@ -23,7 +24,9 @@ gulp.task('ext:lint', () => {
2324
'!' + config.paths.project.root + '/src/views/htmlcontent/**/*',
2425
config.paths.project.root + '/test/unit/**/*.ts'
2526
])
26-
.pipe(gulpESLintNew())
27+
.pipe(gulpESLintNew({
28+
quiet: true
29+
}))
2730
.pipe(gulpESLintNew.format()) // Output lint results to the console.
2831
.pipe(gulpESLintNew.failAfterError());
2932
});
@@ -78,6 +81,18 @@ gulp.task('ext:compile-view', (done) => {
7881
.pipe(gulp.dest('out/src/views/htmlcontent'));
7982
});
8083

84+
// Compile react views
85+
gulp.task('ext:compile-mssql-react-app', (done) => {
86+
return exec('cd mssql-react-app && yarn build --emptyOutDir', {
87+
continueOnError: true
88+
}, (err, stdout, stderr) => {
89+
console.log(stdout);
90+
console.error(stderr);
91+
done();
92+
});
93+
})
94+
95+
8196
// Copy systemjs config file
8297
gulp.task('ext:copy-systemjs-config', (done) => {
8398
return gulp.src([
@@ -227,7 +242,7 @@ gulp.task('ext:copy', gulp.series('ext:copy-tests', 'ext:copy-js', 'ext:copy-con
227242

228243
gulp.task('ext:localization', gulp.series('ext:localization:generate-eng-package.nls', 'ext:localization:xliff-to-ts', 'ext:localization:xliff-to-json', 'ext:localization:xliff-to-package.nls'));
229244

230-
gulp.task('ext:build', gulp.series('ext:localization', 'ext:copy', 'ext:clean-library-ts-files', 'ext:compile', 'ext:compile-view')); // removed lint before copy
245+
gulp.task('ext:build', gulp.series('ext:localization', 'ext:copy', 'ext:clean-library-ts-files', 'ext:compile', 'ext:compile-view', 'ext:compile-mssql-react-app')); // removed lint before copy
231246

232247
gulp.task('ext:test', async () => {
233248
let workspace = process.env['WORKSPACE'];
@@ -264,8 +279,12 @@ gulp.task('watch-tests', function () {
264279
return gulp.watch('./test/unit/**/*.ts', gulp.series('ext:compile-tests'))
265280
});
266281

282+
gulp.task('watch-mssql-react-app', function () {
283+
return gulp.watch('./mssql-react-app/src/**/*', gulp.series('ext:compile-mssql-react-app'))
284+
});
285+
267286
// Do a full build first so we have the latest compiled files before we start watching for more changes
268-
gulp.task('watch', gulp.series('build', gulp.parallel('watch-src', 'watch-tests')));
287+
gulp.task('watch', gulp.series('build', gulp.parallel('watch-src', 'watch-tests', 'watch-mssql-react-app')));
269288

270289
gulp.task('lint', gulp.series('ext:lint'));
271290

media/newTable.svg

+3
Loading

media/newTable_inverse.svg

+3
Loading

mssql-react-app/.eslintrc.cjs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module.exports = {
2+
root: true,
3+
env: { browser: true, es2020: true },
4+
extends: [
5+
'eslint:recommended',
6+
'plugin:@typescript-eslint/recommended',
7+
'plugin:react-hooks/recommended',
8+
],
9+
ignorePatterns: ['dist', '.eslintrc.cjs'],
10+
parser: '@typescript-eslint/parser',
11+
plugins: ['react-refresh'],
12+
rules: {
13+
'react-refresh/only-export-components': [
14+
'warn',
15+
{ allowConstantExport: true },
16+
],
17+
},
18+
}

mssql-react-app/.gitignore

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?

mssql-react-app/README.md

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# React + TypeScript + Vite
2+
3+
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4+
5+
Currently, two official plugins are available:
6+
7+
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8+
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9+
10+
## Expanding the ESLint configuration
11+
12+
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
13+
14+
- Configure the top-level `parserOptions` property like this:
15+
16+
```js
17+
export default {
18+
// other rules...
19+
parserOptions: {
20+
ecmaVersion: 'latest',
21+
sourceType: 'module',
22+
project: ['./tsconfig.json', './tsconfig.node.json'],
23+
tsconfigRootDir: __dirname,
24+
},
25+
}
26+
```
27+
28+
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
29+
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
30+
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list

mssql-react-app/index.html

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vite + React + TS</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>

mssql-react-app/package.json

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "mssql-react-app",
3+
"private": true,
4+
"version": "0.0.0",
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite build --watch --emptyOutDir",
8+
"build": "tsc && vite build",
9+
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10+
"preview": "vite preview"
11+
},
12+
"dependencies": {
13+
"@fluentui/react-components": "^9.51.0",
14+
"@monaco-editor/react": "^4.6.0",
15+
"@types/vscode-webview": "^1.57.5",
16+
"@vscode/webview-ui-toolkit": "^1.4.0",
17+
"react": "^18.2.0",
18+
"react-dom": "^18.2.0",
19+
"react-markdown": "^9.0.1",
20+
"react-resizable": "^3.0.5",
21+
"react-router-dom": "^6.23.1"
22+
},
23+
"devDependencies": {
24+
"@types/react": "^18.2.66",
25+
"@types/react-dom": "^18.2.22",
26+
"@types/react-resizable": "^3.0.7",
27+
"@typescript-eslint/eslint-plugin": "^7.2.0",
28+
"@typescript-eslint/parser": "^7.2.0",
29+
"@vitejs/plugin-react": "^4.2.1",
30+
"eslint": "^8.57.0",
31+
"eslint-plugin-react-hooks": "^4.6.0",
32+
"eslint-plugin-react-refresh": "^0.4.6",
33+
"typescript": "^5.2.2",
34+
"vite": "^5.2.0"
35+
}
36+
}

mssql-react-app/public/vite.svg

+1
Loading

mssql-react-app/src/assets/react.svg

+1
Loading

mssql-react-app/src/common/rpc.ts

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { WebviewApi } from "vscode-webview";
7+
8+
export class WebviewRpc {
9+
private _rpcRequestId = 0;
10+
private _rpcHandlers: { [id: number]: { resolve: (result: unknown) => void, reject: (error: unknown) => void } } = {};
11+
private _methodSubscriptions: { [method: string]: ((params: unknown) => void)[] } = {};
12+
13+
constructor(private _vscodeApi: WebviewApi<unknown>) {
14+
window.addEventListener('message', (event) => {
15+
const message = event.data;
16+
if (message.type === 'response') {
17+
const { id, result, error } = message;
18+
if (this._rpcHandlers[id]) {
19+
if (error) {
20+
this._rpcHandlers[id].reject(error);
21+
} else {
22+
this._rpcHandlers[id].resolve(result);
23+
}
24+
delete this._rpcHandlers[id];
25+
}
26+
}
27+
if (message.type === 'notification') {
28+
const { method, params } = message;
29+
if (this._methodSubscriptions[method]) {
30+
this._methodSubscriptions[method].forEach(callback => callback(params));
31+
}
32+
}
33+
});
34+
35+
}
36+
37+
public call(method: string, params?: unknown): Promise<unknown> {
38+
const id = this._rpcRequestId++;
39+
this._vscodeApi.postMessage({ type: 'request', id, method, params });
40+
return new Promise((resolve, reject) => {
41+
this._rpcHandlers[id] = { resolve, reject };
42+
});
43+
}
44+
45+
public action(type: string, payload?: unknown) {
46+
this.call('action', { type, payload });
47+
}
48+
49+
public subscribe(method: string, callback: (params: unknown) => void) {
50+
if (!this._methodSubscriptions[method]) {
51+
this._methodSubscriptions[method] = [];
52+
}
53+
this._methodSubscriptions[method].push(callback);
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { FluentProvider, Theme, teamsHighContrastTheme, webDarkTheme, webLightTheme } from "@fluentui/react-components";
7+
import { createContext, useState } from "react";
8+
import { WebviewApi } from "vscode-webview";
9+
import { WebviewRpc } from "./rpc";
10+
11+
interface VscodeWebviewContext {
12+
vscodeApi: WebviewApi<unknown>;
13+
extensionRpc: WebviewRpc;
14+
state: unknown;
15+
theme: Theme;
16+
}
17+
18+
const vscodeApiInstance = acquireVsCodeApi<unknown>();
19+
20+
const VscodeWebviewContext = createContext<VscodeWebviewContext | undefined>(undefined);
21+
22+
interface VscodeWebViewProviderProps {
23+
children: React.ReactNode;
24+
}
25+
26+
const VscodeWebViewProvider: React.FC<VscodeWebViewProviderProps> = ({ children }) => {
27+
const vscodeApi = vscodeApiInstance;
28+
const extensionRpc = new WebviewRpc(vscodeApi);
29+
const [theme, setTheme] = useState(webLightTheme);
30+
const [state, setState] = useState<unknown>();
31+
32+
extensionRpc.subscribe('onDidChangeTheme', (params) => {
33+
const kind = params as ColorThemeKind;
34+
switch (kind) {
35+
case ColorThemeKind.Dark:
36+
setTheme(webDarkTheme);
37+
break;
38+
case ColorThemeKind.HighContrast:
39+
setTheme(teamsHighContrastTheme);
40+
break;
41+
default:
42+
setTheme(webLightTheme);
43+
break;
44+
}
45+
});
46+
47+
extensionRpc.subscribe('updateState', (params) => {
48+
setState(params);
49+
});
50+
51+
return <VscodeWebviewContext.Provider value={{
52+
vscodeApi: vscodeApi,
53+
extensionRpc: extensionRpc,
54+
state: state,
55+
theme: theme
56+
}}>
57+
<FluentProvider style={{
58+
height: '100%',
59+
width: '100%',
60+
color: 'var(--vscode-foreground)',
61+
}} theme={theme}>
62+
{children}
63+
</FluentProvider>
64+
</VscodeWebviewContext.Provider>;
65+
}
66+
67+
export { VscodeWebviewContext, VscodeWebViewProvider };
68+
export enum ColorThemeKind {
69+
Light = 1,
70+
Dark = 2,
71+
HighContrast = 3,
72+
HighContrastLight = 4
73+
}

mssql-react-app/src/index.css

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#root {
2+
left: 0;
3+
right: 0;
4+
width: 100%;
5+
height: 100%;
6+
overflow: hidden;
7+
color: 'var(--vscode-foreground)',
8+
}

0 commit comments

Comments
 (0)