Skip to content

Commit 8d1f9c5

Browse files
authored
Integrate Angular Rule Editor (intersystems-community#1014)
1 parent ae34a2e commit 8d1f9c5

File tree

10 files changed

+398
-14
lines changed

10 files changed

+398
-14
lines changed

docs/LowCode.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
layout: default
3+
title: Low-Code Editors
4+
permalink: /low-code/
5+
nav_order: 11
6+
---
7+
8+
# Low-Code Editors
9+
10+
VS Code contains support for low-code editors via its [Custom Editors API](https://code.visualstudio.com/api/extension-guides/custom-editors). As InterSystems redevelops its suite of low-code editors for Interoperability components, support for integration with this extension will be included. This page lists the currently supported low-code editors and describes how to use them in VS Code.
11+
12+
## Supported Editors
13+
14+
The following list contains all InterSystems low-code editors that support integration with VS Code, along with the earliest version of InterSystems IRIS that contains the support:
15+
16+
* Rule Editor (2023.1)
17+
18+
## Opening a Low-Code Editor
19+
20+
To open a low-code editor, first open the class that contains the Interoperability component that you want to edit, right-click on the editor tab and select the `Reopen Editor With...` option:
21+
22+
![Reopen Editor With](../assets/images/reopen-editor-with.png "reopen editor with")
23+
24+
You will then be prompted with a list of editors to choose from:
25+
26+
![Select Editor](../assets/images/low-code-select.png "select editor")
27+
28+
Once you select the editor, it will replace the text editor for the selected class. If the editor cannot be loaded, a modal dialog will be shown that contains the reason and the class will be automatically reopened in the default text editor. A low-code [editor tab](https://code.visualstudio.com/docs/getstarted/userinterface#_tabs) will behave the same as a text editor tab.
29+
30+
## How They Work
31+
32+
This section describes how the low-code editors are integrated in VS Code to create a hassle-free editing experience. Note that while low-code editors are supported for both client-side and server-side workflows, an active server connection is required even when working client-side.
33+
34+
* VS Code sends your credentials to the editor so you don't have to log in again.
35+
* A save, undo, redo or revert action triggered by VS Code (via keyboard shortcuts, for example) will trigger the corresponding action in the editor.
36+
* When the state of the class changes from clean to dirty (or vice versa) in the editor, the underlying text document will also be made dirty/clean.
37+
* When the class is saved or compiled by the editor, VS Code will pull the changes from the server and update the text document.
38+
* If the `objectscript.compileOnSave` setting is enabled and the class was saved by the editor, the class will also be compiled by the editor.
39+
40+
Note that the changes you make in the low-code editor are only synced to the underlying text document when you save them in the editor. Therefore, it is ***strongly*** recommended that you only open and edit the document in one editor (text or low-code) at once to avoid overwriting changes. The low-code editors provide support for server-side source control natively. The underlying text document is kept in sync after saves so changes can be stored in client-side source control.
46.2 KB
Loading
208 KB
Loading

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ nav_exclude: true
1515
* [Reporting Issues](./feedback)
1616
* [Working with Projects](./projects)
1717
* [Migrating from Studio](./studio)
18+
* [Low-Code Editors](./low-code)

package.json

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@
9898
"onFileSystem:isfs",
9999
"onFileSystem:isfs-readonly",
100100
"onFileSystem:objectscript",
101-
"onDebugInitialConfigurations"
101+
"onDebugInitialConfigurations",
102+
"onCustomEditor:vscode-objectscript.rule"
102103
],
103104
"main": "./dist/extension",
104105
"browser": "./dist/web-extension",
@@ -264,7 +265,7 @@
264265
},
265266
{
266267
"command": "vscode-objectscript.showClassDocumentationPreview",
267-
"when": "editorLangId == objectscript-class"
268+
"when": "editorLangId == objectscript-class && activeCustomEditorId == ''"
268269
},
269270
{
270271
"command": "vscode-objectscript.exportCurrentFile",
@@ -328,7 +329,7 @@
328329
},
329330
{
330331
"command": "vscode-objectscript.showRESTDebugWebview",
331-
"when": "editorLangId =~ /^objectscript/ && vscode-objectscript.connectActive"
332+
"when": "editorLangId =~ /^objectscript/ && vscode-objectscript.connectActive && activeCustomEditorId == ''"
332333
},
333334
{
334335
"command": "vscode-objectscript.modifyWsFolder",
@@ -506,7 +507,7 @@
506507
},
507508
{
508509
"command": "vscode-objectscript.showRESTDebugWebview",
509-
"when": "editorLangId =~ /^objectscript/ && vscode-objectscript.connectActive",
510+
"when": "editorLangId =~ /^objectscript/ && vscode-objectscript.connectActive && activeCustomEditorId == ''",
510511
"group": "objectscript@9"
511512
}
512513
],
@@ -524,19 +525,19 @@
524525
{
525526
"command": "vscode-objectscript.showClassDocumentationPreview",
526527
"group": "navigation@3",
527-
"when": "editorLangId == objectscript-class"
528+
"when": "editorLangId == objectscript-class && activeCustomEditorId == ''"
528529
}
529530
],
530531
"editor/title/context": [
531532
{
532533
"command": "vscode-objectscript.showClassDocumentationPreview",
533534
"group": "1_open",
534-
"when": "resourceLangId == objectscript-class"
535+
"when": "resourceLangId == objectscript-class && activeCustomEditorId == ''"
535536
},
536537
{
537538
"command": "vscode-objectscript.showRESTDebugWebview",
538539
"group": "1_open",
539-
"when": "resourceLangId =~ /^objectscript/ && vscode-objectscript.connectActive"
540+
"when": "resourceLangId =~ /^objectscript/ && vscode-objectscript.connectActive && activeCustomEditorId == ''"
540541
}
541542
],
542543
"touchBar": [
@@ -1596,6 +1597,18 @@
15961597
"separator": "/"
15971598
}
15981599
}
1600+
],
1601+
"customEditors": [
1602+
{
1603+
"viewType": "vscode-objectscript.rule",
1604+
"displayName": "Rule Editor",
1605+
"selector": [
1606+
{
1607+
"filenamePattern": "*.cls"
1608+
}
1609+
],
1610+
"priority": "option"
1611+
}
15991612
]
16001613
},
16011614
"scripts": {

src/api/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ export class AtelierAPI {
336336
throw {
337337
statusCode: response.status,
338338
message: response.statusText,
339-
errorText: `The server at ${host}:${port} is unavailable. Check License Usage.`,
339+
errorText: `The server at ${host}:${port}${pathPrefix} is unavailable. Check License Usage.`,
340340
};
341341
}
342342
if (response.status === 401) {
@@ -609,11 +609,11 @@ export class AtelierAPI {
609609
}
610610

611611
// v1+
612-
public getCSPApps(detail = false): Promise<Atelier.Response> {
612+
public getCSPApps(detail = false, nsOverride?: string): Promise<Atelier.Response> {
613613
const params = {
614614
detail: detail ? 1 : 0,
615615
};
616-
return this.request(1, "GET", `%SYS/cspapps/${this.ns || ""}`, null, params);
616+
return this.request(1, "GET", `%SYS/cspapps/${nsOverride || this.ns || ""}`, null, params);
617617
}
618618

619619
// v1+

src/commands/compile.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ export async function loadChanges(files: (CurrentTextFile | CurrentBinaryFile)[]
266266
);
267267
}
268268

269-
async function compile(docs: CurrentFile[], flags?: string): Promise<any> {
269+
export async function compile(docs: CurrentFile[], flags?: string): Promise<any> {
270270
flags = flags || config("compileFlags");
271271
const api = new AtelierAPI(docs[0].uri);
272272
return vscode.window

src/commands/studio.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { RoutineNode } from "../explorer/models/routineNode";
99
import { NodeBase } from "../explorer/models/nodeBase";
1010
import { importAndCompile } from "./compile";
1111
import { ProjectNode } from "../explorer/models/projectNode";
12+
import { openCustomEditors } from "../providers/RuleEditorProvider";
1213

1314
export let documentBeingProcessed: vscode.TextDocument = null;
1415

@@ -63,7 +64,7 @@ function getOtherStudioActionLabel(action: OtherStudioAction): string {
6364
// Used to avoid triggering the edit listener when files are reloaded by an extension
6465
const suppressEditListenerMap = new Map<string, boolean>();
6566

66-
class StudioActions {
67+
export class StudioActions {
6768
private uri: vscode.Uri;
6869
private api: AtelierAPI;
6970
private name: string;
@@ -84,6 +85,7 @@ class StudioActions {
8485
}
8586
}
8687

88+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
8789
public processUserAction(userAction): Thenable<any> {
8890
const serverAction = parseInt(userAction.action || 0, 10);
8991
const { target, errorText } = userAction;
@@ -389,7 +391,8 @@ class StudioActions {
389391
.then((action) => this.userAction(action));
390392
}
391393

392-
public fireOtherStudioAction(action: OtherStudioAction, userAction?) {
394+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
395+
public fireOtherStudioAction(action: OtherStudioAction, userAction?): void {
393396
const actionObject = {
394397
id: action.toString(),
395398
label: getOtherStudioActionLabel(action),
@@ -454,7 +457,7 @@ class StudioActions {
454457
.then((content) => (content && content.length ? content[0].Enabled : false));
455458
}
456459

457-
public getServerInfo() {
460+
public getServerInfo(): { server: string; namespace: string } {
458461
return {
459462
server: `${this.api.config.host}:${this.api.config.port}${this.api.config.pathPrefix}`,
460463
namespace: this.api.config.ns,
@@ -527,6 +530,7 @@ export async function fireOtherStudioAction(action: OtherStudioAction, uri?: vsc
527530
return (
528531
studioActions &&
529532
(await studioActions.isSourceControlEnabled()) &&
533+
!openCustomEditors.includes(uri.toString()) && // The custom editor will handle all server-side source control interactions
530534
studioActions.fireOtherStudioAction(action, userAction)
531535
);
532536
}

src/extension.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ import {
113113
} from "./commands/project";
114114
import { NodeBase } from "./explorer/models/nodeBase";
115115
import { loadStudioColors, loadStudioSnippets } from "./commands/studioMigration";
116+
import { openCustomEditors, RuleEditorProvider } from "./providers/RuleEditorProvider";
116117
import { newFile, NewFileType } from "./commands/newFile";
117118
import { FileDecorationProvider } from "./providers/FileDecorationProvider";
118119
import { RESTDebugPanel } from "./commands/restDebugPanel";
@@ -1047,6 +1048,12 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
10471048
vscode.commands.registerCommand("vscode-objectscript.explorer.project.addWorkspaceFolderForProject", (node) =>
10481049
addWorkspaceFolderForProject(node)
10491050
),
1051+
vscode.window.registerCustomEditorProvider("vscode-objectscript.rule", new RuleEditorProvider(), {
1052+
webviewOptions: {
1053+
retainContextWhenHidden: true,
1054+
},
1055+
supportsMultipleEditorsPerDocument: false,
1056+
}),
10501057
vscode.workspace.onDidChangeWorkspaceFolders(async ({ added, removed }) => {
10511058
const folders = vscode.workspace.workspaceFolders;
10521059

@@ -1116,6 +1123,10 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
11161123
}
11171124
}),
11181125
vscode.workspace.onDidSaveTextDocument((file) => {
1126+
if (openCustomEditors.includes(file.uri.toString())) {
1127+
// Saving is handled by a different event listener
1128+
return;
1129+
}
11191130
if (!schemas.includes(file.uri.scheme) && !config("importOnSave")) {
11201131
// Don't save this local file on the server
11211132
return;

0 commit comments

Comments
 (0)