Skip to content

Commit

Permalink
Add preview
Browse files Browse the repository at this point in the history
  • Loading branch information
TheZoker committed Mar 7, 2019
1 parent f78e7d1 commit 2e2091a
Show file tree
Hide file tree
Showing 10 changed files with 225,080 additions and 22 deletions.
565 changes: 565 additions & 0 deletions jsonforms-tooling-common/package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions jsonforms-tooling-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
"@jsonforms/core": "^2.2.0",
"@jsonforms/react": "^2.2.0",
"ajv": "^6.5.5",
"yeoman-environment": "^2.3.4",
"react": "^16.8.3",
"redux": "^3.0.0"
"redux": "^3.0.0",
"chokidar": "^2.1.2",
"yeoman-environment": "^2.3.4"
},
"type-check": "tsc",
"devDependencies": {
"@types/chokidar": "^1.7.5",
"rimraf": "^2.6.2"
}
}
228 changes: 227 additions & 1 deletion jsonforms-tooling-common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import jsonforms from '@jsonforms/core';
import { readFile, writeFile } from 'fs';
import Ajv from 'ajv';
import { sep } from 'path';
import { join, sep } from 'path';
import { watch } from 'chokidar';
const yeoman = require('yeoman-environment');

export enum Project {
Expand Down Expand Up @@ -67,6 +68,85 @@ export const generateUISchema = (editorInstance: any, path: string) => {
}
};

/**
* Shows a preview form of a given json schema and ui schema in a new panel inside the editor
* @param {any} editorInstance the instance of the editor
* @param {string} path the path to the schema or ui-schema file
* @param {string} extensionPath the path to the extension directory
*/
export const showPreview = (editorInstance: any, path: any, extensionPath: string) => {
if (!path) {
editorInstance.window.showOpenDialog(editorInstance.OpenDialogOptions = {
canSelectMany: false,
canSelectFolders: false,
canSelectFiles: true,
openLabel: 'Select ui schema',
filters: {
'Json Files': ['json'],
},
}).then((uiSchemafileUri: any) => {
if (uiSchemafileUri && uiSchemafileUri[0].fsPath) {
editorInstance.window.showOpenDialog(editorInstance.OpenDialogOptions = {
canSelectMany: false,
canSelectFolders: false,
canSelectFiles: true,
openLabel: 'Select schema',
filters: {
'Json Files': ['json'],
},
}).then((schemaFileUri: any) => {
if (schemaFileUri && schemaFileUri[0].fsPath) {
const uiSchemaPath = uiSchemafileUri[0].fsPath;
const schemaPath = schemaFileUri[0].fsPath;
showWebview(editorInstance, 'preview', extensionPath, uiSchemaPath, schemaPath);
} else {
showMessage('Please select a json schema file', 'err');
return;
}
});
} else {
showMessage('Please select a ui schema file', 'err');
return;
}
});
} else {
editorInstance.window.showQuickPick(['UI Schema', 'Schema'], editorInstance.QuickPickOptions = {
canSelectMany: false,
placeHolder: 'Was that the UI schema or the schema file?'
}).then((schema: any) => {
if (schema) {
let selectLabel = 'Select ui Schema';
if (schema === 'UI Schema') {
selectLabel = 'Select Schema';
}
editorInstance.window.showOpenDialog(editorInstance.OpenDialogOptions = {
canSelectMany: false,
canSelectFolders: false,
canSelectFiles: true,
openLabel: selectLabel,
filters: {
'Json Files': ['json'],
},
}).then((schemaFileUri: any) => {
if (schemaFileUri && schemaFileUri[0].fsPath) {
if (schema === 'UI Schema') {
showWebview(editorInstance, 'preview', extensionPath, path, schemaFileUri[0].fsPath);
} else {
showWebview(editorInstance, 'preview', extensionPath, schemaFileUri[0].fsPath, path);
}
} else {
showMessage('Please select a json schema file', 'err');
return;
}
});
} else {
showMessage('Please select the schema type', 'err');
return;
}
});
}
};

/**
* Async Generate UI Schema
* @param {any} editorInstance the instance of the editor
Expand Down Expand Up @@ -206,3 +286,149 @@ const cloneAndInstall = (editorInstance: any, project: string, path: string, nam
});
});
};

/**
* Get HTML to be shown inside the preview webview
* @param {any} scriptUriCore Uri of jsonforms-core.js
* @param {any} scriptUriReact Uri of jsonforms-react.js
* @param {any} scriptUriMaterial Uri of jsonforms-material.js
* @param {JSON} schema schema of the form
* @param {JSON} uiSchema uiSchema of the form
*/
const getPreviewHTML = (
scriptUriCore: any,
scriptUriReact: any,
scriptUriMaterial: any,
schema: string,
uiSchema: string
) => {
return `<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react.development.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.development.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/redux.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/react-redux.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/browser.min.js"></script>
<script src="${scriptUriCore}"></script>
<script src="${scriptUriReact}"></script>
<script src="${scriptUriMaterial}"></script>
</head>
<body style="background: #fff">
<div id="root">Loading...</div>
<script type="text/babel">
var schema = ${schema};
var uiSchema = ${uiSchema};
const store = Redux.createStore(
Redux.combineReducers({ jsonforms: JSONFormsCore.jsonformsReducer() }),
{
jsonforms: {
fields: JSONFormsMaterial.materialFields,
renderers: JSONFormsMaterial.materialRenderers
},
}
);
store.dispatch(JSONFormsCore.Actions.init({}, schema, uiSchema));
const mapStateToProps = state => {
return { dataAsString: JSON.stringify(JSONFormsCore.getData(state), null, 2) }
};
var App = ({ dataAsString }) => {
return (
<div>
<JSONFormsReact.JsonForms />
</div>
);
};
const CApp = ReactRedux.connect(mapStateToProps, null)(App);
ReactDOM.render(
<ReactRedux.Provider store={store}>
<CApp />
</ReactRedux.Provider>,
document.getElementById('root')
);
</script>
</body>
</html>`;
};

/**
* Show webview
* @param {any} editorInstance the instance of the editor
* @param {string} id the id for the webview
* @param {string} extensionPath the path to the extension directory
* @param {string} uiSchemaPath the path to the ui schema
* @param {string} schemaPath the path to the schema
*/
const showWebview = (
editorInstance: any,
id: string,
extensionPath: string,
uiSchemaPath: string,
schemaPath: string
) => {
const name = id;
const webView = editorInstance.window.createWebviewPanel(
'view-' + name,
name,
editorInstance.ViewColumn.Two,
{ enableScripts: true}
);
preparePreview(editorInstance, extensionPath, uiSchemaPath, schemaPath, (html: string) => {
webView.webview.html = html;
watch(uiSchemaPath).on('change', (event: any, path: any) => {
preparePreview(editorInstance, extensionPath, uiSchemaPath, schemaPath, (newHtml: string) => {
webView.webview.html = newHtml;
});
});
});
};

/**
* Prepare the preview webview
* @param {any} editorInstance the instance of the editor
* @param {string} extensionPath the path to the extension directory
* @param {string} uiSchemaPath the path to the ui schema
* @param {string} schemaPath the path to the schema
* @param {any} callback the callback, that is called, after all files are loaded
*/
const preparePreview = (
editorInstance: any,
extensionPath: string,
uiSchemaPath: string,
schemaPath: string,
callback: any
) => {
// Prepare the scripts needed to show the App inside the Webview
const scriptPathOnDiskCore = editorInstance.Uri.file(
join(extensionPath, 'assets', 'preview', 'jsonforms-core.js')
);
const scriptPathOnDiskReact = editorInstance.Uri.file(
join(extensionPath, 'assets', 'preview', 'jsonforms-react.js')
);
const scriptPathOnDiskMaterial = editorInstance.Uri.file(
join(extensionPath, 'assets', 'preview', 'jsonforms-material.js')
);
const scriptUriCore = scriptPathOnDiskCore.with({ scheme: 'vscode-resource'});
const scriptUriReact = scriptPathOnDiskReact.with({ scheme: 'vscode-resource'});
const scriptUriMaterial = scriptPathOnDiskMaterial.with({ scheme: 'vscode-resource'});

// Read json files and load html for webview
readFile(schemaPath, 'utf8', (readError, schema) => {
if ((readError !== null) && readError.message) {
showMessage(editorInstance, readError.message, 'err');
return;
}
readFile(uiSchemaPath, 'utf8', (secondReadError, uiSchema) => {
if ((secondReadError !== null) && secondReadError.message) {
showMessage(editorInstance, secondReadError.message, 'err');
return;
}
callback(getPreviewHTML(scriptUriCore, scriptUriReact, scriptUriMaterial, schema, uiSchema));
});
});
};
17 changes: 16 additions & 1 deletion theia-plugin/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/

import * as theia from '@theia/plugin';
import { createProject, generateUISchema, Project } from 'jsonforms-tooling-common';
import { createProject, generateUISchema, Project, showPreview } from 'jsonforms-tooling-common';

export const start = (context: theia.PluginContext) => {
const createExampleProjectCommandOptions = {
Expand Down Expand Up @@ -41,7 +41,22 @@ export const start = (context: theia.PluginContext) => {
}
);

const showPreviewCommandOptions = {
id: 'show-preview',
label: 'JSONForms: Show Preview',
};
const showPreviewCommand = theia.commands.registerCommand(
showPreviewCommandOptions,
(args: any) => {
if (args === undefined) {
args = {fsPath: null};
}
showPreview(theia, args.fsPath, context.extensionPath);
}
);

context.subscriptions.push(createExampleProjectCommand);
context.subscriptions.push(createSeedProjectCommand);
context.subscriptions.push(generateUISchemaCommand);
context.subscriptions.push(showPreviewCommand);
};
Loading

0 comments on commit 2e2091a

Please sign in to comment.