diff --git a/src/core/Elsa.Core/Activities/ControlFlow/If/If.cs b/src/core/Elsa.Core/Activities/ControlFlow/If/If.cs index aebc6a07c..336b24241 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/If/If.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/If/If.cs @@ -17,7 +17,7 @@ namespace Elsa.Activities.ControlFlow DisplayName = "If/Else", Category = "Control Flow", Description = "Evaluate a Boolean expression and continue execution depending on the result.", - Outcomes = new[] { True, False, OutcomeNames.Done } + Outcomes = new[] { True, False } )] public class If : Activity, INotificationHandler { diff --git a/src/core/Elsa.Core/Persistence/Specifications/WorkflowDefinitions/VersionOptionsSpecification.cs b/src/core/Elsa.Core/Persistence/Specifications/WorkflowDefinitions/VersionOptionsSpecification.cs index 4cc1cc1c4..923a383b5 100644 --- a/src/core/Elsa.Core/Persistence/Specifications/WorkflowDefinitions/VersionOptionsSpecification.cs +++ b/src/core/Elsa.Core/Persistence/Specifications/WorkflowDefinitions/VersionOptionsSpecification.cs @@ -10,6 +10,8 @@ namespace Elsa.Persistence.Specifications.WorkflowDefinitions public VersionOptionsSpecification(VersionOptions versionOptions) => VersionOptions = versionOptions; public override Expression> ToExpression() { + if (VersionOptions.AllVersions) + return x => true; if (VersionOptions.IsDraft) return x => !x.IsPublished; if (VersionOptions.IsLatest) diff --git a/src/dashboards/blazor/ElsaDashboard.Application/Shared/Pager.razor.cs b/src/dashboards/blazor/ElsaDashboard.Application/Shared/Pager.razor.cs index f9b2b0e1b..ca3944e72 100644 --- a/src/dashboards/blazor/ElsaDashboard.Application/Shared/Pager.razor.cs +++ b/src/dashboards/blazor/ElsaDashboard.Application/Shared/Pager.razor.cs @@ -11,19 +11,6 @@ namespace ElsaDashboard.Application.Shared private int From => Page!.Value * PageSize!.Value + 1; private int To => Math.Min(From + PageSize!.Value, TotalCount); - private int PageCount => (int) (((float) TotalCount - 1) / PageSize!.Value) + 1; - - // private int PageCount - // { - // get - // { - // var count = TotalCount / PageSize!.Value; - // var hasLeftOver = TotalCount % (float) PageSize!.Value == 0; - // var extra = hasLeftOver ? 1 : 0; - // - // return count + extra; - // } - // } } } \ No newline at end of file diff --git a/src/designer/elsa-workflows-studio/package-lock.json b/src/designer/elsa-workflows-studio/package-lock.json index 0a7694f7b..408e66749 100644 --- a/src/designer/elsa-workflows-studio/package-lock.json +++ b/src/designer/elsa-workflows-studio/package-lock.json @@ -12,6 +12,7 @@ "@fullhuman/postcss-purgecss": "^4.0.3", "@stencil/core": "^2.5.2", "@stencil/postcss": "^2.0.0", + "@stencil/router": "^1.0.1", "@stencil/state-tunnel": "^1.0.1", "@stencil/store": "^1.4.1", "@tailwindcss/aspect-ratio": "^0.2.0", @@ -258,6 +259,14 @@ "@stencil/core": ">=2.3.0" } }, + "node_modules/@stencil/router": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stencil/router/-/router-1.0.1.tgz", + "integrity": "sha512-ZMholl1BE+glNAc/8pcEb9RYkeH0XETxsJbx6D7f3azTmaTXqKYty1IACP/3BtVjuimpfLdxQJ+J95wKmnYBtA==", + "dependencies": { + "@stencil/state-tunnel": "^1.0.1" + } + }, "node_modules/@stencil/state-tunnel": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@stencil/state-tunnel/-/state-tunnel-1.0.1.tgz", @@ -10589,6 +10598,14 @@ "postcss": "~8.2.1" } }, + "@stencil/router": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stencil/router/-/router-1.0.1.tgz", + "integrity": "sha512-ZMholl1BE+glNAc/8pcEb9RYkeH0XETxsJbx6D7f3azTmaTXqKYty1IACP/3BtVjuimpfLdxQJ+J95wKmnYBtA==", + "requires": { + "@stencil/state-tunnel": "^1.0.1" + } + }, "@stencil/state-tunnel": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@stencil/state-tunnel/-/state-tunnel-1.0.1.tgz", diff --git a/src/designer/elsa-workflows-studio/package.json b/src/designer/elsa-workflows-studio/package.json index ab2bf0931..d9fcbe782 100644 --- a/src/designer/elsa-workflows-studio/package.json +++ b/src/designer/elsa-workflows-studio/package.json @@ -23,13 +23,14 @@ "test": "stencil test --spec --e2e", "test.watch": "stencil test --spec --e2e --watchAll", "generate": "stencil generate", - "build:tailwind:dev": "cross-env NODE_ENV=development tailwind build ./tailwind.css -o ./src/globals/tailwind.css & copyfiles -u 2 \"./src/globals/tailwind.css\" \"./src/assets\"", - "build:tailwind:prod": "cross-env NODE_ENV=production tailwind build ./tailwind.css -o ./src/globals/tailwind.css & copyfiles -u 2 \"./src/globals/tailwind.css\" \"./src/assets\"" + "build:tailwind:dev": "cross-env NODE_ENV=development tailwind build ./tailwind.css -o ./src/globals/tailwind.css & copyfiles -u 2 \"./src/globals/tailwind.css\" \"./src/assets/styles\"", + "build:tailwind:prod": "cross-env NODE_ENV=production tailwind build ./tailwind.css -o ./src/globals/tailwind.css & copyfiles -u 2 \"./src/globals/tailwind.css\" \"./src/assets/styles\"" }, "dependencies": { "@fullhuman/postcss-purgecss": "^4.0.3", "@stencil/core": "^2.5.2", "@stencil/postcss": "^2.0.0", + "@stencil/router": "^1.0.1", "@stencil/state-tunnel": "^1.0.1", "@stencil/store": "^1.4.1", "@tailwindcss/aspect-ratio": "^0.2.0", @@ -43,6 +44,7 @@ "eslint": "7.23.0", "js-event-bus": "^1.0.3", "jsplumb": "2.15.5", + "lodash": "^4.17.21", "monaco-editor": "^0.23.0", "postcss": "^8.2.9", "postcss-import": "^14.0.0", diff --git a/src/designer/elsa-workflows-studio/src/assets/images/favicon-16x16.png b/src/designer/elsa-workflows-studio/src/assets/images/favicon-16x16.png new file mode 100644 index 000000000..12a813929 Binary files /dev/null and b/src/designer/elsa-workflows-studio/src/assets/images/favicon-16x16.png differ diff --git a/src/designer/elsa-workflows-studio/src/assets/images/favicon-32x32.png b/src/designer/elsa-workflows-studio/src/assets/images/favicon-32x32.png new file mode 100644 index 000000000..a3db0929b Binary files /dev/null and b/src/designer/elsa-workflows-studio/src/assets/images/favicon-32x32.png differ diff --git a/src/designer/elsa-workflows-studio/src/assets/images/favicon.ico b/src/designer/elsa-workflows-studio/src/assets/images/favicon.ico new file mode 100644 index 000000000..1c7b6329c Binary files /dev/null and b/src/designer/elsa-workflows-studio/src/assets/images/favicon.ico differ diff --git a/src/designer/elsa-workflows-studio/src/assets/images/logo.png b/src/designer/elsa-workflows-studio/src/assets/images/logo.png new file mode 100644 index 000000000..28dbaafbf Binary files /dev/null and b/src/designer/elsa-workflows-studio/src/assets/images/logo.png differ diff --git a/src/designer/elsa-workflows-studio/src/assets/tailwind.css b/src/designer/elsa-workflows-studio/src/assets/styles/tailwind.css similarity index 100% rename from src/designer/elsa-workflows-studio/src/assets/tailwind.css rename to src/designer/elsa-workflows-studio/src/assets/styles/tailwind.css diff --git a/src/designer/elsa-workflows-studio/src/components.d.ts b/src/designer/elsa-workflows-studio/src/components.d.ts index 8752c3122..2197ef0c6 100644 --- a/src/designer/elsa-workflows-studio/src/components.d.ts +++ b/src/designer/elsa-workflows-studio/src/components.d.ts @@ -5,10 +5,24 @@ * It contains typing information for all components that exist in this project. */ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; +import { MatchResults, RouterHistory } from "@stencil/router"; import { ActivityDefinitionProperty, ActivityDesignDisplayContext, ActivityModel, ActivityPropertyDescriptor, VersionOptions, WorkflowDefinition, WorkflowModel } from "./models"; -import { MonacoValueChangedArgs } from "./components/editors/monaco/elsa-monaco/elsa-monaco"; +import { MenuItem } from "./components/controls/elsa-context-menu/models"; +import { MonacoValueChangedArgs } from "./components/controls/elsa-monaco/elsa-monaco"; import { ToastNotificationOptions } from "./components/shared/elsa-toast-notification/elsa-toast-notification"; export namespace Components { + interface AppRoot { + "serverUrl": string; + } + interface AppWorkflowDefinitionsEdit { + "match": MatchResults; + "serverUrl": string; + } + interface AppWorkflowDefinitionsList { + "serverUrl": string; + } + interface AppWorkflowRegistry { + } interface ElsaActivityEditorModal { } interface ElsaActivityPickerModal { @@ -21,6 +35,14 @@ export namespace Components { "propertyDescriptor": ActivityPropertyDescriptor; "propertyModel": ActivityDefinitionProperty; } + interface ElsaConfirmDialog { + "hide": () => Promise; + "show": (caption: string, message: string) => Promise; + } + interface ElsaContextMenu { + "history": RouterHistory; + "menuItems": Array; + } interface ElsaDesignerTree { "destroyJsPlumb": () => Promise; "model": WorkflowModel; @@ -96,7 +118,7 @@ export namespace Components { "hide": () => Promise; "show": (options: ToastNotificationOptions) => Promise; } - interface ElsaWorkflowEditor { + interface ElsaWorkflowDefinitionEditorScreen { "exportWorkflow": () => Promise; "getServerUrl": () => Promise; "getWorkflowDefinitionId": () => Promise; @@ -105,6 +127,9 @@ export namespace Components { "serverUrl": string; "workflowDefinitionId": string; } + interface ElsaWorkflowDefinitionsListScreen { + "serverUrl": string; + } interface ElsaWorkflowEditorNotifications { } interface ElsaWorkflowPublishButton { @@ -116,6 +141,30 @@ export namespace Components { } } declare global { + interface HTMLAppRootElement extends Components.AppRoot, HTMLStencilElement { + } + var HTMLAppRootElement: { + prototype: HTMLAppRootElement; + new (): HTMLAppRootElement; + }; + interface HTMLAppWorkflowDefinitionsEditElement extends Components.AppWorkflowDefinitionsEdit, HTMLStencilElement { + } + var HTMLAppWorkflowDefinitionsEditElement: { + prototype: HTMLAppWorkflowDefinitionsEditElement; + new (): HTMLAppWorkflowDefinitionsEditElement; + }; + interface HTMLAppWorkflowDefinitionsListElement extends Components.AppWorkflowDefinitionsList, HTMLStencilElement { + } + var HTMLAppWorkflowDefinitionsListElement: { + prototype: HTMLAppWorkflowDefinitionsListElement; + new (): HTMLAppWorkflowDefinitionsListElement; + }; + interface HTMLAppWorkflowRegistryElement extends Components.AppWorkflowRegistry, HTMLStencilElement { + } + var HTMLAppWorkflowRegistryElement: { + prototype: HTMLAppWorkflowRegistryElement; + new (): HTMLAppWorkflowRegistryElement; + }; interface HTMLElsaActivityEditorModalElement extends Components.ElsaActivityEditorModal, HTMLStencilElement { } var HTMLElsaActivityEditorModalElement: { @@ -140,6 +189,18 @@ declare global { prototype: HTMLElsaCheckboxPropertyElement; new (): HTMLElsaCheckboxPropertyElement; }; + interface HTMLElsaConfirmDialogElement extends Components.ElsaConfirmDialog, HTMLStencilElement { + } + var HTMLElsaConfirmDialogElement: { + prototype: HTMLElsaConfirmDialogElement; + new (): HTMLElsaConfirmDialogElement; + }; + interface HTMLElsaContextMenuElement extends Components.ElsaContextMenu, HTMLStencilElement { + } + var HTMLElsaContextMenuElement: { + prototype: HTMLElsaContextMenuElement; + new (): HTMLElsaContextMenuElement; + }; interface HTMLElsaDesignerTreeElement extends Components.ElsaDesignerTree, HTMLStencilElement { } var HTMLElsaDesignerTreeElement: { @@ -218,11 +279,17 @@ declare global { prototype: HTMLElsaToastNotificationElement; new (): HTMLElsaToastNotificationElement; }; - interface HTMLElsaWorkflowEditorElement extends Components.ElsaWorkflowEditor, HTMLStencilElement { + interface HTMLElsaWorkflowDefinitionEditorScreenElement extends Components.ElsaWorkflowDefinitionEditorScreen, HTMLStencilElement { } - var HTMLElsaWorkflowEditorElement: { - prototype: HTMLElsaWorkflowEditorElement; - new (): HTMLElsaWorkflowEditorElement; + var HTMLElsaWorkflowDefinitionEditorScreenElement: { + prototype: HTMLElsaWorkflowDefinitionEditorScreenElement; + new (): HTMLElsaWorkflowDefinitionEditorScreenElement; + }; + interface HTMLElsaWorkflowDefinitionsListScreenElement extends Components.ElsaWorkflowDefinitionsListScreen, HTMLStencilElement { + } + var HTMLElsaWorkflowDefinitionsListScreenElement: { + prototype: HTMLElsaWorkflowDefinitionsListScreenElement; + new (): HTMLElsaWorkflowDefinitionsListScreenElement; }; interface HTMLElsaWorkflowEditorNotificationsElement extends Components.ElsaWorkflowEditorNotifications, HTMLStencilElement { } @@ -243,10 +310,16 @@ declare global { new (): HTMLElsaWorkflowSettingsModalElement; }; interface HTMLElementTagNameMap { + "app-root": HTMLAppRootElement; + "app-workflow-definitions-edit": HTMLAppWorkflowDefinitionsEditElement; + "app-workflow-definitions-list": HTMLAppWorkflowDefinitionsListElement; + "app-workflow-registry": HTMLAppWorkflowRegistryElement; "elsa-activity-editor-modal": HTMLElsaActivityEditorModalElement; "elsa-activity-picker-modal": HTMLElsaActivityPickerModalElement; "elsa-check-list-property": HTMLElsaCheckListPropertyElement; "elsa-checkbox-property": HTMLElsaCheckboxPropertyElement; + "elsa-confirm-dialog": HTMLElsaConfirmDialogElement; + "elsa-context-menu": HTMLElsaContextMenuElement; "elsa-designer-tree": HTMLElsaDesignerTreeElement; "elsa-designer-tree-activity": HTMLElsaDesignerTreeActivityElement; "elsa-dropdown-property": HTMLElsaDropdownPropertyElement; @@ -260,13 +333,26 @@ declare global { "elsa-script-property": HTMLElsaScriptPropertyElement; "elsa-single-line-property": HTMLElsaSingleLinePropertyElement; "elsa-toast-notification": HTMLElsaToastNotificationElement; - "elsa-workflow-editor": HTMLElsaWorkflowEditorElement; + "elsa-workflow-definition-editor-screen": HTMLElsaWorkflowDefinitionEditorScreenElement; + "elsa-workflow-definitions-list-screen": HTMLElsaWorkflowDefinitionsListScreenElement; "elsa-workflow-editor-notifications": HTMLElsaWorkflowEditorNotificationsElement; "elsa-workflow-publish-button": HTMLElsaWorkflowPublishButtonElement; "elsa-workflow-settings-modal": HTMLElsaWorkflowSettingsModalElement; } } declare namespace LocalJSX { + interface AppRoot { + "serverUrl"?: string; + } + interface AppWorkflowDefinitionsEdit { + "match"?: MatchResults; + "serverUrl"?: string; + } + interface AppWorkflowDefinitionsList { + "serverUrl"?: string; + } + interface AppWorkflowRegistry { + } interface ElsaActivityEditorModal { } interface ElsaActivityPickerModal { @@ -279,6 +365,12 @@ declare namespace LocalJSX { "propertyDescriptor"?: ActivityPropertyDescriptor; "propertyModel"?: ActivityDefinitionProperty; } + interface ElsaConfirmDialog { + } + interface ElsaContextMenu { + "history"?: RouterHistory; + "menuItems"?: Array; + } interface ElsaDesignerTree { "model"?: WorkflowModel; "onWorkflow-changed"?: (event: CustomEvent) => void; @@ -353,11 +445,15 @@ declare namespace LocalJSX { } interface ElsaToastNotification { } - interface ElsaWorkflowEditor { + interface ElsaWorkflowDefinitionEditorScreen { "monacoLibPath"?: string; + "onWorkflowSaved"?: (event: CustomEvent) => void; "serverUrl"?: string; "workflowDefinitionId"?: string; } + interface ElsaWorkflowDefinitionsListScreen { + "serverUrl"?: string; + } interface ElsaWorkflowEditorNotifications { } interface ElsaWorkflowPublishButton { @@ -372,10 +468,16 @@ declare namespace LocalJSX { "workflowDefinition"?: WorkflowDefinition; } interface IntrinsicElements { + "app-root": AppRoot; + "app-workflow-definitions-edit": AppWorkflowDefinitionsEdit; + "app-workflow-definitions-list": AppWorkflowDefinitionsList; + "app-workflow-registry": AppWorkflowRegistry; "elsa-activity-editor-modal": ElsaActivityEditorModal; "elsa-activity-picker-modal": ElsaActivityPickerModal; "elsa-check-list-property": ElsaCheckListProperty; "elsa-checkbox-property": ElsaCheckboxProperty; + "elsa-confirm-dialog": ElsaConfirmDialog; + "elsa-context-menu": ElsaContextMenu; "elsa-designer-tree": ElsaDesignerTree; "elsa-designer-tree-activity": ElsaDesignerTreeActivity; "elsa-dropdown-property": ElsaDropdownProperty; @@ -389,7 +491,8 @@ declare namespace LocalJSX { "elsa-script-property": ElsaScriptProperty; "elsa-single-line-property": ElsaSingleLineProperty; "elsa-toast-notification": ElsaToastNotification; - "elsa-workflow-editor": ElsaWorkflowEditor; + "elsa-workflow-definition-editor-screen": ElsaWorkflowDefinitionEditorScreen; + "elsa-workflow-definitions-list-screen": ElsaWorkflowDefinitionsListScreen; "elsa-workflow-editor-notifications": ElsaWorkflowEditorNotifications; "elsa-workflow-publish-button": ElsaWorkflowPublishButton; "elsa-workflow-settings-modal": ElsaWorkflowSettingsModal; @@ -399,10 +502,16 @@ export { LocalJSX as JSX }; declare module "@stencil/core" { export namespace JSX { interface IntrinsicElements { + "app-root": LocalJSX.AppRoot & JSXBase.HTMLAttributes; + "app-workflow-definitions-edit": LocalJSX.AppWorkflowDefinitionsEdit & JSXBase.HTMLAttributes; + "app-workflow-definitions-list": LocalJSX.AppWorkflowDefinitionsList & JSXBase.HTMLAttributes; + "app-workflow-registry": LocalJSX.AppWorkflowRegistry & JSXBase.HTMLAttributes; "elsa-activity-editor-modal": LocalJSX.ElsaActivityEditorModal & JSXBase.HTMLAttributes; "elsa-activity-picker-modal": LocalJSX.ElsaActivityPickerModal & JSXBase.HTMLAttributes; "elsa-check-list-property": LocalJSX.ElsaCheckListProperty & JSXBase.HTMLAttributes; "elsa-checkbox-property": LocalJSX.ElsaCheckboxProperty & JSXBase.HTMLAttributes; + "elsa-confirm-dialog": LocalJSX.ElsaConfirmDialog & JSXBase.HTMLAttributes; + "elsa-context-menu": LocalJSX.ElsaContextMenu & JSXBase.HTMLAttributes; "elsa-designer-tree": LocalJSX.ElsaDesignerTree & JSXBase.HTMLAttributes; "elsa-designer-tree-activity": LocalJSX.ElsaDesignerTreeActivity & JSXBase.HTMLAttributes; "elsa-dropdown-property": LocalJSX.ElsaDropdownProperty & JSXBase.HTMLAttributes; @@ -416,7 +525,8 @@ declare module "@stencil/core" { "elsa-script-property": LocalJSX.ElsaScriptProperty & JSXBase.HTMLAttributes; "elsa-single-line-property": LocalJSX.ElsaSingleLineProperty & JSXBase.HTMLAttributes; "elsa-toast-notification": LocalJSX.ElsaToastNotification & JSXBase.HTMLAttributes; - "elsa-workflow-editor": LocalJSX.ElsaWorkflowEditor & JSXBase.HTMLAttributes; + "elsa-workflow-definition-editor-screen": LocalJSX.ElsaWorkflowDefinitionEditorScreen & JSXBase.HTMLAttributes; + "elsa-workflow-definitions-list-screen": LocalJSX.ElsaWorkflowDefinitionsListScreen & JSXBase.HTMLAttributes; "elsa-workflow-editor-notifications": LocalJSX.ElsaWorkflowEditorNotifications & JSXBase.HTMLAttributes; "elsa-workflow-publish-button": LocalJSX.ElsaWorkflowPublishButton & JSXBase.HTMLAttributes; "elsa-workflow-settings-modal": LocalJSX.ElsaWorkflowSettingsModal & JSXBase.HTMLAttributes; diff --git a/src/designer/elsa-workflows-studio/src/components/controls/elsa-context-menu/elsa-context-menu.css b/src/designer/elsa-workflows-studio/src/components/controls/elsa-context-menu/elsa-context-menu.css new file mode 100644 index 000000000..e69de29bb diff --git a/src/designer/elsa-workflows-studio/src/components/controls/elsa-context-menu/elsa-context-menu.tsx b/src/designer/elsa-workflows-studio/src/components/controls/elsa-context-menu/elsa-context-menu.tsx new file mode 100644 index 000000000..4d3efea5c --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/controls/elsa-context-menu/elsa-context-menu.tsx @@ -0,0 +1,73 @@ +import {Component, h, Prop} from '@stencil/core'; +import {RouterHistory} from "@stencil/router"; +import {leave, toggle} from 'el-transition' +import {registerClickOutside} from "stencil-click-outside"; +import {MenuItem} from "./models"; + +@Component({ + tag: 'elsa-context-menu', + styleUrl: 'elsa-context-menu.css', + shadow: false, +}) +export class AppContextMenu { + @Prop() history: RouterHistory; + @Prop() menuItems: Array = []; + + contextMenu: HTMLElement; + + closeContextMenu() { + leave(this.contextMenu); + } + + toggleMenu() { + toggle(this.contextMenu); + } + + async onMenuItemClick(e: Event, menuItem: MenuItem) { + e.preventDefault(); + + if (!!menuItem.anchorUrl) + this.history.push(menuItem.anchorUrl); + else if (!!menuItem.clickHandler) { + menuItem.clickHandler(e); + } + + this.closeContextMenu(); + } + + render() { + return ( +
registerClickOutside(this, el, this.closeContextMenu)}> + +
this.contextMenu = el} + data-transition-enter="transition ease-out duration-100" + data-transition-enter-start="transform opacity-0 scale-95" + data-transition-leave="transition ease-in duration-75" + data-transition-leave-start="transform opacity-100 scale-100" + data-transition-leave-end="transform opacity-0 scale-95" + class="hidden z-10 mx-3 origin-top-right absolute right-7 top-0 w-48 mt-1 rounded-md shadow-lg"> + +
+
+ ); + } +} diff --git a/src/designer/elsa-workflows-studio/src/components/controls/elsa-context-menu/models.tsx b/src/designer/elsa-workflows-studio/src/components/controls/elsa-context-menu/models.tsx new file mode 100644 index 000000000..bc1f64ab4 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/controls/elsa-context-menu/models.tsx @@ -0,0 +1,6 @@ +export interface MenuItem { + text: string; + anchorUrl?: string; + clickHandler?: (e: Event) => void; + icon?: any; +} diff --git a/src/designer/elsa-workflows-studio/src/components/editors/controls/elsa-input-tags/elsa-input-tags.css b/src/designer/elsa-workflows-studio/src/components/controls/elsa-input-tags/elsa-input-tags.css similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/editors/controls/elsa-input-tags/elsa-input-tags.css rename to src/designer/elsa-workflows-studio/src/components/controls/elsa-input-tags/elsa-input-tags.css diff --git a/src/designer/elsa-workflows-studio/src/components/editors/controls/elsa-input-tags/elsa-input-tags.tsx b/src/designer/elsa-workflows-studio/src/components/controls/elsa-input-tags/elsa-input-tags.tsx similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/editors/controls/elsa-input-tags/elsa-input-tags.tsx rename to src/designer/elsa-workflows-studio/src/components/controls/elsa-input-tags/elsa-input-tags.tsx diff --git a/src/designer/elsa-workflows-studio/src/components/editors/controls/elsa-input-tags/readme.md b/src/designer/elsa-workflows-studio/src/components/controls/elsa-input-tags/readme.md similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/editors/controls/elsa-input-tags/readme.md rename to src/designer/elsa-workflows-studio/src/components/controls/elsa-input-tags/readme.md diff --git a/src/designer/elsa-workflows-studio/src/components/editors/monaco/elsa-monaco/elsa-monaco-utils.ts b/src/designer/elsa-workflows-studio/src/components/controls/elsa-monaco/elsa-monaco-utils.ts similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/editors/monaco/elsa-monaco/elsa-monaco-utils.ts rename to src/designer/elsa-workflows-studio/src/components/controls/elsa-monaco/elsa-monaco-utils.ts diff --git a/src/designer/elsa-workflows-studio/src/components/editors/monaco/elsa-monaco/elsa-monaco.css b/src/designer/elsa-workflows-studio/src/components/controls/elsa-monaco/elsa-monaco.css similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/editors/monaco/elsa-monaco/elsa-monaco.css rename to src/designer/elsa-workflows-studio/src/components/controls/elsa-monaco/elsa-monaco.css diff --git a/src/designer/elsa-workflows-studio/src/components/editors/monaco/elsa-monaco/elsa-monaco.tsx b/src/designer/elsa-workflows-studio/src/components/controls/elsa-monaco/elsa-monaco.tsx similarity index 99% rename from src/designer/elsa-workflows-studio/src/components/editors/monaco/elsa-monaco/elsa-monaco.tsx rename to src/designer/elsa-workflows-studio/src/components/controls/elsa-monaco/elsa-monaco.tsx index 4c0a33dd4..a4c71c77e 100644 --- a/src/designer/elsa-workflows-studio/src/components/editors/monaco/elsa-monaco/elsa-monaco.tsx +++ b/src/designer/elsa-workflows-studio/src/components/controls/elsa-monaco/elsa-monaco.tsx @@ -1,6 +1,6 @@ import {Component, Host, h, Prop, State, Listen, Method, Watch, Event, EventEmitter} from '@stencil/core'; import {initializeMonacoWorker} from "./elsa-monaco-utils"; -import state from '../../../../utils/store'; +import state from '../../../utils/store'; // Until I figure out why the ESM loader doesn't work properly, we need to include these scripts manually from index.html // import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; diff --git a/src/designer/elsa-workflows-studio/src/components/editors/monaco/elsa-monaco/readme.md b/src/designer/elsa-workflows-studio/src/components/controls/elsa-monaco/readme.md similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/editors/monaco/elsa-monaco/readme.md rename to src/designer/elsa-workflows-studio/src/components/controls/elsa-monaco/readme.md diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-root/app-root.css b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-root/app-root.css new file mode 100644 index 000000000..a8fb2e3dc --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-root/app-root.css @@ -0,0 +1,15 @@ +header { + background: #5851ff; + color: white; + height: 56px; + display: flex; + align-items: center; + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); +} + +h1 { + font-size: 1.4rem; + font-weight: 500; + color: #fff; + padding: 0 12px; +} diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-root/app-root.tsx b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-root/app-root.tsx new file mode 100644 index 000000000..50760f9fd --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-root/app-root.tsx @@ -0,0 +1,62 @@ +import {Component, h, Prop} from '@stencil/core'; +import Tunnel, {DashboardState} from '../../../../data/dashboard'; + +@Component({ + tag: 'app-root', + styleUrl: 'app-root.css', + shadow: false, +}) +export class AppRoot { + + @Prop({attribute: 'server-url', reflect: true}) serverUrl: string; + + render() { + + const serverUrl = this.serverUrl; + + // TODO: Tunneling doesn't appear to be working in combination with the router. + // const tunnelState: DashboardState = { + // serverUrl: serverUrl, + // }; + + return ( +
+ + +
+ {/**/} + + + } exact={true}/> + + + + + + {/**/} +
+
+ ); + } +} diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-definitions-edit/app-workflow-definitions-edit.css b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-definitions-edit/app-workflow-definitions-edit.css new file mode 100644 index 000000000..e69de29bb diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-definitions-edit/app-workflow-definitions-edit.tsx b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-definitions-edit/app-workflow-definitions-edit.tsx new file mode 100644 index 000000000..78db6ffe7 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-definitions-edit/app-workflow-definitions-edit.tsx @@ -0,0 +1,31 @@ +import {Component, Prop, h} from '@stencil/core'; +import {MatchResults} from '@stencil/router'; + +@Component({ + tag: 'app-workflow-definitions-edit', + styleUrl: 'app-workflow-definitions-edit.css', + shadow: false, +}) +export class AppWorkflowDefinitionsEdit { + @Prop() match: MatchResults; + @Prop() serverUrl: string; + + id?: string; + + componentWillLoad() { + let id = this.match.params.id; + + if (id == 'new') + id = null; + + this.id = id; + } + + render() { + const id = this.id; + + return
+ +
; + } +} diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-definitions-list/app-workflow-definitions-list.css b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-definitions-list/app-workflow-definitions-list.css new file mode 100644 index 000000000..e69de29bb diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-definitions-list/app-workflow-definitions-list.tsx b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-definitions-list/app-workflow-definitions-list.tsx new file mode 100644 index 000000000..f8e3f8a86 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-definitions-list/app-workflow-definitions-list.tsx @@ -0,0 +1,33 @@ +import {Component, h, Prop, State} from '@stencil/core'; + +@Component({ + tag: 'app-workflow-definitions-list', + styleUrl: 'app-workflow-definitions-list.css', + shadow: false, +}) +export class AppWorkflowDefinitionsList { + + @Prop() serverUrl: string; + + render() { + return ( +
+
+
+

+ Workflow Definitions +

+
+
+ + Create Workflow + +
+
+ + +
+ ); + } +} diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-registry/app-workflow-registry.css b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-registry/app-workflow-registry.css new file mode 100644 index 000000000..e69de29bb diff --git a/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-registry/app-workflow-registry.tsx b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-registry/app-workflow-registry.tsx new file mode 100644 index 000000000..53a19b4c2 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/components/dashboard/pages/app-workflow-registry/app-workflow-registry.tsx @@ -0,0 +1,69 @@ +import {Component, h} from '@stencil/core'; + +@Component({ + tag: 'app-workflow-registry', + styleUrl: 'app-workflow-registry.css', + shadow: false, +}) +export class AppHome { + render() { + return ( +
+
+
+

+ Workflow Registry +

+
+
+ + Create Workflow + +
+
+ +
+ + + + + + + + + + + + + + + + + + + +
Name + Instances + +
+ + +
+
+
4 + 999 + 75
+
+
+
+ +
+
+
+ ); + } +} diff --git a/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree-activity/elsa-designer-tree-activity.tsx b/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree-activity/elsa-designer-tree-activity.tsx index 5e3230182..146cf6f01 100644 --- a/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree-activity/elsa-designer-tree-activity.tsx +++ b/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree-activity/elsa-designer-tree-activity.tsx @@ -1,9 +1,7 @@ import {Component, Event, EventEmitter, h, Host, Prop, State} from '@stencil/core'; import {leave, toggle} from 'el-transition' import {registerClickOutside} from "stencil-click-outside"; -import {ActivityIcon} from '../../../icons/activity-icon'; import {ActivityModel, ActivityDesignDisplayContext, EventTypes} from "../../../../models"; -import {eventBus} from '../../../../services/event-bus'; @Component({ tag: 'elsa-designer-tree-activity', @@ -49,8 +47,8 @@ export class ElsaDesignerTreeActivity { const displayName = activity.displayName && activity.displayName.length > 0 ? activity.displayName : activity.name && activity.name.length > 0 ? activity.name : activity.type return ( - this.onEditActivityClick(e)} + this.onEditActivityClick(e)} class="activity border-2 border-solid border-white rounded bg-white text-left text-black text-lg hover:border-blue-600 select-none max-w-md shadow-sm relative">
diff --git a/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.css b/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.css index 243130f44..833b3ed6c 100644 --- a/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.css +++ b/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.css @@ -3,7 +3,7 @@ } .workflow-canvas { - background-image: url(build/assets/tile.png); + background-image: url(/build/assets/tile.png); background-repeat: repeat; background-size: 30px 30px; background-color: #FBFBFB; diff --git a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-expression-editor/elsa-expression-editor.css b/src/designer/elsa-workflows-studio/src/components/editors/elsa-expression-editor/elsa-expression-editor.css similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-expression-editor/elsa-expression-editor.css rename to src/designer/elsa-workflows-studio/src/components/editors/elsa-expression-editor/elsa-expression-editor.css diff --git a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-expression-editor/elsa-expression-editor.tsx b/src/designer/elsa-workflows-studio/src/components/editors/elsa-expression-editor/elsa-expression-editor.tsx similarity index 94% rename from src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-expression-editor/elsa-expression-editor.tsx rename to src/designer/elsa-workflows-studio/src/components/editors/elsa-expression-editor/elsa-expression-editor.tsx index d01a50e1a..3d719426d 100644 --- a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-expression-editor/elsa-expression-editor.tsx +++ b/src/designer/elsa-workflows-studio/src/components/editors/elsa-expression-editor/elsa-expression-editor.tsx @@ -1,7 +1,7 @@ import {Component, EventEmitter, h, Host, Method, Prop, State, Watch, Event} from '@stencil/core'; -import {createElsaClient} from "../../../../services/elsa-client"; +import {createElsaClient} from "../../../services/elsa-client"; import Tunnel from '../../../data/workflow-editor'; -import {MonacoValueChangedArgs} from "../../monaco/elsa-monaco/elsa-monaco"; +import {MonacoValueChangedArgs} from "../../controls/elsa-monaco/elsa-monaco"; @Component({ tag: 'elsa-expression-editor', diff --git a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-property-editor/elsa-property-editor.css b/src/designer/elsa-workflows-studio/src/components/editors/elsa-property-editor/elsa-property-editor.css similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-property-editor/elsa-property-editor.css rename to src/designer/elsa-workflows-studio/src/components/editors/elsa-property-editor/elsa-property-editor.css diff --git a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-property-editor/elsa-property-editor.tsx b/src/designer/elsa-workflows-studio/src/components/editors/elsa-property-editor/elsa-property-editor.tsx similarity index 99% rename from src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-property-editor/elsa-property-editor.tsx rename to src/designer/elsa-workflows-studio/src/components/editors/elsa-property-editor/elsa-property-editor.tsx index eb544d773..f0d092ff8 100644 --- a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-property-editor/elsa-property-editor.tsx +++ b/src/designer/elsa-workflows-studio/src/components/editors/elsa-property-editor/elsa-property-editor.tsx @@ -1,5 +1,5 @@ import {Component, h, Prop, State, Event, EventEmitter} from '@stencil/core'; -import {ActivityDefinitionProperty, ActivityPropertyDescriptor, SyntaxNames} from "../../../../models"; +import {ActivityDefinitionProperty, ActivityPropertyDescriptor, SyntaxNames} from "../../../models"; import {registerClickOutside} from "stencil-click-outside"; import {enter, leave, toggle} from 'el-transition' diff --git a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-script-property/elsa-script-property.tsx b/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-script-property/elsa-script-property.tsx index 83fed57be..75e7a6e4f 100644 --- a/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-script-property/elsa-script-property.tsx +++ b/src/designer/elsa-workflows-studio/src/components/editors/properties/elsa-script-property/elsa-script-property.tsx @@ -1,8 +1,8 @@ import {Component, h, Prop, State} from '@stencil/core'; import {ActivityDefinitionProperty, ActivityPropertyDescriptor} from "../../../../models"; import {createElsaClient} from "../../../../services/elsa-client"; -import Tunnel from '../../../data/workflow-editor'; -import {MonacoValueChangedArgs} from "../../monaco/elsa-monaco/elsa-monaco"; +import Tunnel from '../../../../data/workflow-editor'; +import {MonacoValueChangedArgs} from "../../../controls/elsa-monaco/elsa-monaco"; @Component({ tag: 'elsa-script-property', diff --git a/src/designer/elsa-workflows-studio/src/components/editors/workflow-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.css b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.css similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/editors/workflow-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.css rename to src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.css diff --git a/src/designer/elsa-workflows-studio/src/components/editors/workflow-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.tsx similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/editors/workflow-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.tsx rename to src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/elsa-activity-editor-modal.tsx diff --git a/src/designer/elsa-workflows-studio/src/components/editors/workflow-editor/elsa-activity-editor-modal/readme.md b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/readme.md similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/editors/workflow-editor/elsa-activity-editor-modal/readme.md rename to src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-activity-editor-modal/readme.md diff --git a/src/designer/elsa-workflows-studio/src/components/editors/workflow-editor/elsa-workflow-editor-notifications/elsa-workflow-editor-notifications.css b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.css similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/editors/workflow-editor/elsa-workflow-editor-notifications/elsa-workflow-editor-notifications.css rename to src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.css diff --git a/src/designer/elsa-workflows-studio/src/components/editors/workflow-editor/elsa-workflow-editor/elsa-workflow-editor.tsx b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx similarity index 97% rename from src/designer/elsa-workflows-studio/src/components/editors/workflow-editor/elsa-workflow-editor/elsa-workflow-editor.tsx rename to src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx index 2d6556261..8e1ff06da 100644 --- a/src/designer/elsa-workflows-studio/src/components/editors/workflow-editor/elsa-workflow-editor/elsa-workflow-editor.tsx +++ b/src/designer/elsa-workflows-studio/src/components/screens/workflow-definition-editor/elsa-workflow-definition-editor-screen/elsa-workflow-definition-editor-screen.tsx @@ -4,20 +4,21 @@ import {ActivityDefinition, ActivityDescriptor, ActivityModel, ConnectionDefinit import {createElsaClient, SaveWorkflowDefinitionRequest} from "../../../../services/elsa-client"; import {pluginManager} from '../../../../services/plugin-manager'; import state from '../../../../utils/store'; -import Tunnel, {WorkflowEditorState} from '../../../data/workflow-editor'; +import Tunnel, {WorkflowEditorState} from '../../../../data/workflow-editor'; import {downloadFromBlob} from "../../../../utils/download"; @Component({ - tag: 'elsa-workflow-editor', - styleUrl: 'elsa-workflow-editor.css', + tag: 'elsa-workflow-definition-editor-screen', + styleUrl: 'elsa-workflow-definition-editor-screen.css', shadow: false, }) -export class ElsaWorkflowDefinitionEditor { +export class ElsaWorkflowDefinitionEditorScreen { constructor() { pluginManager.initialize(); } + @Event() workflowSaved: EventEmitter; @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; @@ -213,6 +214,7 @@ export class ElsaWorkflowDefinitionEditor { this.saved = !publish; this.publishing = false; setTimeout(() => this.saved = false, 500); + this.workflowSaved.emit(workflowDefinition); } catch (e) { console.error(e); this.saving = false; @@ -343,7 +345,7 @@ export class ElsaWorkflowDefinitionEditor { renderWorkflowSettingsButton() { return ( +
+
+
+ +
+
+ +
+

+ {this.message} +

+
+
+
+
+
+
+ + +
+
+ +
+ ); + } +} diff --git a/src/designer/elsa-workflows-studio/src/data/dashboard.tsx b/src/designer/elsa-workflows-studio/src/data/dashboard.tsx new file mode 100644 index 000000000..9f8cc9049 --- /dev/null +++ b/src/designer/elsa-workflows-studio/src/data/dashboard.tsx @@ -0,0 +1,13 @@ +import {createProviderConsumer} from "@stencil/state-tunnel"; +import {h} from "@stencil/core"; + +export interface DashboardState { + serverUrl: string; +} + +export default createProviderConsumer( + { + serverUrl: null + }, + (subscribe, child) => () +); diff --git a/src/designer/elsa-workflows-studio/src/components/data/workflow-editor.tsx b/src/designer/elsa-workflows-studio/src/data/workflow-editor.tsx similarity index 100% rename from src/designer/elsa-workflows-studio/src/components/data/workflow-editor.tsx rename to src/designer/elsa-workflows-studio/src/data/workflow-editor.tsx diff --git a/src/designer/elsa-workflows-studio/src/index.html b/src/designer/elsa-workflows-studio/src/index.html index c6c56897b..2a833516f 100644 --- a/src/designer/elsa-workflows-studio/src/index.html +++ b/src/designer/elsa-workflows-studio/src/index.html @@ -7,14 +7,16 @@ - + - + + + diff --git a/src/designer/elsa-workflows-studio/src/index.ts b/src/designer/elsa-workflows-studio/src/index.ts index 7531c10b8..9d8623245 100644 --- a/src/designer/elsa-workflows-studio/src/index.ts +++ b/src/designer/elsa-workflows-studio/src/index.ts @@ -1 +1,2 @@ export { Components, JSX } from './components'; +import '@stencil/router'; diff --git a/src/designer/elsa-workflows-studio/src/models/domain.ts b/src/designer/elsa-workflows-studio/src/models/domain.ts index 0f2ff3500..14ecdea8f 100644 --- a/src/designer/elsa-workflows-studio/src/models/domain.ts +++ b/src/designer/elsa-workflows-studio/src/models/domain.ts @@ -20,6 +20,20 @@ export interface WorkflowDefinition { connections: Array; } +export interface WorkflowDefinitionSummary { + id?: string; + definitionId?: string; + tenantId?: string; + name?: string; + displayName?: string; + description?: string; + version: number; + isSingleton?: boolean; + persistenceBehavior?: WorkflowPersistenceBehavior; + isPublished?: boolean; + isLatest?: boolean; +} + export interface ActivityDefinition { activityId: string; type: string; @@ -75,17 +89,21 @@ export interface VersionOptions { version?: number; } -export const getVersionOptionsString = (versionOptions: VersionOptions) => { +export const getVersionOptionsString = (versionOptions?: VersionOptions) => { + + if(!versionOptions) + return ''; + return versionOptions.allVersions - ? "AllVersions" + ? 'AllVersions' : versionOptions.isDraft - ? "Draft" + ? 'Draft' : versionOptions.isLatest - ? "Latest" + ? 'Latest' : versionOptions.isPublished - ? "Published" + ? 'Published' : versionOptions.isLatestOrPublished - ? "LatestOrPublished" + ? 'LatestOrPublished' : versionOptions.version.toString(); }; @@ -112,6 +130,13 @@ export interface ActivityPropertyDescriptor { supportedSyntaxes: Array } +export interface PagedList { + items: Array; + page: number; + pageSize: number; + totalCount: number; +} + export enum ActivityTraits { Action = 1, Trigger = 2, diff --git a/src/designer/elsa-workflows-studio/src/services/elsa-client.ts b/src/designer/elsa-workflows-studio/src/services/elsa-client.ts index 336f14f8c..adcd28ebc 100644 --- a/src/designer/elsa-workflows-studio/src/services/elsa-client.ts +++ b/src/designer/elsa-workflows-studio/src/services/elsa-client.ts @@ -1,5 +1,17 @@ import axios, {AxiosRequestConfig} from "axios"; -import {ActivityDefinition, ActivityDescriptor, ConnectionDefinition, getVersionOptionsString, Variables, VersionOptions, WorkflowContextOptions, WorkflowDefinition, WorkflowPersistenceBehavior} from "../models"; +import { + ActivityDefinition, + ActivityDescriptor, + ConnectionDefinition, + getVersionOptionsString, + PagedList, + Variables, + VersionOptions, + WorkflowContextOptions, + WorkflowDefinition, + WorkflowDefinitionSummary, + WorkflowPersistenceBehavior +} from "../models"; export const createElsaClient = function (serverUrl: string): ElsaClient { const config: AxiosRequestConfig = { @@ -16,6 +28,11 @@ export const createElsaClient = function (serverUrl: string): ElsaClient { } }, workflowDefinitionsApi: { + list: async (page?: number, pageSize?: number, versionOptions?: VersionOptions) => { + const versionOptionsString = getVersionOptionsString(versionOptions); + const response = await httpClient.get>(`v1/workflow-definitions?version=${versionOptionsString}`); + return response.data; + }, getByDefinitionAndVersion: async (definitionId: string, versionOptions: VersionOptions) => { const versionOptionsString = getVersionOptionsString(versionOptions); const response = await httpClient.get(`v1/workflow-definitions/${definitionId}/${versionOptionsString}`); @@ -25,6 +42,9 @@ export const createElsaClient = function (serverUrl: string): ElsaClient { const response = await httpClient.post('v1/workflow-definitions', request); return response.data; }, + delete: async definitionId => { + await httpClient.delete(`v1/workflow-definitions/${definitionId}`); + }, retract: async workflowDefinitionId => { const response = await httpClient.post(`v1/workflow-definitions/${workflowDefinitionId}/retract`); return response.data; @@ -78,8 +98,12 @@ export interface ActivitiesApi { export interface WorkflowDefinitionsApi { getByDefinitionAndVersion(definitionId: string, versionOptions: VersionOptions): Promise + list(page?: number, pageSize?: number, versionOptions?: VersionOptions): Promise> + save(request: SaveWorkflowDefinitionRequest): Promise + delete(definitionId: string): Promise + retract(workflowDefinitionId: string): Promise export(workflowDefinitionId: string, versionOptions: VersionOptions): Promise diff --git a/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/List.cs b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/List.cs index 2d9d8e16f..f4d0313df 100644 --- a/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/List.cs +++ b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/List.cs @@ -1,6 +1,8 @@ +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using AutoMapper; using Elsa.Models; using Elsa.Persistence; using Elsa.Persistence.Specifications; @@ -23,30 +25,33 @@ namespace Elsa.Server.Api.Endpoints.WorkflowDefinitions { private readonly IWorkflowDefinitionStore _workflowDefinitionStore; private readonly IContentSerializer _serializer; + private readonly IMapper _mapper; - public List(IWorkflowDefinitionStore workflowDefinitionStore, IContentSerializer serializer) + public List(IWorkflowDefinitionStore workflowDefinitionStore, IContentSerializer serializer, IMapper mapper) { _workflowDefinitionStore = workflowDefinitionStore; _serializer = serializer; + _mapper = mapper; } [HttpGet] - [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(PagedList))] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(PagedList))] [SwaggerResponseExample(StatusCodes.Status200OK, typeof(WorkflowDefinitionPagedListExample))] [SwaggerOperation( Summary = "Returns a list of workflow definitions.", - Description = "Returns paginated a list of workflow definitions. When no version options are specified, the latest versions are returned.", + Description = "Returns paginated a list of workflow definition summaries. When no version options are specified, the latest versions are returned.", OperationId = "WorkflowDefinitions.List", Tags = new[] { "WorkflowDefinitions" }) ] - public async Task>> Handle(int? page = default, int? pageSize = default, VersionOptions? version = default, CancellationToken cancellationToken = default) + public async Task>> Handle(int? page = default, int? pageSize = default, VersionOptions? version = default, CancellationToken cancellationToken = default) { version ??= VersionOptions.Latest; var specification = new VersionOptionsSpecification(version.Value); - var totalCount = await _workflowDefinitionStore.CountAsync(specification, cancellationToken: cancellationToken); + var totalCount = await _workflowDefinitionStore.CountAsync(specification, cancellationToken); var paging = page == null || pageSize == null ? default : Paging.Page(page.Value, pageSize.Value); var items = await _workflowDefinitionStore.FindManyAsync(specification, paging: paging, cancellationToken: cancellationToken); - var pagedList = new PagedList(items.ToList(), page, pageSize, totalCount); + var summaries = _mapper.Map>(items); + var pagedList = new PagedList(summaries, page, pageSize, totalCount); return Json(pagedList, _serializer.GetSettings()); } diff --git a/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Models.cs b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Models.cs new file mode 100644 index 000000000..45134cbf7 --- /dev/null +++ b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Models.cs @@ -0,0 +1,16 @@ +using Elsa.Models; + +namespace Elsa.Server.Api.Endpoints.WorkflowDefinitions +{ + public record WorkflowDefinitionSummaryModel( + string Id, + string DefinitionId, + string? Name, + string? DisplayName, + string? Description, + int Version, + bool IsSingleton, + WorkflowPersistenceBehavior PersistenceBehavior, + bool IsPublished, + bool IsLatest); +} \ No newline at end of file diff --git a/src/server/Elsa.Server.Api/Mapping/AutoMapperProfile.cs b/src/server/Elsa.Server.Api/Mapping/AutoMapperProfile.cs index d70d9277f..d6a0a5d0a 100644 --- a/src/server/Elsa.Server.Api/Mapping/AutoMapperProfile.cs +++ b/src/server/Elsa.Server.Api/Mapping/AutoMapperProfile.cs @@ -1,5 +1,6 @@ using AutoMapper; using Elsa.Models; +using Elsa.Server.Api.Endpoints.WorkflowDefinitions; using Elsa.Server.Api.Endpoints.WorkflowInstances; using Elsa.Server.Api.Endpoints.WorkflowRegistry; using Elsa.Services.Models; @@ -16,6 +17,7 @@ namespace Elsa.Server.Api.Mapping CreateMap(); CreateMap().ConvertUsing(); CreateMap(); + CreateMap(); } } } \ No newline at end of file diff --git a/src/server/Elsa.Server.Api/Swagger/Examples/WebhookDefinitionExample.cs b/src/server/Elsa.Server.Api/Swagger/Examples/WebhookDefinitionExample.cs index 5485be203..efa3c641c 100644 --- a/src/server/Elsa.Server.Api/Swagger/Examples/WebhookDefinitionExample.cs +++ b/src/server/Elsa.Server.Api/Swagger/Examples/WebhookDefinitionExample.cs @@ -1,5 +1,6 @@ using System; using Elsa.Activities.Webhooks.Models; +using Elsa.Server.Api.Endpoints.WorkflowDefinitions; using Swashbuckle.AspNetCore.Filters; namespace Elsa.Server.Api.Swagger.Examples diff --git a/src/server/Elsa.Server.Api/Swagger/Examples/WorkflowDefinitionSummaryModelExample.cs b/src/server/Elsa.Server.Api/Swagger/Examples/WorkflowDefinitionSummaryModelExample.cs new file mode 100644 index 000000000..95cc040be --- /dev/null +++ b/src/server/Elsa.Server.Api/Swagger/Examples/WorkflowDefinitionSummaryModelExample.cs @@ -0,0 +1,24 @@ +using System; +using Elsa.Models; +using Elsa.Server.Api.Endpoints.WorkflowDefinitions; +using Swashbuckle.AspNetCore.Filters; + +namespace Elsa.Server.Api.Swagger.Examples +{ + public class WorkflowDefinitionSummaryModelExample : IExamplesProvider + { + public WorkflowDefinitionSummaryModel GetExamples() => + new( + Guid.NewGuid().ToString("N"), + Guid.NewGuid().ToString("N"), + "ProcessOrderWorkflow", + "Process Order Workflow", + "Process new orders", + 1, + false, + WorkflowPersistenceBehavior.Suspended, + true, + false + ); + } +} \ No newline at end of file diff --git a/src/server/Elsa.Server.Api/Swagger/Examples/WorkflowDefinitionSummaryModelPagedListExample.cs b/src/server/Elsa.Server.Api/Swagger/Examples/WorkflowDefinitionSummaryModelPagedListExample.cs new file mode 100644 index 000000000..982f6a037 --- /dev/null +++ b/src/server/Elsa.Server.Api/Swagger/Examples/WorkflowDefinitionSummaryModelPagedListExample.cs @@ -0,0 +1,16 @@ +using System.Linq; +using Elsa.Server.Api.Endpoints.WorkflowDefinitions; +using Elsa.Server.Api.Models; +using Swashbuckle.AspNetCore.Filters; + +namespace Elsa.Server.Api.Swagger.Examples +{ + public class WorkflowDefinitionSummaryModelPagedListExample : IExamplesProvider> + { + public PagedList GetExamples() + { + var examples = Enumerable.Range(1, 3).Select(_ => new WorkflowDefinitionSummaryModelExample().GetExamples()).ToList(); + return new PagedList(examples, 0, 10, examples.Count); + } + } +} \ No newline at end of file