Added feature panel. Added ability to manage experimental features. (#2619)
This commit is contained in:
parent
5bc368efe7
commit
88e6987176
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"workflowLayout": {
|
||||
"enabled": true,
|
||||
"ui": true,
|
||||
"defaultValue": "topbottom"
|
||||
}
|
||||
}
|
||||
|
|
@ -49,6 +49,9 @@ export namespace Components {
|
|||
interface ElsaCopyButton {
|
||||
"value": string;
|
||||
}
|
||||
interface ElsaDesignerPanel {
|
||||
"culture": string;
|
||||
}
|
||||
interface ElsaDesignerTree {
|
||||
"activityBorderColor"?: (activity: ActivityModel) => string;
|
||||
"activityContextMenu"?: ActivityContextMenuState;
|
||||
|
|
@ -201,8 +204,9 @@ export namespace Components {
|
|||
"addPlugin": (pluginType: any) => Promise<void>;
|
||||
"addPlugins": (pluginTypes: Array<any>) => Promise<void>;
|
||||
"basePath": string;
|
||||
"config": string;
|
||||
"culture": string;
|
||||
"featuresString": string;
|
||||
"features": any;
|
||||
"monacoLibPath": string;
|
||||
"serverUrl": string;
|
||||
}
|
||||
|
|
@ -285,6 +289,7 @@ export namespace Components {
|
|||
"basePath": string;
|
||||
"culture": string;
|
||||
"exportWorkflow": () => Promise<void>;
|
||||
"features": string;
|
||||
"getServerUrl": () => Promise<string>;
|
||||
"getWorkflowDefinitionId": () => Promise<string>;
|
||||
"history": RouterHistory;
|
||||
|
|
@ -410,6 +415,12 @@ declare global {
|
|||
prototype: HTMLElsaCopyButtonElement;
|
||||
new (): HTMLElsaCopyButtonElement;
|
||||
};
|
||||
interface HTMLElsaDesignerPanelElement extends Components.ElsaDesignerPanel, HTMLStencilElement {
|
||||
}
|
||||
var HTMLElsaDesignerPanelElement: {
|
||||
prototype: HTMLElsaDesignerPanelElement;
|
||||
new (): HTMLElsaDesignerPanelElement;
|
||||
};
|
||||
interface HTMLElsaDesignerTreeElement extends Components.ElsaDesignerTree, HTMLStencilElement {
|
||||
}
|
||||
var HTMLElsaDesignerTreeElement: {
|
||||
|
|
@ -731,6 +742,7 @@ declare global {
|
|||
"elsa-context-menu": HTMLElsaContextMenuElement;
|
||||
"elsa-control": HTMLElsaControlElement;
|
||||
"elsa-copy-button": HTMLElsaCopyButtonElement;
|
||||
"elsa-designer-panel": HTMLElsaDesignerPanelElement;
|
||||
"elsa-designer-tree": HTMLElsaDesignerTreeElement;
|
||||
"elsa-dictionary-property": HTMLElsaDictionaryPropertyElement;
|
||||
"elsa-dropdown-button": HTMLElsaDropdownButtonElement;
|
||||
|
|
@ -815,6 +827,11 @@ declare namespace LocalJSX {
|
|||
interface ElsaCopyButton {
|
||||
"value"?: string;
|
||||
}
|
||||
interface ElsaDesignerPanel {
|
||||
"culture"?: string;
|
||||
"onFeatureChanged"?: (event: CustomEvent<string>) => void;
|
||||
"onFeatureStatusChanged"?: (event: CustomEvent<string>) => void;
|
||||
}
|
||||
interface ElsaDesignerTree {
|
||||
"activityBorderColor"?: (activity: ActivityModel) => string;
|
||||
"activityContextMenu"?: ActivityContextMenuState;
|
||||
|
|
@ -973,8 +990,9 @@ declare namespace LocalJSX {
|
|||
}
|
||||
interface ElsaStudioRoot {
|
||||
"basePath"?: string;
|
||||
"config"?: string;
|
||||
"culture"?: string;
|
||||
"featuresString"?: string;
|
||||
"features"?: any;
|
||||
"monacoLibPath"?: string;
|
||||
"onInitialized"?: (event: CustomEvent<ElsaStudio>) => void;
|
||||
"onInitializing"?: (event: CustomEvent<ElsaStudio>) => void;
|
||||
|
|
@ -1053,6 +1071,7 @@ declare namespace LocalJSX {
|
|||
interface ElsaWorkflowDefinitionEditorScreen {
|
||||
"basePath"?: string;
|
||||
"culture"?: string;
|
||||
"features"?: string;
|
||||
"history"?: RouterHistory;
|
||||
"monacoLibPath"?: string;
|
||||
"onWorkflowSaved"?: (event: CustomEvent<WorkflowDefinition>) => void;
|
||||
|
|
@ -1136,6 +1155,7 @@ declare namespace LocalJSX {
|
|||
"elsa-context-menu": ElsaContextMenu;
|
||||
"elsa-control": ElsaControl;
|
||||
"elsa-copy-button": ElsaCopyButton;
|
||||
"elsa-designer-panel": ElsaDesignerPanel;
|
||||
"elsa-designer-tree": ElsaDesignerTree;
|
||||
"elsa-dictionary-property": ElsaDictionaryProperty;
|
||||
"elsa-dropdown-button": ElsaDropdownButton;
|
||||
|
|
@ -1202,6 +1222,7 @@ declare module "@stencil/core" {
|
|||
"elsa-context-menu": LocalJSX.ElsaContextMenu & JSXBase.HTMLAttributes<HTMLElsaContextMenuElement>;
|
||||
"elsa-control": LocalJSX.ElsaControl & JSXBase.HTMLAttributes<HTMLElsaControlElement>;
|
||||
"elsa-copy-button": LocalJSX.ElsaCopyButton & JSXBase.HTMLAttributes<HTMLElsaCopyButtonElement>;
|
||||
"elsa-designer-panel": LocalJSX.ElsaDesignerPanel & JSXBase.HTMLAttributes<HTMLElsaDesignerPanelElement>;
|
||||
"elsa-designer-tree": LocalJSX.ElsaDesignerTree & JSXBase.HTMLAttributes<HTMLElsaDesignerTreeElement>;
|
||||
"elsa-dictionary-property": LocalJSX.ElsaDictionaryProperty & JSXBase.HTMLAttributes<HTMLElsaDictionaryPropertyElement>;
|
||||
"elsa-dropdown-button": LocalJSX.ElsaDropdownButton & JSXBase.HTMLAttributes<HTMLElsaDropdownButtonElement>;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import {Component, Event, EventEmitter, h, Listen, Method, Prop} from '@stencil/core';
|
||||
import {Component, Event, EventEmitter, h, Listen, Method, Prop, State} from '@stencil/core';
|
||||
import Tunnel, {DashboardState} from "../../../../data/dashboard";
|
||||
import {ElsaStudio, WorkflowModel} from "../../../../models";
|
||||
import {
|
||||
|
|
@ -10,7 +10,8 @@ import {
|
|||
createElsaClient,
|
||||
createHttpClient,
|
||||
ElsaClient,
|
||||
propertyDisplayManager
|
||||
propertyDisplayManager,
|
||||
featuresDataManager
|
||||
} from "../../../../services";
|
||||
import {AxiosInstance} from "axios";
|
||||
import {EventTypes} from "../../../../models";
|
||||
|
|
@ -27,7 +28,9 @@ export class ElsaStudioRoot {
|
|||
@Prop({attribute: 'monaco-lib-path', reflect: true}) monacoLibPath: string;
|
||||
@Prop({attribute: 'culture', reflect: true}) culture: string;
|
||||
@Prop({attribute: 'base-path', reflect: true}) basePath: string = '';
|
||||
@Prop({attribute: 'features', reflect: true}) featuresString: string;
|
||||
@Prop() features: any;
|
||||
@Prop() config: string;
|
||||
@State() featuresConfig: any;
|
||||
@Event() initializing: EventEmitter<ElsaStudio>;
|
||||
@Event() initialized: EventEmitter<ElsaStudio>;
|
||||
|
||||
|
|
@ -67,13 +70,26 @@ export class ElsaStudioRoot {
|
|||
async componentWillLoad() {
|
||||
const elsaClientFactory: () => Promise<ElsaClient> = () => createElsaClient(this.serverUrl);
|
||||
const httpClientFactory: () => Promise<AxiosInstance> = () => createHttpClient(this.serverUrl);
|
||||
await fetch(`${document.location.origin}/${this.config}`)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error("HTTP error " + response.status);
|
||||
}
|
||||
|
||||
return response.json()
|
||||
})
|
||||
.then(data => {
|
||||
this.featuresConfig = data;
|
||||
}).catch((error) => {
|
||||
console.error(error)
|
||||
});
|
||||
|
||||
const elsaClient = await elsaClientFactory();
|
||||
|
||||
const elsaStudio: ElsaStudio = this.elsaStudio = {
|
||||
serverUrl: this.serverUrl,
|
||||
basePath: this.basePath,
|
||||
featuresString: this.featuresString,
|
||||
features: this.featuresConfig,
|
||||
serverFeatures: [],
|
||||
eventBus,
|
||||
pluginManager,
|
||||
|
|
@ -91,6 +107,7 @@ export class ElsaStudioRoot {
|
|||
await eventBus.emit(EventTypes.Root.Initializing);
|
||||
pluginManager.initialize(elsaStudio);
|
||||
propertyDisplayManager.initialize(elsaStudio);
|
||||
featuresDataManager.initialize(elsaStudio);
|
||||
|
||||
elsaStudio.serverFeatures = await elsaClient.featuresApi.list();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,13 +7,14 @@
|
|||
|
||||
## Properties
|
||||
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ---------------- | ----------------- | ----------- | -------- | ----------- |
|
||||
| `basePath` | `base-path` | | `string` | `''` |
|
||||
| `culture` | `culture` | | `string` | `undefined` |
|
||||
| `featuresString` | `features` | | `string` | `undefined` |
|
||||
| `monacoLibPath` | `monaco-lib-path` | | `string` | `undefined` |
|
||||
| `serverUrl` | `server-url` | | `string` | `undefined` |
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| --------------- | ----------------- | ----------- | -------- | ----------- |
|
||||
| `basePath` | `base-path` | | `string` | `''` |
|
||||
| `config` | `config` | | `string` | `undefined` |
|
||||
| `culture` | `culture` | | `string` | `undefined` |
|
||||
| `features` | `features` | | `any` | `undefined` |
|
||||
| `monacoLibPath` | `monaco-lib-path` | | `string` | `undefined` |
|
||||
| `serverUrl` | `server-url` | | `string` | `undefined` |
|
||||
|
||||
|
||||
## Events
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ graph TD;
|
|||
elsa-workflow-definition-editor-screen --> elsa-tab-content
|
||||
elsa-workflow-definition-editor-screen --> elsa-workflow-properties-panel
|
||||
elsa-workflow-definition-editor-screen --> elsa-workflow-test-panel
|
||||
elsa-workflow-definition-editor-screen --> elsa-designer-panel
|
||||
elsa-workflow-definition-editor-screen --> context-consumer
|
||||
elsa-workflow-settings-modal --> elsa-modal-dialog
|
||||
elsa-workflow-settings-modal --> elsa-monaco
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ export class ElsaWorkflowDesigner {
|
|||
@Prop() connectionContextMenu?: ActivityContextMenuState;
|
||||
@Prop() activityContextTestMenu?: ActivityContextMenuState;
|
||||
@Prop() mode: WorkflowDesignerMode = WorkflowDesignerMode.Edit;
|
||||
@Prop() layoutDirection: LayoutDirection = LayoutDirection.Vertical;
|
||||
@Prop() layoutDirection: LayoutDirection = LayoutDirection.TopBottom;
|
||||
@Prop({attribute: 'enable-multiple-connections'}) enableMultipleConnectionsFromSingleSource: boolean;
|
||||
@Event({
|
||||
eventName: 'workflow-changed',
|
||||
|
|
@ -568,9 +568,7 @@ export class ElsaWorkflowDesigner {
|
|||
|
||||
setEntities() {
|
||||
this.graph = new dagreD3.graphlib.Graph().setGraph({});
|
||||
|
||||
const layoutDirection = this.layoutDirection;
|
||||
this.graph.graph().rankdir = layoutDirection == LayoutDirection.Vertical ? 'TB' : 'LR';
|
||||
this.graph.graph().rankdir = this.getLayoutDirection();
|
||||
|
||||
const rootActivities = this.getRootActivities();
|
||||
|
||||
|
|
@ -947,4 +945,18 @@ export class ElsaWorkflowDesigner {
|
|||
</Host>
|
||||
);
|
||||
}
|
||||
|
||||
private getLayoutDirection = () => {
|
||||
switch (this.layoutDirection) {
|
||||
case LayoutDirection.BottomTop:
|
||||
return 'BT';
|
||||
case LayoutDirection.LeftRight:
|
||||
return 'LR';
|
||||
case LayoutDirection.RightLeft:
|
||||
return 'RL';
|
||||
case LayoutDirection.TopBottom:
|
||||
default:
|
||||
return 'TB';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ export interface ActivityContextMenuState {
|
|||
}
|
||||
|
||||
export enum LayoutDirection {
|
||||
Horizontal,
|
||||
Vertical
|
||||
LeftRight ='leftright',
|
||||
TopBottom = 'topbottom',
|
||||
RightLeft = 'rightleft',
|
||||
BottomTop = 'bottomtop'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
| `activityContextTestMenu` | -- | | `ActivityContextMenuState` | `undefined` |
|
||||
| `connectionContextMenu` | -- | | `ActivityContextMenuState` | `undefined` |
|
||||
| `enableMultipleConnectionsFromSingleSource` | `enable-multiple-connections` | | `boolean` | `undefined` |
|
||||
| `layoutDirection` | `layout-direction` | | `LayoutDirection.Horizontal \| LayoutDirection.Vertical` | `LayoutDirection.Vertical` |
|
||||
| `layoutDirection` | `layout-direction` | | `LayoutDirection.BottomTop \| LayoutDirection.LeftRight \| LayoutDirection.RightLeft \| LayoutDirection.TopBottom` | `LayoutDirection.TopBottom` |
|
||||
| `mode` | `mode` | | `WorkflowDesignerMode.Blueprint \| WorkflowDesignerMode.Edit \| WorkflowDesignerMode.Instance \| WorkflowDesignerMode.Test` | `WorkflowDesignerMode.Edit` |
|
||||
| `model` | -- | | `WorkflowModel` | `{ activities: [], connections: [], persistenceBehavior: WorkflowPersistenceBehavior.WorkflowBurst }` |
|
||||
| `selectedActivityIds` | -- | | `string[]` | `[]` |
|
||||
|
|
|
|||
|
|
@ -1,33 +1,38 @@
|
|||
import {Component, Event, EventEmitter, h, Host, Listen, Method, Prop, State, Watch} from '@stencil/core';
|
||||
import {RouterHistory, injectHistory} from '@stencil/router';
|
||||
import {injectHistory, RouterHistory} from '@stencil/router';
|
||||
import {
|
||||
ActivityDefinition,
|
||||
ActivityDescriptor,
|
||||
ActivityModel,
|
||||
ConfigureComponentCustomButtonContext,
|
||||
ComponentCustomButtonClickContext,
|
||||
ConfigureComponentCustomButtonContext,
|
||||
ConnectionDefinition,
|
||||
ConnectionModel,
|
||||
EventTypes,
|
||||
VersionOptions,
|
||||
WorkflowDefinition,
|
||||
WorkflowInstance,
|
||||
WorkflowModel,
|
||||
WorkflowPersistenceBehavior,
|
||||
WorkflowTestActivityMessage,
|
||||
WorkflowInstance, WorkflowTestActivityMessageStatus,
|
||||
WorkflowTestActivityMessageStatus,
|
||||
} from "../../../../models";
|
||||
import {
|
||||
ActivityStats,
|
||||
createElsaClient,
|
||||
eventBus,
|
||||
SaveWorkflowDefinitionRequest, toastNotificationService,
|
||||
WorkflowTestRestartFromActivityRequest
|
||||
featuresDataManager,
|
||||
SaveWorkflowDefinitionRequest
|
||||
} from "../../../../services";
|
||||
import state from '../../../../utils/store';
|
||||
import WorkflowEditorTunnel, {WorkflowEditorState} from '../../../../data/workflow-editor';
|
||||
import DashboardTunnel from "../../../../data/dashboard";
|
||||
import {downloadFromBlob} from "../../../../utils/download";
|
||||
import {ActivityContextMenuState, WorkflowDesignerMode} from "../../../designers/tree/elsa-designer-tree/models";
|
||||
import {
|
||||
ActivityContextMenuState,
|
||||
LayoutDirection,
|
||||
WorkflowDesignerMode
|
||||
} from "../../../designers/tree/elsa-designer-tree/models";
|
||||
import {i18n} from "i18next";
|
||||
import {loadTranslations} from "../../../i18n/i18n-loader";
|
||||
import {resources} from "./localizations";
|
||||
|
|
@ -44,6 +49,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
|
|||
@Prop({attribute: 'workflow-definition-id', reflect: true}) workflowDefinitionId: string;
|
||||
@Prop({attribute: 'server-url', reflect: true}) serverUrl: string;
|
||||
@Prop({attribute: 'monaco-lib-path', reflect: true}) monacoLibPath: string;
|
||||
@Prop() features: string;
|
||||
@Prop() culture: string;
|
||||
@Prop() basePath: string;
|
||||
@Prop() serverFeatures: Array<string> = [];
|
||||
|
|
@ -64,6 +70,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
|
|||
@State() workflowInstance?: WorkflowInstance;
|
||||
@State() workflowInstanceId?: string;
|
||||
@State() activityStats?: ActivityStats;
|
||||
@State() layoutDirection: LayoutDirection = LayoutDirection.TopBottom;//???
|
||||
|
||||
@State() activityContextMenuState: ActivityContextMenuState = {
|
||||
shown: false,
|
||||
|
|
@ -197,6 +204,11 @@ export class ElsaWorkflowDefinitionEditorScreen {
|
|||
async componentWillLoad() {
|
||||
this.i18next = await loadTranslations(this.culture, resources);
|
||||
this.workflowDesignerMode = WorkflowDesignerMode.Edit;
|
||||
|
||||
const layoutFeature = featuresDataManager.getFeatureConfig(featuresDataManager.supportedFeatures.workflowLayout);
|
||||
if (layoutFeature && layoutFeature.enabled) {
|
||||
this.layoutDirection = layoutFeature.value as LayoutDirection;
|
||||
}
|
||||
await this.serverUrlChangedHandler(this.serverUrl);
|
||||
await this.workflowDefinitionIdChangedHandler(this.workflowDefinitionId);
|
||||
await this.monacoLibPathChangedHandler(this.monacoLibPath);
|
||||
|
|
@ -647,6 +659,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
|
|||
<div class="elsa-flex-1 elsa-flex elsa-relative">
|
||||
<elsa-designer-tree model={this.workflowModel}
|
||||
mode={this.workflowDesignerMode}
|
||||
layoutDirection={this.layoutDirection}
|
||||
activityContextMenuButton={this.workflowDesignerMode == WorkflowDesignerMode.Edit
|
||||
? activityContextMenuButton
|
||||
: this.renderActivityStatsButton}
|
||||
|
|
@ -1061,6 +1074,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
|
|||
/>
|
||||
</elsa-tab-content>
|
||||
{this.renderTestPanel()}
|
||||
{this.renderDesignerPanel()}
|
||||
</elsa-flyout-panel>
|
||||
);
|
||||
}
|
||||
|
|
@ -1081,6 +1095,44 @@ export class ElsaWorkflowDefinitionEditorScreen {
|
|||
</elsa-tab-content>
|
||||
];
|
||||
}
|
||||
|
||||
private renderDesignerPanel = () => {
|
||||
const isFeaturePanelVisible = featuresDataManager.getUIFeatureList().length != 0;
|
||||
|
||||
if (isFeaturePanelVisible) {
|
||||
return [
|
||||
<elsa-tab-header tab="designer" slot="header">Designer</elsa-tab-header>,
|
||||
<elsa-tab-content tab="designer" slot="content">
|
||||
<elsa-designer-panel
|
||||
onFeatureChanged={this.handleFeatureChange}
|
||||
onFeatureStatusChanged={this.handleFeatureStatusChange}
|
||||
/>
|
||||
</elsa-tab-content>
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
handleFeatureChange = (e: CustomEvent<string>) => {
|
||||
const feature = e.detail;
|
||||
|
||||
if (feature === featuresDataManager.supportedFeatures.workflowLayout) {
|
||||
const layoutFeature = featuresDataManager.getFeatureConfig(feature);
|
||||
this.layoutDirection = layoutFeature.value as LayoutDirection;
|
||||
}
|
||||
}
|
||||
|
||||
handleFeatureStatusChange = (e: CustomEvent<string>) => {
|
||||
const feature = e.detail;
|
||||
|
||||
if (feature === featuresDataManager.supportedFeatures.workflowLayout) {
|
||||
const layoutFeature = featuresDataManager.getFeatureConfig(feature);
|
||||
if (layoutFeature.enabled) {
|
||||
this.layoutDirection = layoutFeature.value as LayoutDirection;
|
||||
} else {
|
||||
this.layoutDirection = LayoutDirection.TopBottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
injectHistory(ElsaWorkflowDefinitionEditorScreen);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
| Property | Attribute | Description | Type | Default |
|
||||
| ---------------------- | ------------------------ | ----------- | --------------- | ----------- |
|
||||
| `culture` | `culture` | | `string` | `undefined` |
|
||||
| `features` | `features` | | `string` | `undefined` |
|
||||
| `history` | -- | | `RouterHistory` | `undefined` |
|
||||
| `monacoLibPath` | `monaco-lib-path` | | `string` | `undefined` |
|
||||
| `serverUrl` | `server-url` | | `string` | `undefined` |
|
||||
|
|
@ -88,6 +89,7 @@ Type: `Promise<void>`
|
|||
- [elsa-tab-content](../../../shared/elsa-tab-content)
|
||||
- [elsa-workflow-properties-panel](../elsa-workflow-properties-panel)
|
||||
- [elsa-workflow-test-panel](../elsa-workflow-test-panel)
|
||||
- [elsa-designer-panel](../../../shared/elsa-designer-panel)
|
||||
- context-consumer
|
||||
|
||||
### Graph
|
||||
|
|
@ -107,6 +109,7 @@ graph TD;
|
|||
elsa-workflow-definition-editor-screen --> elsa-tab-content
|
||||
elsa-workflow-definition-editor-screen --> elsa-workflow-properties-panel
|
||||
elsa-workflow-definition-editor-screen --> elsa-workflow-test-panel
|
||||
elsa-workflow-definition-editor-screen --> elsa-designer-panel
|
||||
elsa-workflow-definition-editor-screen --> context-consumer
|
||||
elsa-workflow-settings-modal --> elsa-modal-dialog
|
||||
elsa-workflow-settings-modal --> elsa-monaco
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
import {Component, Host, h, Event, EventEmitter, Prop, State} from '@stencil/core';
|
||||
import {FeatureConfig, featuresDataManager} from "../../../services";
|
||||
import {LayoutDirection} from "../../designers/tree/elsa-designer-tree/models";
|
||||
import {i18n} from "i18next";
|
||||
import {resources} from "./localizations";
|
||||
import {loadTranslations} from "../../i18n/i18n-loader";
|
||||
|
||||
@Component({
|
||||
tag: 'elsa-designer-panel',
|
||||
shadow: false,
|
||||
})
|
||||
|
||||
export class ElsaDesignerPanel {
|
||||
|
||||
@Prop() culture: string;
|
||||
@State() lastChangeTime: Date;
|
||||
@Event() featureChanged: EventEmitter<string>;
|
||||
@Event() featureStatusChanged: EventEmitter<string>;
|
||||
|
||||
i18next: i18n;
|
||||
|
||||
async componentWillLoad() {
|
||||
this.i18next = await loadTranslations(this.culture, resources);
|
||||
}
|
||||
|
||||
t = (key: string, options?: any) => this.i18next.t(key, options);
|
||||
|
||||
render() {
|
||||
const features = featuresDataManager.getUIFeatureList();
|
||||
const {t} = this;
|
||||
|
||||
return (
|
||||
<Host>
|
||||
<div class="elsa-mt-4">
|
||||
{features.map(name => {
|
||||
const feature = featuresDataManager.getFeatureConfig(name);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div class="elsa-relative elsa-flex elsa-items-start elsa-ml-1">
|
||||
<div class="elsa-flex elsa-items-center elsa-h-5">
|
||||
<input
|
||||
id={name}
|
||||
name={name}
|
||||
type="checkbox"
|
||||
value={`${feature.enabled}`}
|
||||
checked={feature.enabled}
|
||||
onChange={e => this.onToggleChange(e, name)}
|
||||
class="focus:elsa-ring-blue-500 elsa-h-4 elsa-w-4 elsa-text-blue-600 elsa-border-gray-300 rounded"
|
||||
/>
|
||||
</div>
|
||||
<div class="elsa-ml-3 elsa-text-sm">
|
||||
<label htmlFor={name} class="elsa-font-medium elsa-text-gray-700">{t(`${name}Name`)}</label>
|
||||
<p class="elsa-text-gray-500">{t(`${name}Description`)}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="elsa-ml-1 elsa-my-4">
|
||||
{this.renderFeatureData(name, feature)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
|
||||
renderFeatureData = (name: string, feature: FeatureConfig) => {
|
||||
if (!feature.enabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {t} = this;
|
||||
switch (name) {
|
||||
case featuresDataManager.supportedFeatures.workflowLayout:
|
||||
return (
|
||||
<select id={name} name={name} onChange={e => this.onPropertyChange(e, name)} class="block focus:elsa-ring-blue-500 focus:elsa-border-blue-500 elsa-w-full elsa-shadow-sm sm:elsa-text-sm elsa-border-gray-300 elsa-rounded-md">
|
||||
{Object.keys(LayoutDirection).map(key => {
|
||||
return <option value={LayoutDirection[key]} selected={LayoutDirection[key] === feature.value}>{t(key)}</option>;
|
||||
})}
|
||||
</select>
|
||||
)
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
onToggleChange = (e: Event, name: string) => {
|
||||
const element = e.target as HTMLInputElement;
|
||||
featuresDataManager.setEnableStatus(name, element.checked);
|
||||
this.lastChangeTime = new Date();
|
||||
this.featureStatusChanged.emit(name);
|
||||
}
|
||||
|
||||
onPropertyChange = (e: Event, name: string) => {
|
||||
const element = e.target as HTMLInputElement;
|
||||
featuresDataManager.setFeatureConfig(name, element.value.trim());
|
||||
this.featureChanged.emit(name);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
export const resources = {
|
||||
'en': {
|
||||
default: {
|
||||
'workflowLayoutName': 'Workflow Layout',
|
||||
'workflowLayoutDescription': 'Determines the directions cards are displayed in. Changed for every workflow.',
|
||||
'TopBottom': 'Top to Bottom',
|
||||
'LeftRight': 'Left to Right',
|
||||
'BottomTop': 'Bottom to Top',
|
||||
'RightLeft': 'Right to Left',
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
# elsa-designer-panel
|
||||
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| --------- | --------- | ----------- | -------- | ----------- |
|
||||
| `culture` | `culture` | | `string` | `undefined` |
|
||||
|
||||
|
||||
## Events
|
||||
|
||||
| Event | Description | Type |
|
||||
| ---------------------- | ----------- | --------------------- |
|
||||
| `featureChanged` | | `CustomEvent<string>` |
|
||||
| `featureStatusChanged` | | `CustomEvent<string>` |
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Used by
|
||||
|
||||
- [elsa-workflow-definition-editor-screen](../../screens/workflow-definition-editor/elsa-workflow-definition-editor-screen)
|
||||
|
||||
### Graph
|
||||
```mermaid
|
||||
graph TD;
|
||||
elsa-workflow-definition-editor-screen --> elsa-designer-panel
|
||||
style elsa-designer-panel fill:#f9f,stroke:#333,stroke-width:4px
|
||||
```
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
*Built with [StencilJS](https://stenciljs.com/)*
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<elsa-studio-root server-url="https://localhost:11000" monaco-lib-path="build/assets/js/monaco-editor/min" culture="en-US">
|
||||
<elsa-studio-root server-url="https://localhost:11000" monaco-lib-path="build/assets/js/monaco-editor/min" culture="en-US" config="build/assets/designer.config.json">
|
||||
<!-- The root dashboard component -->
|
||||
<elsa-studio-dashboard></elsa-studio-dashboard>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {ActivityModel} from "./view";
|
|||
export interface ElsaStudio {
|
||||
serverUrl: string;
|
||||
basePath: string;
|
||||
featuresString: string;
|
||||
features: any;
|
||||
serverFeatures: Array<string>;
|
||||
pluginManager: PluginManager;
|
||||
propertyDisplayManager: PropertyDisplayManager;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
import {ElsaStudio} from "../models/";
|
||||
|
||||
export interface FeatureConfig {
|
||||
enabled: boolean;
|
||||
ui: boolean;
|
||||
defaultValue: string;
|
||||
value?: string;
|
||||
}
|
||||
|
||||
type FeatureConfigMap = {
|
||||
[key:string]: FeatureConfig;
|
||||
}
|
||||
|
||||
export class FeaturesDataManager {
|
||||
|
||||
elsaStudio: ElsaStudio;
|
||||
initialized: boolean;
|
||||
features: FeatureConfigMap;
|
||||
supportedFeatures = {
|
||||
workflowLayout: 'workflowLayout'
|
||||
}
|
||||
|
||||
initialize(elsaStudio: ElsaStudio) {
|
||||
if (this.initialized)
|
||||
return;
|
||||
|
||||
this.elsaStudio = elsaStudio;
|
||||
this.initialized = true;
|
||||
this.features = elsaStudio.features || {};
|
||||
}
|
||||
|
||||
getFeatureList = () => {
|
||||
return Object.keys(this.features);
|
||||
}
|
||||
|
||||
getUIFeatureList = () => {
|
||||
return Object.keys(this.features).filter(feature => this.features[feature].ui);
|
||||
}
|
||||
|
||||
getFeatureConfig = (name: string) => {
|
||||
const value = localStorage.getItem(`elsa.properties.${name}`);
|
||||
const enabled = localStorage.getItem(`elsa.properties.${name}.enabled`);
|
||||
const feature = this.features[name];
|
||||
|
||||
if (feature) {
|
||||
return {
|
||||
...feature,
|
||||
value: value === null ? feature.defaultValue : value,
|
||||
'enabled': enabled === null ? feature.enabled : enabled === 'true'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setFeatureConfig = (name: string, value: string) => {
|
||||
const feature = this.features[name];
|
||||
|
||||
if (feature) {
|
||||
localStorage.setItem(`elsa.properties.${name}`, value);
|
||||
}
|
||||
}
|
||||
|
||||
setEnableStatus = (name: string, value: boolean) => {
|
||||
const feature = this.features[name];
|
||||
|
||||
if (feature) {
|
||||
localStorage.setItem(`elsa.properties.${name}.enabled`, `${value}`);
|
||||
console.log(`elsa.properties.${name}-enabled`, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const featuresDataManager = new FeaturesDataManager();
|
||||
|
|
@ -4,6 +4,7 @@ export * from './toast-notification-service';
|
|||
export * from './elsa-plugin';
|
||||
export * from './elsa-client';
|
||||
export * from './event-bus';
|
||||
export * from './features-data-manager';
|
||||
export * from './plugin-manager';
|
||||
export * from './property-display-driver';
|
||||
export * from './property-display-manager';
|
||||
export * from './property-display-manager';
|
||||
|
|
|
|||
Loading…
Reference in a new issue