Implement monaco editor

This commit is contained in:
Sipke Schoorstra 2022-01-04 20:43:46 +01:00
parent a949fa2c14
commit 1e71ea605f
17 changed files with 2086 additions and 21 deletions

View file

@ -0,0 +1,3 @@
namespace Elsa.Management.ActivityInputOptions;
public record CodeEditorOptions(EditorHeight? EditorHeight = default, string? Language = default, bool? SingleLineMode = default);

File diff suppressed because it is too large Load diff

View file

@ -36,6 +36,9 @@
"el-transition": "^0.0.7",
"moment": "^2.29.1"
},
"peerDependencies": {
"monaco-editor": ""
},
"devDependencies": {
"@fullhuman/postcss-purgecss": "^4.1.3",
"@stencil/postcss": "^2.1.0",

View file

@ -12,6 +12,7 @@ import { NodeInputContext } from "./services/node-input-driver";
import { MenuItem } from "./components/shared/context-menu/models";
import { DropdownButtonItem, DropdownButtonOrigin } from "./components/shared/dropdown-button/models";
import { AddActivityArgs as AddActivityArgs1 } from "./components/designer/canvas/canvas";
import { MonacoLib, MonacoValueChangedArgs } from "./components/shared/monaco-editor/monaco-editor";
import { PagerData } from "./components/shared/pager/pager";
import { PanelPosition, PanelStateChangedArgs } from "./components/designer/panel/models";
import { Graph } from "@antv/x6";
@ -38,6 +39,9 @@ export namespace Components {
interface ElsaCheckListInput {
"inputContext": NodeInputContext;
}
interface ElsaCodeEditorInput {
"inputContext": NodeInputContext;
}
interface ElsaContextMenu {
"menuItems": Array<MenuItem>;
}
@ -83,6 +87,16 @@ export namespace Components {
"show": (animate?: boolean) => Promise<void>;
"size": string;
}
interface ElsaMonacoEditor {
"editorHeight": string;
"language": string;
"monacoLibPath"?: string;
"padding": string;
"setJavaScriptLibs": (libs: Array<MonacoLib>) => Promise<void>;
"setValue": (value: string) => Promise<void>;
"singleLineMode": boolean;
"value": string;
}
interface ElsaMultiLineInput {
"inputContext": NodeInputContext;
}
@ -113,6 +127,7 @@ export namespace Components {
"tabs": Array<TabDefinition>;
}
interface ElsaStudio {
"monacoLibPath": string;
"serverUrl": string;
}
interface ElsaToolbox {
@ -149,6 +164,7 @@ export namespace Components {
"getWorkflow": () => Promise<Workflow>;
"importWorkflow": (workflow: Workflow, workflowInstance?: WorkflowInstance) => Promise<void>;
"importWorkflowMetadata": (workflow: Workflow) => Promise<void>;
"monacoLibPath": string;
"registerActivityDrivers": (register: (registry: ActivityDriverRegistry) => void) => Promise<void>;
"triggerDescriptors": Array<TriggerDescriptor>;
}
@ -188,6 +204,12 @@ declare global {
prototype: HTMLElsaCheckListInputElement;
new (): HTMLElsaCheckListInputElement;
};
interface HTMLElsaCodeEditorInputElement extends Components.ElsaCodeEditorInput, HTMLStencilElement {
}
var HTMLElsaCodeEditorInputElement: {
prototype: HTMLElsaCodeEditorInputElement;
new (): HTMLElsaCodeEditorInputElement;
};
interface HTMLElsaContextMenuElement extends Components.ElsaContextMenu, HTMLStencilElement {
}
var HTMLElsaContextMenuElement: {
@ -236,6 +258,12 @@ declare global {
prototype: HTMLElsaModalDialogElement;
new (): HTMLElsaModalDialogElement;
};
interface HTMLElsaMonacoEditorElement extends Components.ElsaMonacoEditor, HTMLStencilElement {
}
var HTMLElsaMonacoEditorElement: {
prototype: HTMLElsaMonacoEditorElement;
new (): HTMLElsaMonacoEditorElement;
};
interface HTMLElsaMultiLineInputElement extends Components.ElsaMultiLineInput, HTMLStencilElement {
}
var HTMLElsaMultiLineInputElement: {
@ -360,6 +388,7 @@ declare global {
"elsa-activity-properties-editor": HTMLElsaActivityPropertiesEditorElement;
"elsa-canvas": HTMLElsaCanvasElement;
"elsa-check-list-input": HTMLElsaCheckListInputElement;
"elsa-code-editor-input": HTMLElsaCodeEditorInputElement;
"elsa-context-menu": HTMLElsaContextMenuElement;
"elsa-dropdown-button": HTMLElsaDropdownButtonElement;
"elsa-dropdown-input": HTMLElsaDropdownInputElement;
@ -368,6 +397,7 @@ declare global {
"elsa-input-tags": HTMLElsaInputTagsElement;
"elsa-input-tags-dropdown": HTMLElsaInputTagsDropdownElement;
"elsa-modal-dialog": HTMLElsaModalDialogElement;
"elsa-monaco-editor": HTMLElsaMonacoEditorElement;
"elsa-multi-line-input": HTMLElsaMultiLineInputElement;
"elsa-multi-text-input": HTMLElsaMultiTextInputElement;
"elsa-pager": HTMLElsaPagerElement;
@ -403,6 +433,9 @@ declare namespace LocalJSX {
interface ElsaCheckListInput {
"inputContext"?: NodeInputContext;
}
interface ElsaCodeEditorInput {
"inputContext"?: NodeInputContext;
}
interface ElsaContextMenu {
"menuItems"?: Array<MenuItem>;
}
@ -454,6 +487,15 @@ declare namespace LocalJSX {
"onShown"?: (event: CustomEvent<any>) => void;
"size"?: string;
}
interface ElsaMonacoEditor {
"editorHeight"?: string;
"language"?: string;
"monacoLibPath"?: string;
"onValueChanged"?: (event: CustomEvent<MonacoValueChangedArgs>) => void;
"padding"?: string;
"singleLineMode"?: boolean;
"value"?: string;
}
interface ElsaMultiLineInput {
"inputContext"?: NodeInputContext;
}
@ -486,6 +528,7 @@ declare namespace LocalJSX {
"tabs"?: Array<TabDefinition>;
}
interface ElsaStudio {
"monacoLibPath"?: string;
"serverUrl"?: string;
}
interface ElsaToolbox {
@ -520,6 +563,7 @@ declare namespace LocalJSX {
}
interface ElsaWorkflowEditor {
"activityDescriptors"?: Array<ActivityDescriptor>;
"monacoLibPath"?: string;
"onWorkflowUpdated"?: (event: CustomEvent<WorkflowUpdatedArgs>) => void;
"triggerDescriptors"?: Array<TriggerDescriptor>;
}
@ -546,6 +590,7 @@ declare namespace LocalJSX {
"elsa-activity-properties-editor": ElsaActivityPropertiesEditor;
"elsa-canvas": ElsaCanvas;
"elsa-check-list-input": ElsaCheckListInput;
"elsa-code-editor-input": ElsaCodeEditorInput;
"elsa-context-menu": ElsaContextMenu;
"elsa-dropdown-button": ElsaDropdownButton;
"elsa-dropdown-input": ElsaDropdownInput;
@ -554,6 +599,7 @@ declare namespace LocalJSX {
"elsa-input-tags": ElsaInputTags;
"elsa-input-tags-dropdown": ElsaInputTagsDropdown;
"elsa-modal-dialog": ElsaModalDialog;
"elsa-monaco-editor": ElsaMonacoEditor;
"elsa-multi-line-input": ElsaMultiLineInput;
"elsa-multi-text-input": ElsaMultiTextInput;
"elsa-pager": ElsaPager;
@ -583,6 +629,7 @@ declare module "@stencil/core" {
"elsa-activity-properties-editor": LocalJSX.ElsaActivityPropertiesEditor & JSXBase.HTMLAttributes<HTMLElsaActivityPropertiesEditorElement>;
"elsa-canvas": LocalJSX.ElsaCanvas & JSXBase.HTMLAttributes<HTMLElsaCanvasElement>;
"elsa-check-list-input": LocalJSX.ElsaCheckListInput & JSXBase.HTMLAttributes<HTMLElsaCheckListInputElement>;
"elsa-code-editor-input": LocalJSX.ElsaCodeEditorInput & JSXBase.HTMLAttributes<HTMLElsaCodeEditorInputElement>;
"elsa-context-menu": LocalJSX.ElsaContextMenu & JSXBase.HTMLAttributes<HTMLElsaContextMenuElement>;
"elsa-dropdown-button": LocalJSX.ElsaDropdownButton & JSXBase.HTMLAttributes<HTMLElsaDropdownButtonElement>;
"elsa-dropdown-input": LocalJSX.ElsaDropdownInput & JSXBase.HTMLAttributes<HTMLElsaDropdownInputElement>;
@ -591,6 +638,7 @@ declare module "@stencil/core" {
"elsa-input-tags": LocalJSX.ElsaInputTags & JSXBase.HTMLAttributes<HTMLElsaInputTagsElement>;
"elsa-input-tags-dropdown": LocalJSX.ElsaInputTagsDropdown & JSXBase.HTMLAttributes<HTMLElsaInputTagsDropdownElement>;
"elsa-modal-dialog": LocalJSX.ElsaModalDialog & JSXBase.HTMLAttributes<HTMLElsaModalDialogElement>;
"elsa-monaco-editor": LocalJSX.ElsaMonacoEditor & JSXBase.HTMLAttributes<HTMLElsaMonacoEditorElement>;
"elsa-multi-line-input": LocalJSX.ElsaMultiLineInput & JSXBase.HTMLAttributes<HTMLElsaMultiLineInputElement>;
"elsa-multi-text-input": LocalJSX.ElsaMultiTextInput & JSXBase.HTMLAttributes<HTMLElsaMultiTextInputElement>;
"elsa-pager": LocalJSX.ElsaPager & JSXBase.HTMLAttributes<HTMLElsaPagerElement>;

View file

@ -1,6 +1,6 @@
$activity-picker-width: 300px;
$trigger-panel-height: 76px;
$activity-editor-width: 500px;
$activity-editor-width: 580px;
elsa-canvas {
left: $activity-picker-width;

View file

@ -20,6 +20,7 @@ import {ActivityDriverRegistry} from '../../../services';
import {TriggerSelectedArgs, TriggersUpdatedArgs} from '../trigger-container/trigger-container';
import {DeleteTriggerRequestedArgs, TriggerUpdatedArgs} from "../trigger-properties-editor/trigger-properties-editor";
import {WorkflowPropsUpdatedArgs} from "../workflow-properties-editor/workflow-properties-editor";
import {MonacoEditorSettings} from "../../../services/monaco-editor-settings";
export interface WorkflowUpdatedArgs {
workflow: Workflow;
@ -55,6 +56,7 @@ export class WorkflowEditor {
this.saveChangesDebounced = debounce(this.saveChanges, 1000);
}
@Prop({attribute: 'monaco-lib-path'}) public monacoLibPath: string;
@Prop() public activityDescriptors: Array<ActivityDescriptor> = [];
@Prop() public triggerDescriptors: Array<TriggerDescriptor> = [];
@Event() public workflowUpdated: EventEmitter<WorkflowUpdatedArgs>
@ -66,6 +68,12 @@ export class WorkflowEditor {
return !this.workflowInstance;
}
@Watch('monacoLibPath')
private handleMonacoLibPath(value: string) {
const settings = Container.get(MonacoEditorSettings);
settings.monacoLibPath = value;
}
@Listen('resize', {target: 'window'})
private async handleResize() {
await this.updateLayout();

View file

@ -0,0 +1,39 @@
import {Component, h, Prop} from '@stencil/core';
import {EditorHeight, LiteralExpression, SyntaxNames} from "../../models";
import {NodeInputContext} from "../../services/node-input-driver";
import {getInputPropertyValue} from "../../utils";
import {MonacoValueChangedArgs} from "../shared/monaco-editor/monaco-editor";
interface CodeEditorOptions {
editorHeight?: EditorHeight;
language?: string;
singleLineMode?: boolean;
}
@Component({
tag: 'elsa-code-editor-input',
shadow: false
})
export class CodeEditorInput {
@Prop() public inputContext: NodeInputContext;
public render() {
const inputContext = this.inputContext;
const inputDescriptor = inputContext.inputDescriptor;
const options: CodeEditorOptions = inputDescriptor.options || {};
const input = getInputPropertyValue(inputContext);
let currentValue = (input?.expression as LiteralExpression)?.value;
if (currentValue == undefined)
currentValue = inputDescriptor.defaultValue;
return (
<elsa-monaco-editor value={currentValue} {...options} onValueChanged={this.onChange}/>
);
}
private onChange = (e: CustomEvent<MonacoValueChangedArgs>) => {
const value = e.detail.value;
this.inputContext.inputChanged(value, SyntaxNames.Literal);
}
}

View file

@ -0,0 +1,29 @@
.monaco-editor-host {
display: block;
position: relative;
min-height: 6em;
}
.monaco-editor-container {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
max-height: 100% !important;
margin: 0;
padding: 0;
}
.monaco-editor {
border-radius: 0.25rem;
}
.monaco-editor .overflow-guard {
border-radius: 0.25rem;
}
.monaco-editor .suggest-widget div.tree {
white-space: unset;
padding-bottom: 0;
}

View file

@ -0,0 +1,219 @@
import {Component, Event, EventEmitter, h, Host, Method, Prop, Watch} from '@stencil/core';
import {initializeMonacoWorker, Monaco} from "./utils";
import globalState from '../../../data/store';
export interface MonacoValueChangedArgs {
value: string;
markers: Array<any>;
}
export interface MonacoLib {
content: string;
filePath?: string;
}
@Component({
tag: 'elsa-monaco-editor',
styleUrl: 'monaco-editor.scss',
shadow: false
})
export class MonacoEditor {
private monaco: Monaco;
private container: HTMLElement;
private editor: any;
@Prop() public monacoLibPath?: string;
@Prop() public editorHeight: string = '5em';
@Prop() public value: string;
@Prop() public language: string;
@Prop() public singleLineMode: boolean = false;
@Prop() public padding: string;
@Event() public valueChanged: EventEmitter<MonacoValueChangedArgs>;
@Watch('language')
languageChangeHandler(newValue: string) {
if (!this.editor)
return;
const model = this.editor.getModel();
this.monaco.editor.setModelLanguage(model, this.language);
}
@Method()
async setValue(value: string) {
if (!this.editor)
return;
const model = this.editor.getModel();
model.setValue(value || '');
}
@Method()
async setJavaScriptLibs(libs: Array<MonacoLib>) {
const monaco = this.monaco;
const defaultLib: MonacoLib = {
content: "<reference lib=\"es5\" />",
filePath: "lib.d.ts"
};
libs = [defaultLib, ...libs];
monaco.languages.typescript.javascriptDefaults.setExtraLibs(libs);
for (const lib of libs) {
const oldModel = monaco.editor.getModel(lib.filePath);
if (oldModel)
oldModel.dispose();
monaco.editor.createModel(lib.content, 'typescript', monaco.Uri.parse(lib.filePath));
}
}
async componentWillLoad() {
const monacoLibPath = this.monacoLibPath || globalState.monacoLibPath;
this.monaco = await initializeMonacoWorker(monacoLibPath);
await this.setJavaScriptLibs([]);
this.registerLiquid();
}
componentDidLoad() {
const monaco = this.monaco;
const language = this.language;
// Validation settings.
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
noSemanticValidation: true,
noSyntaxValidation: false,
});
// Compiler options.
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
target: monaco.languages.typescript.ScriptTarget.ES2020,
lib: [],
allowNonTsExtensions: true
});
monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true);
const defaultOptions = {
value: this.value,
language: language,
fontFamily: "Roboto Mono, monospace",
renderLineHighlight: 'none',
minimap: {
enabled: false
},
automaticLayout: true,
lineNumbers: "on",
theme: "vs",
roundedSelection: true,
scrollBeyondLastLine: false,
readOnly: false,
overviewRulerLanes: 0,
overviewRulerBorder: false,
lineDecorationsWidth: 0,
hideCursorInOverviewRuler: true,
glyphMargin: false
};
let options = defaultOptions;
if (this.singleLineMode) {
options = {
...defaultOptions, ...{
wordWrap: 'off',
lineNumbers: 'off',
lineNumbersMinChars: 0,
folding: false,
scrollBeyondLastColumn: 0,
scrollbar: {horizontal: 'hidden', vertical: 'hidden'},
find: {addExtraSpaceOnTop: false, autoFindInSelection: 'never', seedSearchStringFromSelection: false},
}
}
}
this.editor = monaco.editor.create(this.container, options);
this.editor.onDidChangeModelContent(e => {
const value = this.editor.getValue();
const markers = monaco.editor.getModelMarkers({owner: language});
this.valueChanged.emit({value: value, markers: markers});
});
if (this.singleLineMode) {
this.editor.onKeyDown(e => {
if (e.keyCode == monaco.KeyCode.Enter) {
// We only prevent enter when the suggest model is not active
if (this.editor.getContribution('editor.contrib.suggestController').model.state == 0) {
e.preventDefault();
}
}
});
this.editor.onDidPaste(e => {
if (e.range.endLineNumber > 1) {
let newContent = "";
const model = this.editor.getModel();
let lineCount = model.getLineCount();
for (let i = 0; i < lineCount; i++) {
newContent += model.getLineContent(i + 1);
}
model.setValue(newContent);
}
});
}
}
disconnectedCallback() {
const editor = this.editor;
if (!!editor)
editor.dispose();
}
registerLiquid() {
const monaco = this.monaco;
monaco.languages.register({id: 'liquid'});
monaco.languages.registerCompletionItemProvider('liquid', {
provideCompletionItems: () => {
const autocompleteProviderItems = [];
const keywords = ['assign', 'capture', 'endcapture', 'increment', 'decrement',
'if', 'else', 'elsif', 'endif', 'for', 'endfor', 'break',
'continue', 'limit', 'offset', 'range', 'reversed', 'cols',
'case', 'endcase', 'when', 'block', 'endblock', 'true', 'false',
'in', 'unless', 'endunless', 'cycle', 'tablerow', 'endtablerow',
'contains', 'startswith', 'endswith', 'comment', 'endcomment',
'raw', 'endraw', 'editable', 'endentitylist', 'endentityview', 'endinclude',
'endmarker', 'entitylist', 'entityview', 'forloop', 'image', 'include',
'marker', 'outputcache', 'plugin', 'style', 'text', 'widget',
'abs', 'append', 'at_least', 'at_most', 'capitalize', 'ceil', 'compact',
'concat', 'date', 'default', 'divided_by', 'downcase', 'escape',
'escape_once', 'first', 'floor', 'join', 'last', 'lstrip', 'map',
'minus', 'modulo', 'newline_to_br', 'plus', 'prepend', 'remove',
'remove_first', 'replace', 'replace_first', 'reverse', 'round',
'rstrip', 'size', 'slice', 'sort', 'sort_natural', 'split', 'strip',
'strip_html', 'strip_newlines', 'times', 'truncate', 'truncatewords',
'uniq', 'upcase', 'url_decode', 'url_encode'];
for (let i = 0; i < keywords.length; i++) {
autocompleteProviderItems.push({'label': keywords[i], kind: monaco.languages.CompletionItemKind.Keyword});
}
return {suggestions: autocompleteProviderItems};
}
});
}
render() {
const padding = this.padding || 'elsa-pt-1.5 elsa-pl-1';
return (
<Host
class="monaco-editor-host border focus:ring-blue-500 focus:border-blue-500 block w-full min-w-0 rounded-md sm:text-sm border-gray-300 p-4"
style={{'min-height': this.editorHeight}}>
<div ref={el => this.container = el} class={`monaco-editor-container ${padding}`}/>
</Host>
)
}
}

View file

@ -0,0 +1,39 @@
const win = window as any;
const require = win.require;
export interface Monaco {
editor: any;
languages: any;
KeyCode: any;
Uri: any;
}
export function initializeMonacoWorker(libPath?: string): Promise<Monaco> {
if (win.monaco)
return win.monaco;
if (!libPath)
return win.monaco;
const origin = document.location.origin;
const baseUrl = libPath.startsWith('http') ? libPath : `${origin}/${libPath}`;
require.config({paths: {'vs': `${baseUrl}/vs`}});
win.MonacoEnvironment = {getWorkerUrl: () => proxy};
let proxy = URL.createObjectURL(new Blob([`
self.MonacoEnvironment = {
baseUrl: '${baseUrl}'
};
importScripts('${baseUrl}/vs/base/worker/workerMain.js');
`], {type: 'text/javascript'}));
return new Promise(resolve => {
require(["vs/editor/editor.main"], () => {
resolve(win.monaco);
});
});
}
export const DefaultLibUri: string = 'defaultLib:lib.es6.d.ts';

View file

@ -5,6 +5,7 @@ import {ElsaApiClientProvider, ElsaClient, SaveWorkflowRequest, ServerSettings}
import {ActivityDescriptor, TriggerDescriptor, VersionOptions, Workflow, WorkflowInstanceSummary, WorkflowSummary} from '../../../models';
import {WorkflowUpdatedArgs} from '../../designer/workflow-editor/workflow-editor';
import {PublishClickedArgs} from "../../toolbar/workflow-publish-button/workflow-publish-button";
import {MonacoEditorSettings} from "../../../services/monaco-editor-settings";
@Component({
tag: 'elsa-studio'
@ -17,7 +18,7 @@ export class Studio {
@Element() private el: HTMLElsaStudioElement;
@Prop({attribute: 'server'}) public serverUrl: string;
@Prop({attribute: 'monaco-lib-path'}) public monacoLibPath: string;
@Watch('serverUrl')
private handleServerUrl(value: string) {
@ -25,6 +26,15 @@ export class Studio {
settings.baseAddress = value;
}
@Watch('monacoLibPath')
private handleMonacoLibPath(value: string) {
const settings = Container.get(MonacoEditorSettings);
settings.monacoLibPath = value;
if (!!this.workflowEditorElement)
this.workflowEditorElement.monacoLibPath = this.monacoLibPath;
}
@Listen('workflowUpdated')
private async handleWorkflowUpdated(e: CustomEvent<WorkflowUpdatedArgs>) {
const workflow = e.detail.workflow;
@ -84,6 +94,7 @@ export class Studio {
if (!!this.workflowEditorElement) {
this.workflowEditorElement.activityDescriptors = this.activityDescriptors;
this.workflowEditorElement.triggerDescriptors = this.triggerDescriptors;
this.workflowEditorElement.monacoLibPath = this.monacoLibPath;
}
}

View file

@ -6,12 +6,13 @@
<title>Elsa Workflows Designer</title>
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
<link rel="stylesheet" href="/build/elsa-workflows-designer.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.31.1/min/vs/loader.min.js"></script>
<script type="module" src="/build/elsa-workflows-designer.esm.js"></script>
<script nomodule src="/build/elsa-workflows-designer.js"></script>
</head>
<body>
<!--Use the Server Shell component to handle automatic interaction with the Elsa Server API-->
<elsa-studio server="https://localhost:5001">
<elsa-studio server="https://localhost:5001" monaco-lib-path="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.31.1/min">
<elsa-workflow-toolbar></elsa-workflow-toolbar>
<div class="absolute inset-0" style="top: 63px;">
<elsa-workflow-editor></elsa-workflow-editor>

View file

@ -92,3 +92,8 @@ export interface RuntimeSelectListProviderSettings {
runtimeSelectListProviderType: string;
context?: any;
}
export enum EditorHeight {
Default = 'Default',
Large = 'Large'
}

View file

@ -1,5 +1,11 @@
export * from './activity-driver';
export * from './activity-driver-registry';
export * from './activity-icon-registry';
export * from './custom-event-bus';
export * from './elsa-api-client-provider';
export * from './event-bus';
export * from './input-control-registry';
export * from './input-driver-registry';
export * from './server-settings';
export * from './trigger-driver';
export * from './trigger-driver-registry';

View file

@ -16,6 +16,7 @@ export class InputControlRegistry {
this.add('check-list', c => <elsa-check-list-input inputContext={c}/>);
this.add('radio-list', c => <elsa-radio-list-input inputContext={c}/>);
this.add('multi-text', c => <elsa-multi-text-input inputContext={c}/>);
this.add('code-editor', c => <elsa-code-editor-input inputContext={c}/>);
}
public add(uiHint: UIHint, control: RenderActivityPropInputControl) {

View file

@ -0,0 +1,13 @@
import {Service} from "typedi";
import store from "../data/store";
@Service()
export class MonacoEditorSettings {
get monacoLibPath(): string {
return store.monacoLibPath;
}
set monacoLibPath(value: string) {
store.monacoLibPath = value;
}
}

View file

@ -38,10 +38,13 @@ public class WriteLines : Activity, IActivityPropertyOptionsProvider
[Input(Options = new[] { "Normal", "Bold", "Italic" }, UIHint = InputUIHints.RadioList)]
public Input<string> Format { get; set; } = default!;
[Input(OptionsProvider = typeof(WriteLines), UIHint = InputUIHints.MultiLine)]
public Input<string> Body { get; set; } = default!;
[Input(UIHint = InputUIHints.CodeEditor, OptionsProvider = typeof(WriteLines))]
public Input<string> Script { get; set; } = default!;
[Input(UIHint = InputUIHints.MultiText)]
public Input<ICollection<string>> Tags { get; set; } = default!;
@ -55,9 +58,11 @@ public class WriteLines : Activity, IActivityPropertyOptionsProvider
public object? GetOptions(PropertyInfo property)
{
if (property.Name == nameof(Body))
return new MultiLineOptions(EditorHeight.Large);
return null;
return property.Name switch
{
nameof(Body) => new { EditorHeight = EditorHeight.Large },
nameof(Script) => new { EditorHeight = EditorHeight.Large, Language = "JavaScript" },
_ => null
};
}
}