Incremental work on dashboard
This commit is contained in:
parent
aabf9ff2c2
commit
727191c0e8
|
|
@ -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<ScopeEvicted>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ namespace Elsa.Persistence.Specifications.WorkflowDefinitions
|
|||
public VersionOptionsSpecification(VersionOptions versionOptions) => VersionOptions = versionOptions;
|
||||
public override Expression<Func<WorkflowDefinition, bool>> ToExpression()
|
||||
{
|
||||
if (VersionOptions.AllVersions)
|
||||
return x => true;
|
||||
if (VersionOptions.IsDraft)
|
||||
return x => !x.IsPublished;
|
||||
if (VersionOptions.IsLatest)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
17
src/designer/elsa-workflows-studio/package-lock.json
generated
17
src/designer/elsa-workflows-studio/package-lock.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/designer/elsa-workflows-studio/src/assets/images/favicon.ico
Normal file
BIN
src/designer/elsa-workflows-studio/src/assets/images/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/designer/elsa-workflows-studio/src/assets/images/logo.png
Normal file
BIN
src/designer/elsa-workflows-studio/src/assets/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
|
|
@ -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<void>;
|
||||
"show": (caption: string, message: string) => Promise<boolean>;
|
||||
}
|
||||
interface ElsaContextMenu {
|
||||
"history": RouterHistory;
|
||||
"menuItems": Array<MenuItem>;
|
||||
}
|
||||
interface ElsaDesignerTree {
|
||||
"destroyJsPlumb": () => Promise<void>;
|
||||
"model": WorkflowModel;
|
||||
|
|
@ -96,7 +118,7 @@ export namespace Components {
|
|||
"hide": () => Promise<void>;
|
||||
"show": (options: ToastNotificationOptions) => Promise<void>;
|
||||
}
|
||||
interface ElsaWorkflowEditor {
|
||||
interface ElsaWorkflowDefinitionEditorScreen {
|
||||
"exportWorkflow": () => Promise<void>;
|
||||
"getServerUrl": () => Promise<string>;
|
||||
"getWorkflowDefinitionId": () => Promise<string>;
|
||||
|
|
@ -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<MenuItem>;
|
||||
}
|
||||
interface ElsaDesignerTree {
|
||||
"model"?: WorkflowModel;
|
||||
"onWorkflow-changed"?: (event: CustomEvent<WorkflowModel>) => void;
|
||||
|
|
@ -353,11 +445,15 @@ declare namespace LocalJSX {
|
|||
}
|
||||
interface ElsaToastNotification {
|
||||
}
|
||||
interface ElsaWorkflowEditor {
|
||||
interface ElsaWorkflowDefinitionEditorScreen {
|
||||
"monacoLibPath"?: string;
|
||||
"onWorkflowSaved"?: (event: CustomEvent<WorkflowDefinition>) => 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<HTMLAppRootElement>;
|
||||
"app-workflow-definitions-edit": LocalJSX.AppWorkflowDefinitionsEdit & JSXBase.HTMLAttributes<HTMLAppWorkflowDefinitionsEditElement>;
|
||||
"app-workflow-definitions-list": LocalJSX.AppWorkflowDefinitionsList & JSXBase.HTMLAttributes<HTMLAppWorkflowDefinitionsListElement>;
|
||||
"app-workflow-registry": LocalJSX.AppWorkflowRegistry & JSXBase.HTMLAttributes<HTMLAppWorkflowRegistryElement>;
|
||||
"elsa-activity-editor-modal": LocalJSX.ElsaActivityEditorModal & JSXBase.HTMLAttributes<HTMLElsaActivityEditorModalElement>;
|
||||
"elsa-activity-picker-modal": LocalJSX.ElsaActivityPickerModal & JSXBase.HTMLAttributes<HTMLElsaActivityPickerModalElement>;
|
||||
"elsa-check-list-property": LocalJSX.ElsaCheckListProperty & JSXBase.HTMLAttributes<HTMLElsaCheckListPropertyElement>;
|
||||
"elsa-checkbox-property": LocalJSX.ElsaCheckboxProperty & JSXBase.HTMLAttributes<HTMLElsaCheckboxPropertyElement>;
|
||||
"elsa-confirm-dialog": LocalJSX.ElsaConfirmDialog & JSXBase.HTMLAttributes<HTMLElsaConfirmDialogElement>;
|
||||
"elsa-context-menu": LocalJSX.ElsaContextMenu & JSXBase.HTMLAttributes<HTMLElsaContextMenuElement>;
|
||||
"elsa-designer-tree": LocalJSX.ElsaDesignerTree & JSXBase.HTMLAttributes<HTMLElsaDesignerTreeElement>;
|
||||
"elsa-designer-tree-activity": LocalJSX.ElsaDesignerTreeActivity & JSXBase.HTMLAttributes<HTMLElsaDesignerTreeActivityElement>;
|
||||
"elsa-dropdown-property": LocalJSX.ElsaDropdownProperty & JSXBase.HTMLAttributes<HTMLElsaDropdownPropertyElement>;
|
||||
|
|
@ -416,7 +525,8 @@ declare module "@stencil/core" {
|
|||
"elsa-script-property": LocalJSX.ElsaScriptProperty & JSXBase.HTMLAttributes<HTMLElsaScriptPropertyElement>;
|
||||
"elsa-single-line-property": LocalJSX.ElsaSingleLineProperty & JSXBase.HTMLAttributes<HTMLElsaSingleLinePropertyElement>;
|
||||
"elsa-toast-notification": LocalJSX.ElsaToastNotification & JSXBase.HTMLAttributes<HTMLElsaToastNotificationElement>;
|
||||
"elsa-workflow-editor": LocalJSX.ElsaWorkflowEditor & JSXBase.HTMLAttributes<HTMLElsaWorkflowEditorElement>;
|
||||
"elsa-workflow-definition-editor-screen": LocalJSX.ElsaWorkflowDefinitionEditorScreen & JSXBase.HTMLAttributes<HTMLElsaWorkflowDefinitionEditorScreenElement>;
|
||||
"elsa-workflow-definitions-list-screen": LocalJSX.ElsaWorkflowDefinitionsListScreen & JSXBase.HTMLAttributes<HTMLElsaWorkflowDefinitionsListScreenElement>;
|
||||
"elsa-workflow-editor-notifications": LocalJSX.ElsaWorkflowEditorNotifications & JSXBase.HTMLAttributes<HTMLElsaWorkflowEditorNotificationsElement>;
|
||||
"elsa-workflow-publish-button": LocalJSX.ElsaWorkflowPublishButton & JSXBase.HTMLAttributes<HTMLElsaWorkflowPublishButtonElement>;
|
||||
"elsa-workflow-settings-modal": LocalJSX.ElsaWorkflowSettingsModal & JSXBase.HTMLAttributes<HTMLElsaWorkflowSettingsModalElement>;
|
||||
|
|
|
|||
|
|
@ -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<MenuItem> = [];
|
||||
|
||||
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 (
|
||||
<div class="relative flex justify-end items-center" ref={el => registerClickOutside(this, el, this.closeContextMenu)}>
|
||||
<button onClick={() => this.toggleMenu()} aria-has-popup="true" type="button"
|
||||
class="w-8 h-8 inline-flex items-center justify-center text-gray-400 rounded-full bg-transparent hover:text-gray-500 focus:outline-none focus:text-gray-500 focus:bg-gray-100 transition ease-in-out duration-150">
|
||||
<svg class="w-5 h-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div ref={el => 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">
|
||||
<div class="rounded-md bg-white shadow-xs" role="menu" aria-orientation="vertical" aria-labelledby="project-options-menu-0">
|
||||
{this.menuItems.map(menuItem => {
|
||||
const anchorUrl = menuItem.anchorUrl || '#';
|
||||
return (
|
||||
<div class="py-1">
|
||||
<a href={anchorUrl}
|
||||
onClick={e => this.onMenuItemClick(e, menuItem)}
|
||||
class="group flex items-center px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900" role="menuitem">
|
||||
{menuItem.icon ? <span class="mr-3 ">{menuItem.icon}</span> : undefined}
|
||||
{menuItem.text}
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
export interface MenuItem {
|
||||
text: string;
|
||||
anchorUrl?: string;
|
||||
clickHandler?: (e: Event) => void;
|
||||
icon?: any;
|
||||
}
|
||||
|
|
@ -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';
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 (
|
||||
<div class="h-screen bg-gray-100">
|
||||
<nav class="bg-gray-800">
|
||||
<div class="px-4 sm:px-6 lg:px-8">
|
||||
<div class="flex items-center justify-between h-16">
|
||||
<div class="flex items-center">
|
||||
<div class="flex-shrink-0">
|
||||
<img class="h-8 w-8" src="/build/assets/images/logo.png" alt="Workflow"/>
|
||||
</div>
|
||||
<div class="hidden md:block">
|
||||
<div class="ml-10 flex items-baseline space-x-4">
|
||||
<stencil-route-link url="/workflow-definitions" anchorClass="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium" activeClass="text-white bg-gray-900">Workflow Definitions
|
||||
</stencil-route-link>
|
||||
<stencil-route-link url="/workflow-instances" anchorClass="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium" activeClass="text-white bg-gray-900">Workflow Instances
|
||||
</stencil-route-link>
|
||||
<stencil-route-link url="/workflow-registry" anchorClass="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium" activeClass="text-white bg-gray-900">Workflow Registry
|
||||
</stencil-route-link>
|
||||
<stencil-route-link url="/custom-activities" class="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium">Custom Activities</stencil-route-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main>
|
||||
{/*<Tunnel.Provider state={tunnelState}>*/}
|
||||
<stencil-router>
|
||||
<stencil-route-switch scrollTopOffset={0}>
|
||||
<stencil-route url="/" routeRender={props => <stencil-route-redirect url="/workflow-registry"/>} exact={true}/>
|
||||
<stencil-route url="/workflow-registry" component="app-workflow-registry"/>
|
||||
<stencil-route url="/workflow-definitions" component="app-workflow-definitions-list" componentProps={{'serverUrl': serverUrl}} exact={true}/>
|
||||
<stencil-route url="/workflow-definitions/:id" component="app-workflow-definitions-edit" componentProps={{'serverUrl': serverUrl}} />
|
||||
</stencil-route-switch>
|
||||
</stencil-router>
|
||||
{/*</Tunnel.Provider>*/}
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 <div>
|
||||
<elsa-workflow-definition-editor-screen server-url={this.serverUrl} workflow-definition-id={id} monaco-lib-path="build/assets/js"/>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
|
|
@ -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 (
|
||||
<div>
|
||||
<div class="border-b border-gray-200 px-4 py-4 sm:flex sm:items-center sm:justify-between sm:px-6 lg:px-8 bg-white">
|
||||
<div class="flex-1 min-w-0">
|
||||
<h1 class="text-lg font-medium leading-6 text-gray-900 sm:truncate">
|
||||
Workflow Definitions
|
||||
</h1>
|
||||
</div>
|
||||
<div class="mt-4 flex sm:mt-0 sm:ml-4">
|
||||
<stencil-route-link url="/workflow-definitions/new"
|
||||
class="order-0 inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:order-1 sm:ml-3">
|
||||
Create Workflow
|
||||
</stencil-route-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<elsa-workflow-definitions-list-screen serverUrl={this.serverUrl} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 (
|
||||
<div>
|
||||
<div class="border-b border-gray-200 px-4 py-4 sm:flex sm:items-center sm:justify-between sm:px-6 lg:px-8 bg-white">
|
||||
<div class="flex-1 min-w-0">
|
||||
<h1 class="text-lg font-medium leading-6 text-gray-900 sm:truncate">
|
||||
Workflow Registry
|
||||
</h1>
|
||||
</div>
|
||||
<div class="mt-4 flex sm:mt-0 sm:ml-4">
|
||||
<stencil-route-link url="/workflow-definitions/new" class="order-0 inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:order-1 sm:ml-3">
|
||||
Create Workflow
|
||||
</stencil-route-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="align-middle inline-block min-w-full border-b border-gray-200">
|
||||
<table class="min-w-full">
|
||||
<thead>
|
||||
<tr class="border-t border-gray-200">
|
||||
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider"><span class="lg:pl-2">Name</span></th>
|
||||
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
||||
Instances
|
||||
</th>
|
||||
<th class="hidden md:table-cell px-6 py-3 border-b border-gray-200 bg-gray-50 text-right text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
||||
Latest Version
|
||||
</th>
|
||||
<th class="hidden md:table-cell px-6 py-3 border-b border-gray-200 bg-gray-50 text-right text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
||||
Published Version
|
||||
</th>
|
||||
<th class="pr-6 py-3 border-b border-gray-200 bg-gray-50 text-right text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider"/>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-gray-100">
|
||||
<tr>
|
||||
<td class="px-6 py-3 whitespace-no-wrap text-sm leading-5 font-medium text-gray-900">
|
||||
<div class="flex items-center space-x-3 lg:pl-2"><a href="/workflow-registry/7eed1333c2674370a1e9b300aa94fda2/viewer" class="truncate hover:text-gray-600"><span>Customer Call Flow</span></a></div>
|
||||
</td>
|
||||
|
||||
<td class="px-6 py-3 text-sm leading-5 text-gray-500 font-medium">
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="flex flex-shrink-0 -space-x-1"><a class="max-w-none h-9 w-9 rounded-full text-white shadow-solid p-2 text-xs bg-blue-500 hover:bg-blue-400" href="#">4</a>
|
||||
<a class="max-w-none h-9 w-9 rounded-full text-white shadow-solid p-2 text-xs bg-green-500 hover:bg-green-400" href="#">999</a>
|
||||
<a class="max-w-none h-9 w-9 rounded-full text-white shadow-solid p-2 text-xs bg-red-500 hover:bg-red-400" href="#">75</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="hidden md:table-cell px-6 py-3 whitespace-no-wrap text-sm leading-5 text-gray-500 text-right">47</td>
|
||||
<td class="hidden md:table-cell px-6 py-3 whitespace-no-wrap text-sm leading-5 text-gray-500 text-right">47</td>
|
||||
<td class="pr-6">
|
||||
<elsa-context-menu/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 (
|
||||
<Host id={`activity-${activityId}`}
|
||||
onDblClick={e => this.onEditActivityClick(e)}
|
||||
<Host id={`activity-${activityId}`}
|
||||
onDblClick={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">
|
||||
<div class="p-5">
|
||||
<div class="flex justify-between space-x-8">
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
@ -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'
|
||||
|
||||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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<WorkflowDefinition>;
|
||||
@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 (
|
||||
<button onClick={() => this.onShowWorkflowSettingsClick()} type="button"
|
||||
class="workflow-settings-button fixed top-10 right-12 inline-flex items-center p-2 rounded-full border border-transparent bg-white shadow text-gray-400 hover:text-blue-500 focus:text-blue-500 hover:ring-2 hover:ring-offset-2 hover:ring-blue-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
|
||||
class="workflow-settings-button fixed top-20 right-12 inline-flex items-center p-2 rounded-full border border-transparent bg-white shadow text-gray-400 hover:text-blue-500 focus:text-blue-500 hover:ring-2 hover:ring-offset-2 hover:ring-blue-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke="currentColor" fill="none" class="h-8 w-8">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/>
|
||||
|
|
@ -3,7 +3,7 @@ import {enter, leave, toggle} from 'el-transition'
|
|||
import {registerClickOutside} from "stencil-click-outside";
|
||||
import {VersionOptions, WorkflowDefinition} from "../../../../models";
|
||||
import {createElsaClient} from "../../../../services/elsa-client";
|
||||
import Tunnel from '../../../data/workflow-editor';
|
||||
import Tunnel from '../../../../data/workflow-editor';
|
||||
|
||||
@Component({
|
||||
tag: 'elsa-workflow-publish-button',
|
||||
|
|
@ -2,7 +2,7 @@ import {Component, Event, h, Host, Prop, State, Watch} from '@stencil/core';
|
|||
import {eventBus} from "../../../../services/event-bus";
|
||||
import {Map} from "../../../../utils/utils";
|
||||
import {EventTypes, Variables, WorkflowContextFidelity, WorkflowContextOptions, WorkflowDefinition} from "../../../../models";
|
||||
import {MonacoValueChangedArgs} from "../../monaco/elsa-monaco/elsa-monaco";
|
||||
import {MonacoValueChangedArgs} from "../../../controls/elsa-monaco/elsa-monaco";
|
||||
import {MarkerSeverity} from "monaco-editor";
|
||||
import {checkBox, FormContext, selectField, SelectOption, textArea, textInput} from "../../../../utils/forms";
|
||||
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
import {Component, h, Prop, State} from '@stencil/core';
|
||||
import * as collection from 'lodash/collection';
|
||||
import * as object from 'lodash/object';
|
||||
import {createElsaClient} from "../../../../services/elsa-client";
|
||||
import {PagedList, VersionOptions, WorkflowDefinitionSummary} from "../../../../models";
|
||||
|
||||
@Component({
|
||||
tag: 'elsa-workflow-definitions-list-screen',
|
||||
styleUrl: 'elsa-workflow-definitions-list-screen.css',
|
||||
shadow: false,
|
||||
})
|
||||
export class ElsaWorkflowDefinitionsListScreen {
|
||||
|
||||
@Prop() serverUrl: string;
|
||||
@State() workflowDefinitions: PagedList<WorkflowDefinitionSummary> = {items: [], page: 1, pageSize: 50, totalCount: 0};
|
||||
|
||||
confirmDialog: HTMLElsaConfirmDialogElement;
|
||||
|
||||
async componentWillLoad() {
|
||||
await this.loadWorkflowDefinitions();
|
||||
}
|
||||
|
||||
async onDeleteClick(e: Event, workflowDefinition: WorkflowDefinitionSummary) {
|
||||
const result = await this.confirmDialog.show('Delete Workflow Definition', 'Are you sure you wish to permanently delete this workflow, including all of its workflow instances?');
|
||||
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
const elsaClient = this.createClient();
|
||||
await elsaClient.workflowDefinitionsApi.delete(workflowDefinition.definitionId);
|
||||
await this.loadWorkflowDefinitions();
|
||||
}
|
||||
|
||||
async loadWorkflowDefinitions() {
|
||||
const elsaClient = this.createClient();
|
||||
const page = 0;
|
||||
const pageSize = 50;
|
||||
const versionOptions: VersionOptions = {allVersions: true};
|
||||
this.workflowDefinitions = await elsaClient.workflowDefinitionsApi.list(page, pageSize, versionOptions);
|
||||
}
|
||||
|
||||
createClient() {
|
||||
return createElsaClient(this.serverUrl);
|
||||
}
|
||||
|
||||
render() {
|
||||
const workflowDefinitions = this.workflowDefinitions.items;
|
||||
const groupings = collection.groupBy(workflowDefinitions, 'definitionId');
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div class="align-middle inline-block min-w-full border-b border-gray-200">
|
||||
<table class="min-w-full">
|
||||
<thead>
|
||||
<tr class="border-t border-gray-200">
|
||||
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider"><span class="lg:pl-2">Name</span></th>
|
||||
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
||||
Instances
|
||||
</th>
|
||||
<th class="hidden md:table-cell px-6 py-3 border-b border-gray-200 bg-gray-50 text-right text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
||||
Latest Version
|
||||
</th>
|
||||
<th class="hidden md:table-cell px-6 py-3 border-b border-gray-200 bg-gray-50 text-right text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
||||
Published Version
|
||||
</th>
|
||||
<th class="pr-6 py-3 border-b border-gray-200 bg-gray-50 text-right text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider"/>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="bg-white divide-y divide-gray-100">
|
||||
{collection.map(groupings, group => {
|
||||
const versions = collection.orderBy(group, 'version', 'desc');
|
||||
const workflowDefinition = versions[0]
|
||||
const latestVersionNumber = workflowDefinition.version;
|
||||
const publishedVersion: WorkflowDefinitionSummary = versions.find(x => x.isPublished);
|
||||
const publishedVersionNumber = !!publishedVersion ? publishedVersion.version : '-';
|
||||
let workflowDisplayName = workflowDefinition.displayName;
|
||||
|
||||
if (!workflowDisplayName || workflowDisplayName.trim().length == 0)
|
||||
workflowDisplayName = workflowDefinition.name;
|
||||
|
||||
if (!workflowDisplayName || workflowDisplayName.trim().length == 0)
|
||||
workflowDisplayName = 'Untitled';
|
||||
|
||||
const editUrl = `/workflow-definitions/${workflowDefinition.definitionId}`;
|
||||
|
||||
const editIcon = (
|
||||
<svg class="h-5 w-5 text-gray-500" width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
|
||||
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const deleteIcon = (
|
||||
<svg class="h-5 w-5 text-gray-500" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z"/>
|
||||
<line x1="4" y1="7" x2="20" y2="7"/>
|
||||
<line x1="10" y1="11" x2="10" y2="17"/>
|
||||
<line x1="14" y1="11" x2="14" y2="17"/>
|
||||
<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2l1 -12"/>
|
||||
<path d="M9 7v-3a1 1 0 0 1 1 -1h4a1 1 0 0 1 1 1v3"/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
return (
|
||||
<tr>
|
||||
<td class="px-6 py-3 whitespace-no-wrap text-sm leading-5 font-medium text-gray-900">
|
||||
<div class="flex items-center space-x-3 lg:pl-2">
|
||||
<stencil-route-link url={editUrl} anchorClass="truncate hover:text-gray-600"><span>{workflowDisplayName}</span></stencil-route-link>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="px-6 py-3 text-sm leading-5 text-gray-500 font-medium">
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="flex flex-shrink-0 -space-x-1"><a class="max-w-none h-9 w-9 rounded-full text-white shadow-solid p-2 text-xs bg-blue-500 hover:bg-blue-400" href="#">4</a>
|
||||
<a class="max-w-none h-9 w-9 rounded-full text-white shadow-solid p-2 text-xs bg-green-500 hover:bg-green-400" href="#">999</a>
|
||||
<a class="max-w-none h-9 w-9 rounded-full text-white shadow-solid p-2 text-xs bg-red-500 hover:bg-red-400" href="#">75</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="hidden md:table-cell px-6 py-3 whitespace-no-wrap text-sm leading-5 text-gray-500 text-right">{latestVersionNumber}</td>
|
||||
<td class="hidden md:table-cell px-6 py-3 whitespace-no-wrap text-sm leading-5 text-gray-500 text-right">{publishedVersionNumber}</td>
|
||||
<td class="pr-6">
|
||||
<elsa-context-menu menuItems={[
|
||||
{text: 'Edit', anchorUrl: editUrl, icon: editIcon},
|
||||
{text: 'Delete', clickHandler: e => this.onDeleteClick(e, workflowDefinition), icon: deleteIcon}
|
||||
]}/>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<elsa-confirm-dialog ref={el => this.confirmDialog = el}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
import {Component, h, Host, Method, State} from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'elsa-confirm-dialog',
|
||||
shadow: false,
|
||||
})
|
||||
export class ElsaConfirmDialog {
|
||||
|
||||
@State() caption: string;
|
||||
@State() message: string;
|
||||
|
||||
dialog: HTMLElsaModalDialogElement;
|
||||
fulFill: (value: (PromiseLike<boolean> | boolean)) => void;
|
||||
reject: () => void;
|
||||
|
||||
@Method()
|
||||
async show(caption: string, message: string): Promise<boolean> {
|
||||
this.caption = caption;
|
||||
this.message = message;
|
||||
|
||||
await this.dialog.show(true);
|
||||
|
||||
return new Promise<boolean>((fulfill, reject) => {
|
||||
this.fulFill = fulfill;
|
||||
this.reject = reject;
|
||||
});
|
||||
}
|
||||
|
||||
@Method()
|
||||
async hide() {
|
||||
await this.dialog.hide(true);
|
||||
}
|
||||
|
||||
async onDismissClick() {
|
||||
this.fulFill(false);
|
||||
await this.hide();
|
||||
}
|
||||
|
||||
async onAcceptClick() {
|
||||
this.fulFill(true);
|
||||
this.fulFill = null;
|
||||
this.reject = null;
|
||||
await this.hide();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Host>
|
||||
<elsa-modal-dialog ref={el => this.dialog = el}>
|
||||
<div slot="content" class="py-8 px-4">
|
||||
<div class="hidden sm:block absolute top-0 right-0 pt-4 pr-4">
|
||||
<button type="button"
|
||||
onClick={() => this.onDismissClick()}
|
||||
class="bg-white rounded-md text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
|
||||
<span class="sr-only">Close</span>
|
||||
<svg class="h-6 w-6" x-description="Heroicon name: outline/x" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="sm:flex sm:items-start">
|
||||
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||
<svg class="h-6 w-6 text-red-600" x-description="Heroicon name: outline/exclamation" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||
<h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">
|
||||
{this.caption}
|
||||
</h3>
|
||||
<div class="mt-2">
|
||||
<p class="text-sm text-gray-500">
|
||||
{this.message}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div slot="buttons">
|
||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<button type="button"
|
||||
onClick={() => this.onAcceptClick()}
|
||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
Yes
|
||||
</button>
|
||||
<button type="button"
|
||||
onClick={() => this.onDismissClick()}
|
||||
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:w-auto sm:text-sm">
|
||||
No
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</elsa-modal-dialog>
|
||||
</Host>
|
||||
);
|
||||
}
|
||||
}
|
||||
13
src/designer/elsa-workflows-studio/src/data/dashboard.tsx
Normal file
13
src/designer/elsa-workflows-studio/src/data/dashboard.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import {createProviderConsumer} from "@stencil/state-tunnel";
|
||||
import {h} from "@stencil/core";
|
||||
|
||||
export interface DashboardState {
|
||||
serverUrl: string;
|
||||
}
|
||||
|
||||
export default createProviderConsumer<DashboardState>(
|
||||
{
|
||||
serverUrl: null
|
||||
},
|
||||
(subscribe, child) => (<context-consumer subscribe={subscribe} renderer={child}/>)
|
||||
);
|
||||
|
|
@ -7,14 +7,16 @@
|
|||
<link rel="stylesheet" href="/build/assets/fonts/inter/inter.css">
|
||||
|
||||
<!-- Including a pre-built tailwind.css file for development. Don't include this when using a production build, since tailwind would already be included -->
|
||||
<link href="/build/assets/tailwind.css" rel="stylesheet">
|
||||
<link href="/build/assets/styles/tailwind.css" rel="stylesheet">
|
||||
<script src="/build/assets/js/monaco-editor/min/vs/loader.js"></script>
|
||||
<script type="module" src="/build/elsa-workflows-studio.esm.js"></script>
|
||||
<script nomodule src="/build/elsa-workflows-studio.js"></script>
|
||||
</head>
|
||||
<body class="h-screen" style="background-size: 30px 30px; background-image: url(/build/assets/tile.png); background-color: #FBFBFB;">
|
||||
|
||||
<elsa-workflow-editor id="workflowEditor" server-url="https://localhost:11000/" workflow-definition-id="7eed1333c2674370a1e9b300aa94fda2" monaco-lib-path="build/assets/js"></elsa-workflow-editor>
|
||||
<!--<elsa-workflow-editor id="workflowEditor" server-url="https://localhost:11000/" workflow-definition-id="7eed1333c2674370a1e9b300aa94fda2" monaco-lib-path="build/assets/js"></elsa-workflow-editor>-->
|
||||
|
||||
<app-root server-url="https://localhost:11000/"></app-root>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
export { Components, JSX } from './components';
|
||||
import '@stencil/router';
|
||||
|
|
|
|||
|
|
@ -20,6 +20,20 @@ export interface WorkflowDefinition {
|
|||
connections: Array<ConnectionDefinition>;
|
||||
}
|
||||
|
||||
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<string>
|
||||
}
|
||||
|
||||
export interface PagedList<T> {
|
||||
items: Array<T>;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
export enum ActivityTraits {
|
||||
Action = 1,
|
||||
Trigger = 2,
|
||||
|
|
|
|||
|
|
@ -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<PagedList<WorkflowDefinitionSummary>>(`v1/workflow-definitions?version=${versionOptionsString}`);
|
||||
return response.data;
|
||||
},
|
||||
getByDefinitionAndVersion: async (definitionId: string, versionOptions: VersionOptions) => {
|
||||
const versionOptionsString = getVersionOptionsString(versionOptions);
|
||||
const response = await httpClient.get<WorkflowDefinition>(`v1/workflow-definitions/${definitionId}/${versionOptionsString}`);
|
||||
|
|
@ -25,6 +42,9 @@ export const createElsaClient = function (serverUrl: string): ElsaClient {
|
|||
const response = await httpClient.post<WorkflowDefinition>('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<WorkflowDefinition>(`v1/workflow-definitions/${workflowDefinitionId}/retract`);
|
||||
return response.data;
|
||||
|
|
@ -78,8 +98,12 @@ export interface ActivitiesApi {
|
|||
export interface WorkflowDefinitionsApi {
|
||||
getByDefinitionAndVersion(definitionId: string, versionOptions: VersionOptions): Promise<WorkflowDefinition>
|
||||
|
||||
list(page?: number, pageSize?: number, versionOptions?: VersionOptions): Promise<PagedList<WorkflowDefinitionSummary>>
|
||||
|
||||
save(request: SaveWorkflowDefinitionRequest): Promise<WorkflowDefinition>
|
||||
|
||||
delete(definitionId: string): Promise<void>
|
||||
|
||||
retract(workflowDefinitionId: string): Promise<WorkflowDefinition>
|
||||
|
||||
export(workflowDefinitionId: string, versionOptions: VersionOptions): Promise<ExportWorkflowResponse>
|
||||
|
|
|
|||
|
|
@ -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<WorkflowDefinition>))]
|
||||
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(PagedList<WorkflowDefinitionSummaryModel>))]
|
||||
[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<ActionResult<PagedList<WorkflowDefinition>>> Handle(int? page = default, int? pageSize = default, VersionOptions? version = default, CancellationToken cancellationToken = default)
|
||||
public async Task<ActionResult<PagedList<WorkflowDefinitionSummaryModel>>> 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<WorkflowDefinition>(items.ToList(), page, pageSize, totalCount);
|
||||
var summaries = _mapper.Map<IList<WorkflowDefinitionSummaryModel>>(items);
|
||||
var pagedList = new PagedList<WorkflowDefinitionSummaryModel>(summaries, page, pageSize, totalCount);
|
||||
|
||||
return Json(pagedList, _serializer.GetSettings());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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<ICompositeActivityBlueprint, CompositeActivityBlueprintModel>();
|
||||
CreateMap<IConnection, ConnectionModel>().ConvertUsing<ConnectionConverter>();
|
||||
CreateMap<WorkflowInstance, WorkflowInstanceSummaryModel>();
|
||||
CreateMap<WorkflowDefinition, WorkflowDefinitionSummaryModel>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<WorkflowDefinitionSummaryModel>
|
||||
{
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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<PagedList<WorkflowDefinitionSummaryModel>>
|
||||
{
|
||||
public PagedList<WorkflowDefinitionSummaryModel> GetExamples()
|
||||
{
|
||||
var examples = Enumerable.Range(1, 3).Select(_ => new WorkflowDefinitionSummaryModelExample().GetExamples()).ToList();
|
||||
return new PagedList<WorkflowDefinitionSummaryModel>(examples, 0, 10, examples.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue