Merge branch 'master' into manual_workflow_trigger

This commit is contained in:
axeleron007 2021-10-02 22:43:29 +03:00
commit cc600ff372
36 changed files with 367 additions and 290 deletions

View file

@ -366,7 +366,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.Forks", "src\s
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "retention", "retention", "{235ABC3F-A075-4682-B6D7-837098BA6B00}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Retention", "src\modules\Elsa.Retention\Elsa.Retention.csproj", "{6DD8EB07-95CD-4F5A-9C0C-FD7F317EBC5A}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Retention", "src\modules\retention\Elsa.Retention\Elsa.Retention.csproj", "{FAEEA170-560C-4AF3-B4A8-92DEBD59D418}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -866,10 +866,10 @@ Global
{AB67BA19-5BC2-4C6D-A994-61D51A6A6FD5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AB67BA19-5BC2-4C6D-A994-61D51A6A6FD5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AB67BA19-5BC2-4C6D-A994-61D51A6A6FD5}.Release|Any CPU.Build.0 = Release|Any CPU
{6DD8EB07-95CD-4F5A-9C0C-FD7F317EBC5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6DD8EB07-95CD-4F5A-9C0C-FD7F317EBC5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6DD8EB07-95CD-4F5A-9C0C-FD7F317EBC5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6DD8EB07-95CD-4F5A-9C0C-FD7F317EBC5A}.Release|Any CPU.Build.0 = Release|Any CPU
{FAEEA170-560C-4AF3-B4A8-92DEBD59D418}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FAEEA170-560C-4AF3-B4A8-92DEBD59D418}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FAEEA170-560C-4AF3-B4A8-92DEBD59D418}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FAEEA170-560C-4AF3-B4A8-92DEBD59D418}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1033,7 +1033,7 @@ Global
{A2572DBF-AF11-4A02-AF99-B343871F2D85} = {22E75696-6FE9-436A-9097-EE21C603F818}
{AB67BA19-5BC2-4C6D-A994-61D51A6A6FD5} = {FC9F520F-BA51-4AD2-BFEE-EF787798E734}
{235ABC3F-A075-4682-B6D7-837098BA6B00} = {69BB424A-AAA3-415C-9651-9F4349CA3AC5}
{6DD8EB07-95CD-4F5A-9C0C-FD7F317EBC5A} = {235ABC3F-A075-4682-B6D7-837098BA6B00}
{FAEEA170-560C-4AF3-B4A8-92DEBD59D418} = {235ABC3F-A075-4682-B6D7-837098BA6B00}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8B0975FD-7050-48B0-88C5-48C33378E158}

View file

@ -9,7 +9,7 @@ namespace Elsa
{
public static class ObjectConverter
{
public static T? ConvertTo<T>(this object? value) => (T?) value.ConvertTo(typeof(T));
public static T? ConvertTo<T>(this object? value) => value != null ? (T?)value.ConvertTo(typeof(T)) : default;
public static object? ConvertTo(this object? value, Type targetType)
{

View file

@ -43,6 +43,9 @@ export namespace Components {
interface ElsaControl {
"content": VNode | string | Element;
}
interface ElsaCopyButton {
"value": string;
}
interface ElsaDesignerTree {
"activityBorderColor"?: (activity: ActivityModel) => string;
"activityContextMenu"?: ActivityContextMenuState;
@ -54,6 +57,7 @@ export namespace Components {
"mode": WorkflowDesignerMode;
"model": WorkflowModel;
"removeActivity": (activity: ActivityModel) => Promise<void>;
"removeSelectedActivities": () => Promise<void>;
"selectedActivityIds": Array<string>;
"showActivityEditor": (activity: ActivityModel, animate: boolean) => Promise<void>;
}
@ -101,8 +105,8 @@ export namespace Components {
"propertyModel": ActivityDefinitionProperty;
}
interface ElsaModalDialog {
"hide": (animate: boolean) => Promise<void>;
"show": (animate: boolean) => Promise<void>;
"hide": (animate?: boolean) => Promise<void>;
"show": (animate?: boolean) => Promise<void>;
}
interface ElsaMonaco {
"addJavaScriptLib": (libSource: string, libUri: string) => Promise<void>;
@ -248,11 +252,6 @@ export namespace Components {
}
interface ElsaWorkflowBlueprintPropertiesPanel {
"culture": string;
"expandButtonPosition": number;
"serverUrl": string;
"workflowBlueprint": WorkflowBlueprint;
}
interface ElsaWorkflowBlueprintSidePanel {
"serverUrl": string;
"workflowId": string;
}
@ -377,6 +376,12 @@ declare global {
prototype: HTMLElsaControlElement;
new (): HTMLElsaControlElement;
};
interface HTMLElsaCopyButtonElement extends Components.ElsaCopyButton, HTMLStencilElement {
}
var HTMLElsaCopyButtonElement: {
prototype: HTMLElsaCopyButtonElement;
new (): HTMLElsaCopyButtonElement;
};
interface HTMLElsaDesignerTreeElement extends Components.ElsaDesignerTree, HTMLStencilElement {
}
var HTMLElsaDesignerTreeElement: {
@ -599,12 +604,6 @@ declare global {
prototype: HTMLElsaWorkflowBlueprintPropertiesPanelElement;
new (): HTMLElsaWorkflowBlueprintPropertiesPanelElement;
};
interface HTMLElsaWorkflowBlueprintSidePanelElement extends Components.ElsaWorkflowBlueprintSidePanel, HTMLStencilElement {
}
var HTMLElsaWorkflowBlueprintSidePanelElement: {
prototype: HTMLElsaWorkflowBlueprintSidePanelElement;
new (): HTMLElsaWorkflowBlueprintSidePanelElement;
};
interface HTMLElsaWorkflowBlueprintViewerScreenElement extends Components.ElsaWorkflowBlueprintViewerScreen, HTMLStencilElement {
}
var HTMLElsaWorkflowBlueprintViewerScreenElement: {
@ -685,6 +684,7 @@ declare global {
"elsa-confirm-dialog": HTMLElsaConfirmDialogElement;
"elsa-context-menu": HTMLElsaContextMenuElement;
"elsa-control": HTMLElsaControlElement;
"elsa-copy-button": HTMLElsaCopyButtonElement;
"elsa-designer-tree": HTMLElsaDesignerTreeElement;
"elsa-dropdown-button": HTMLElsaDropdownButtonElement;
"elsa-dropdown-property": HTMLElsaDropdownPropertyElement;
@ -722,7 +722,6 @@ declare global {
"elsa-webhook-definition-editor-screen": HTMLElsaWebhookDefinitionEditorScreenElement;
"elsa-webhook-definitions-list-screen": HTMLElsaWebhookDefinitionsListScreenElement;
"elsa-workflow-blueprint-properties-panel": HTMLElsaWorkflowBlueprintPropertiesPanelElement;
"elsa-workflow-blueprint-side-panel": HTMLElsaWorkflowBlueprintSidePanelElement;
"elsa-workflow-blueprint-viewer-screen": HTMLElsaWorkflowBlueprintViewerScreenElement;
"elsa-workflow-definition-editor-notifications": HTMLElsaWorkflowDefinitionEditorNotificationsElement;
"elsa-workflow-definition-editor-screen": HTMLElsaWorkflowDefinitionEditorScreenElement;
@ -762,6 +761,9 @@ declare namespace LocalJSX {
interface ElsaControl {
"content"?: VNode | string | Element;
}
interface ElsaCopyButton {
"value"?: string;
}
interface ElsaDesignerTree {
"activityBorderColor"?: (activity: ActivityModel) => string;
"activityContextMenu"?: ActivityContextMenuState;
@ -971,11 +973,6 @@ declare namespace LocalJSX {
}
interface ElsaWorkflowBlueprintPropertiesPanel {
"culture"?: string;
"expandButtonPosition"?: number;
"serverUrl"?: string;
"workflowBlueprint"?: WorkflowBlueprint;
}
interface ElsaWorkflowBlueprintSidePanel {
"serverUrl"?: string;
"workflowId"?: string;
}
@ -1061,6 +1058,7 @@ declare namespace LocalJSX {
"elsa-confirm-dialog": ElsaConfirmDialog;
"elsa-context-menu": ElsaContextMenu;
"elsa-control": ElsaControl;
"elsa-copy-button": ElsaCopyButton;
"elsa-designer-tree": ElsaDesignerTree;
"elsa-dropdown-button": ElsaDropdownButton;
"elsa-dropdown-property": ElsaDropdownProperty;
@ -1098,7 +1096,6 @@ declare namespace LocalJSX {
"elsa-webhook-definition-editor-screen": ElsaWebhookDefinitionEditorScreen;
"elsa-webhook-definitions-list-screen": ElsaWebhookDefinitionsListScreen;
"elsa-workflow-blueprint-properties-panel": ElsaWorkflowBlueprintPropertiesPanel;
"elsa-workflow-blueprint-side-panel": ElsaWorkflowBlueprintSidePanel;
"elsa-workflow-blueprint-viewer-screen": ElsaWorkflowBlueprintViewerScreen;
"elsa-workflow-definition-editor-notifications": ElsaWorkflowDefinitionEditorNotifications;
"elsa-workflow-definition-editor-screen": ElsaWorkflowDefinitionEditorScreen;
@ -1124,6 +1121,7 @@ declare module "@stencil/core" {
"elsa-confirm-dialog": LocalJSX.ElsaConfirmDialog & JSXBase.HTMLAttributes<HTMLElsaConfirmDialogElement>;
"elsa-context-menu": LocalJSX.ElsaContextMenu & JSXBase.HTMLAttributes<HTMLElsaContextMenuElement>;
"elsa-control": LocalJSX.ElsaControl & JSXBase.HTMLAttributes<HTMLElsaControlElement>;
"elsa-copy-button": LocalJSX.ElsaCopyButton & JSXBase.HTMLAttributes<HTMLElsaCopyButtonElement>;
"elsa-designer-tree": LocalJSX.ElsaDesignerTree & JSXBase.HTMLAttributes<HTMLElsaDesignerTreeElement>;
"elsa-dropdown-button": LocalJSX.ElsaDropdownButton & JSXBase.HTMLAttributes<HTMLElsaDropdownButtonElement>;
"elsa-dropdown-property": LocalJSX.ElsaDropdownProperty & JSXBase.HTMLAttributes<HTMLElsaDropdownPropertyElement>;
@ -1161,7 +1159,6 @@ declare module "@stencil/core" {
"elsa-webhook-definition-editor-screen": LocalJSX.ElsaWebhookDefinitionEditorScreen & JSXBase.HTMLAttributes<HTMLElsaWebhookDefinitionEditorScreenElement>;
"elsa-webhook-definitions-list-screen": LocalJSX.ElsaWebhookDefinitionsListScreen & JSXBase.HTMLAttributes<HTMLElsaWebhookDefinitionsListScreenElement>;
"elsa-workflow-blueprint-properties-panel": LocalJSX.ElsaWorkflowBlueprintPropertiesPanel & JSXBase.HTMLAttributes<HTMLElsaWorkflowBlueprintPropertiesPanelElement>;
"elsa-workflow-blueprint-side-panel": LocalJSX.ElsaWorkflowBlueprintSidePanel & JSXBase.HTMLAttributes<HTMLElsaWorkflowBlueprintSidePanelElement>;
"elsa-workflow-blueprint-viewer-screen": LocalJSX.ElsaWorkflowBlueprintViewerScreen & JSXBase.HTMLAttributes<HTMLElsaWorkflowBlueprintViewerScreenElement>;
"elsa-workflow-definition-editor-notifications": LocalJSX.ElsaWorkflowDefinitionEditorNotifications & JSXBase.HTMLAttributes<HTMLElsaWorkflowDefinitionEditorNotificationsElement>;
"elsa-workflow-definition-editor-screen": LocalJSX.ElsaWorkflowDefinitionEditorScreen & JSXBase.HTMLAttributes<HTMLElsaWorkflowDefinitionEditorScreenElement>;

View file

@ -26,10 +26,8 @@ graph TD;
elsa-workflow-blueprint-viewer-screen --> elsa-flyout-panel
elsa-workflow-blueprint-viewer-screen --> elsa-tab-header
elsa-workflow-blueprint-viewer-screen --> elsa-tab-content
elsa-workflow-blueprint-viewer-screen --> elsa-workflow-blueprint-side-panel
elsa-workflow-blueprint-viewer-screen --> elsa-workflow-blueprint-properties-panel
elsa-workflow-blueprint-viewer-screen --> context-consumer
elsa-workflow-blueprint-side-panel --> elsa-workflow-blueprint-properties-panel
elsa-workflow-blueprint-side-panel --> context-consumer
elsa-workflow-blueprint-properties-panel --> context-consumer
style elsa-studio-workflow-blueprint-view fill:#f9f,stroke:#333,stroke-width:4px
```

View file

@ -25,6 +25,8 @@ graph TD;
elsa-workflow-instance-viewer-screen --> elsa-workflow-instance-journal
elsa-workflow-instance-viewer-screen --> elsa-designer-tree
elsa-workflow-instance-viewer-screen --> context-consumer
elsa-workflow-instance-journal --> elsa-copy-button
elsa-workflow-instance-journal --> elsa-workflow-definition-editor-notifications
elsa-workflow-instance-journal --> elsa-flyout-panel
elsa-workflow-instance-journal --> elsa-tab-header
elsa-workflow-instance-journal --> elsa-tab-content

View file

@ -67,6 +67,7 @@ export class ElsaWorkflowDesigner {
x: 0,
y: 0,
activity: null,
selectedActivities: {}
};
@State() connectionContextMenuState: ActivityContextMenuState = {
@ -169,6 +170,17 @@ export class ElsaWorkflowDesigner {
this.removeActivityInternal(activity);
}
@Method()
async removeSelectedActivities() {
let model = {...this.workflowModel};
Object.keys(this.selectedActivities).forEach((key) => {
model = this.removeActivityInternal(this.selectedActivities[key], model);
});
this.updateWorkflowModel(model);
}
@Method()
async showActivityEditor(activity: ActivityModel, animate: boolean) {
await this.showActivityEditorInternal(activity, animate);
@ -369,8 +381,8 @@ export class ElsaWorkflowDesigner {
return model;
}
removeActivityInternal(activity: ActivityModel) {
let workflowModel = {...this.workflowModel};
removeActivityInternal(activity: ActivityModel, model?: WorkflowModel) {
let workflowModel = model || {...this.workflowModel};
const incomingConnections = getInboundConnections(workflowModel, activity.activityId);
const outgoingConnections = getOutboundConnections(workflowModel, activity.activityId);
@ -395,7 +407,14 @@ export class ElsaWorkflowDesigner {
});
}
}
this.updateWorkflowModel(workflowModel);
delete this.selectedActivities[activity.activityId];
if (!model) {
this.updateWorkflowModel(workflowModel);
}
return workflowModel;
}
newActivity(activityDescriptor: ActivityDescriptor): ActivityModel {
@ -798,7 +817,13 @@ export class ElsaWorkflowDesigner {
.select('.context-menu-button-container button')
.on('click', evt => {
evt.stopPropagation();
this.handleContextMenuChange({x: evt.clientX, y: evt.clientY, shown: true, activity: node.activity});
this.handleContextMenuChange({
x: evt.clientX,
y: evt.clientY,
shown: true,
activity: node.activity,
selectedActivities: this.selectedActivities
});
});
}
else if (this.mode == WorkflowDesignerMode.Test) {

View file

@ -1,4 +1,5 @@
import {ActivityModel, WorkflowFault} from "../../../../models";
import {ActivityModel} from "../../../../models";
import {Map} from "../../../../utils/utils";
export enum WorkflowDesignerMode {
Edit,
@ -12,9 +13,10 @@ export interface ActivityContextMenuState {
x: number;
y: number;
activity?: ActivityModel | null;
selectedActivities?: Map<ActivityModel> ;
}
export enum LayoutDirection {
Horizontal,
Vertical
}
}

View file

@ -1,6 +1,5 @@
import {Component, Prop, h, State, Watch, Host} from '@stencil/core';
import {enter, leave} from "el-transition"
import {WorkflowBlueprint, WorkflowDefinition, WorkflowDefinitionSummary} from "../../../../models";
import {WorkflowBlueprint, WorkflowDefinitionSummary} from "../../../../models";
import {i18n} from "i18next";
import {loadTranslations} from "../../../i18n/i18n-loader";
import {resources} from "./localizations";
@ -13,111 +12,58 @@ import Tunnel from "../../../../data/dashboard";
})
export class ElsaWorkflowBlueprintPropertiesPanel {
@Prop() workflowBlueprint: WorkflowBlueprint;
@Prop() workflowId: string;
@Prop() culture: string;
@Prop() serverUrl: string;
@Prop() expandButtonPosition = 1;
@State() workflowBlueprint: WorkflowBlueprint;
@State() publishedVersion: number;
@State() expanded: boolean;
private i18next: i18n;
el: HTMLElement;
@Watch('workflowBlueprint')
async workflowDefinitionChangedHandler(newWorkflow: WorkflowDefinition, oldWorkflow: WorkflowDefinition) {
if (newWorkflow.version !== oldWorkflow.version || newWorkflow.isPublished !== oldWorkflow.isPublished || newWorkflow.isLatest !== oldWorkflow.isLatest)
await this.loadPublishedVersion();
@Watch('workflowId')
async workflowIdChangedHandler(newWorkflowId: string) {
await this.loadWorkflowBlueprint(newWorkflowId);
await this.loadPublishedVersion();
}
async componentWillLoad() {
this.i18next = await loadTranslations(this.culture, resources);
await this.loadWorkflowBlueprint();
await this.loadPublishedVersion();
}
render() {
const t = (x, params?) => this.i18next.t(x, params);
const {workflowBlueprint, expanded, expandButtonPosition} = this;
const {workflowBlueprint} = this;
const name = workflowBlueprint.name || this.i18next.t("Untitled");
const {isPublished} = workflowBlueprint;
const expandPositionClass = expandButtonPosition == 1 ? "elsa-right-12" : "elsa-right-28";
return (
<Host>
<button type="button"
onClick={this.toggle}
class={`${expanded ? "hidden" : expandPositionClass} workflow-settings-button elsa-fixed elsa-top-20 elsa-inline-flex elsa-items-center elsa-p-2 elsa-rounded-full elsa-border elsa-border-transparent elsa-bg-white shadow elsa-text-gray-400 hover:elsa-text-blue-500 focus:elsa-text-blue-500 hover:elsa-ring-2 hover:elsa-ring-offset-2 hover:elsa-ring-blue-500 focus:elsa-outline-none focus:elsa-ring-2 focus:elsa-ring-offset-2 focus:elsa-ring-blue-500 elsa-z-10`}>
<svg xmlns="http://www.w3.org/2000/svg" class="elsa-h-8 elsa-w-8" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 19l-7-7 7-7m8 14l-7-7 7-7"/>
</svg>
</button>
<section
class={`${this.expanded ? '' : 'hidden'} elsa-fixed elsa-top-4 elsa-right-0 elsa-bottom-0 elsa-overflow-hidden`}
aria-labelledby="slide-over-title" role="dialog" aria-modal="true">
<div class="elsa-absolute elsa-inset-0 elsa-overflow-hidden">
<div class="elsa-absolute elsa-inset-0" aria-hidden="true"/>
<div
class="elsa-fixed elsa-inset-y-0 elsa-top-16 elsa-right-0 max-elsa-w-full elsa-flex">
<div
ref={el => this.el = el}
data-transition-enter="elsa-transform elsa-transition elsa-ease-in-out elsa-duration-300 sm:elsa-duration-700"
data-transition-enter-start="elsa-translate-x-full"
data-transition-enter-end="elsa-translate-x-0"
data-transition-leave="elsa-transform elsa-transition elsa-ease-in-out elsa-duration-300 sm:elsa-duration-700"
data-transition-leave-start="elsa-translate-x-0"
data-transition-leave-end="elsa-translate-x-full"
class="elsa-w-screen elsa-max-w-lg elsa-h-full">
<button type="button"
onClick={this.toggle}
class="workflow-settings-button elsa-absolute elsa-top-4 elsa-left-2 elsa-inline-flex elsa-items-center elsa-p-2 elsa-rounded-full elsa-border elsa-border-transparent elsa-bg-white shadow elsa-text-gray-400 hover:elsa-text-blue-500 focus:elsa-text-blue-500 hover:elsa-ring-2 hover:elsa-ring-offset-2 hover:elsa-ring-blue-500 focus:elsa-outline-none focus:elsa-ring-2 focus:elsa-ring-offset-2 focus:elsa-ring-blue-500 elsa-z-10">
<svg xmlns="http://www.w3.org/2000/svg" class="elsa-h-8 elsa-w-8" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 5l7 7-7 7M5 5l7 7-7 7"/>
</svg>
</button>
<div
class="elsa-h-full elsa-flex elsa-flex-col elsa-py-6 elsa-bg-white elsa-shadow-xl elsa-overflow-y-scroll elsa-bg-white">
<div class="elsa-h-full">
<div class="elsa-mt-16 elsa-p-6">
<div class="elsa-font-medium elsa-leading-8 elsa-overflow-hidden">
<p
class="elsa-overflow-ellipsis">{t('Properties', {name: workflowBlueprint.displayName || name})}</p>
</div>
<div>
<dl
class="elsa-mt-2 elsa-border-t elsa-border-b elsa-border-gray-200 elsa-divide-y elsa-divide-gray-200">
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">{t('Name')}</dt>
<dd class="elsa-text-gray-900">{name}</dd>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">{t('Id')}</dt>
<dd class="elsa-text-gray-900 elsa-break-all">{workflowBlueprint.id || '-'}</dd>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">{t('Version')}</dt>
<dd class="elsa-text-gray-900">{workflowBlueprint.version}</dd>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">{t('PublishedVersion')}</dt>
<dd class="elsa-text-gray-900">{this.publishedVersion || '-'}</dd>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">{t('Status')}</dt>
<dd
class={`${isPublished ? 'elsa-text-green-600' : 'elsa-text-yellow-700'}`}>{isPublished ? t('Published') : t('Draft')}</dd>
</div>
</dl>
</div>
</div>
</div>
</div>
</div>
</div>
<dl class="elsa-border-b elsa-border-gray-200 elsa-divide-y elsa-divide-gray-200">
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">{t('Name')}</dt>
<dd class="elsa-text-gray-900">{name}</dd>
</div>
</section>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">{t('Id')}</dt>
<dd class="elsa-text-gray-900 elsa-break-all">{workflowBlueprint.id || '-'}</dd>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">{t('Version')}</dt>
<dd class="elsa-text-gray-900">{workflowBlueprint.version}</dd>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">{t('PublishedVersion')}</dt>
<dd class="elsa-text-gray-900">{this.publishedVersion || '-'}</dd>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">{t('Status')}</dt>
<dd
class={`${isPublished ? 'elsa-text-green-600' : 'elsa-text-yellow-700'}`}>{isPublished ? t('Published') : t('Draft')}</dd>
</div>
</dl>
</Host>
);
)
}
createClient() {
@ -128,21 +74,22 @@ export class ElsaWorkflowBlueprintPropertiesPanel {
const elsaClient = await this.createClient();
const {workflowBlueprint} = this;
const publishedWorkflowDefinitions = await elsaClient.workflowDefinitionsApi.getMany([workflowBlueprint.id], {isPublished: true});
const publishedDefinition: WorkflowDefinitionSummary = workflowBlueprint.isPublished ? workflowBlueprint : publishedWorkflowDefinitions.find(x => x.definitionId == workflowBlueprint.id);
if (workflowBlueprint.isPublished) {
const publishedWorkflowDefinitions = await elsaClient.workflowDefinitionsApi.getMany([workflowBlueprint.id], {isPublished: true});
const publishedDefinition: WorkflowDefinitionSummary = workflowBlueprint.isPublished ? workflowBlueprint : publishedWorkflowDefinitions.find(x => x.definitionId == workflowBlueprint.id);
if (publishedDefinition) {
this.publishedVersion = publishedDefinition.version;
if (publishedDefinition) {
this.publishedVersion = publishedDefinition.version;
}
} else {
this.publishedVersion = 0;
}
}
toggle = () => {
if (this.expanded) {
leave(this.el).then(() => this.expanded = false);
} else {
this.expanded = true;
enter(this.el);
}
async loadWorkflowBlueprint(workflowId = this.workflowId) {
const elsaClient = await this.createClient();
this.workflowBlueprint = await elsaClient.workflowRegistryApi.get(workflowId, {isLatest: true});
}
}

View file

@ -7,19 +7,18 @@
## Properties
| Property | Attribute | Description | Type | Default |
| ---------------------- | ------------------------ | ----------- | ------------------- | ----------- |
| `culture` | `culture` | | `string` | `undefined` |
| `expandButtonPosition` | `expand-button-position` | | `number` | `1` |
| `serverUrl` | `server-url` | | `string` | `undefined` |
| `workflowBlueprint` | -- | | `WorkflowBlueprint` | `undefined` |
| Property | Attribute | Description | Type | Default |
| ------------ | ------------- | ----------- | -------- | ----------- |
| `culture` | `culture` | | `string` | `undefined` |
| `serverUrl` | `server-url` | | `string` | `undefined` |
| `workflowId` | `workflow-id` | | `string` | `undefined` |
## Dependencies
### Used by
- [elsa-workflow-blueprint-side-panel](../elsa-workflow-blueprint-side-panel)
- [elsa-workflow-blueprint-viewer-screen](../elsa-workflow-blueprint-viewer-screen)
### Depends on
@ -29,7 +28,7 @@
```mermaid
graph TD;
elsa-workflow-blueprint-properties-panel --> context-consumer
elsa-workflow-blueprint-side-panel --> elsa-workflow-blueprint-properties-panel
elsa-workflow-blueprint-viewer-screen --> elsa-workflow-blueprint-properties-panel
style elsa-workflow-blueprint-properties-panel fill:#f9f,stroke:#333,stroke-width:4px
```

View file

@ -1,44 +0,0 @@
import {Component, h, Prop, State, Watch} from '@stencil/core';
import {WorkflowBlueprint} from "../../../../models";
import {createElsaClient} from "../../../../services";
import Tunnel from "../../../../data/dashboard";
@Component({
tag: 'elsa-workflow-blueprint-side-panel',
shadow: false,
})
export class ElsaWorkflowBlueprintSidePanel {
@Prop() workflowId: string;
@Prop() serverUrl: string;
@State() workflowBlueprint: WorkflowBlueprint;
@Watch('workflowId')
async workflowIdChangedHandler(newWorkflowId: string) {
await this.loadWorkflowBlueprint(newWorkflowId);
}
render() {
return (
<elsa-workflow-blueprint-properties-panel
workflowBlueprint={this.workflowBlueprint}
/>
);
}
async componentWillLoad() {
await this.loadWorkflowBlueprint();
}
createClient() {
return createElsaClient(this.serverUrl);
}
async loadWorkflowBlueprint(workflowId = this.workflowId) {
const elsaClient = await this.createClient();
this.workflowBlueprint = await elsaClient.workflowRegistryApi.get(workflowId, {isLatest: true});
}
}
Tunnel.injectProps(ElsaWorkflowBlueprintSidePanel, ['serverUrl']);

View file

@ -1,39 +0,0 @@
# elsa-workflow-blueprint-side-panel
<!-- Auto Generated Below -->
## Properties
| Property | Attribute | Description | Type | Default |
| ------------ | ------------- | ----------- | -------- | ----------- |
| `serverUrl` | `server-url` | | `string` | `undefined` |
| `workflowId` | `workflow-id` | | `string` | `undefined` |
## Dependencies
### Used by
- [elsa-workflow-blueprint-viewer-screen](../elsa-workflow-blueprint-viewer-screen)
### Depends on
- [elsa-workflow-blueprint-properties-panel](../elsa-workflow-blueprint-properties-panel)
- context-consumer
### Graph
```mermaid
graph TD;
elsa-workflow-blueprint-side-panel --> elsa-workflow-blueprint-properties-panel
elsa-workflow-blueprint-side-panel --> context-consumer
elsa-workflow-blueprint-properties-panel --> context-consumer
elsa-workflow-blueprint-viewer-screen --> elsa-workflow-blueprint-side-panel
style elsa-workflow-blueprint-side-panel fill:#f9f,stroke:#333,stroke-width:4px
```
----------------------------------------------
*Built with [StencilJS](https://stenciljs.com/)*

View file

@ -150,12 +150,16 @@ export class ElsaWorkflowBlueprintViewerScreen {
renderCanvas() {
return (
<div class="elsa-flex-1 elsa-flex">
<elsa-designer-tree model={this.workflowModel} class="elsa-flex-1" ref={el => this.designer = el}
mode={WorkflowDesignerMode.Blueprint}/>
<elsa-designer-tree
model={this.workflowModel}
class="elsa-flex-1"
ref={el => this.designer = el}
mode={WorkflowDesignerMode.Blueprint}
/>
<elsa-flyout-panel>
<elsa-tab-header tab="general" slot="header">General</elsa-tab-header>
<elsa-tab-content tab="general" slot="content">
<elsa-workflow-blueprint-side-panel workflowId={this.workflowDefinitionId}/>
<elsa-workflow-blueprint-properties-panel workflowId={this.workflowDefinitionId}/>
</elsa-tab-content>
</elsa-flyout-panel>
</div>

View file

@ -39,7 +39,7 @@ Type: `Promise<string>`
- [elsa-flyout-panel](../../../shared/elsa-flyout-panel)
- [elsa-tab-header](../../../shared/elsa-tab-header)
- [elsa-tab-content](../../../shared/elsa-tab-content)
- [elsa-workflow-blueprint-side-panel](../elsa-workflow-blueprint-side-panel)
- [elsa-workflow-blueprint-properties-panel](../elsa-workflow-blueprint-properties-panel)
- context-consumer
### Graph
@ -49,10 +49,8 @@ graph TD;
elsa-workflow-blueprint-viewer-screen --> elsa-flyout-panel
elsa-workflow-blueprint-viewer-screen --> elsa-tab-header
elsa-workflow-blueprint-viewer-screen --> elsa-tab-content
elsa-workflow-blueprint-viewer-screen --> elsa-workflow-blueprint-side-panel
elsa-workflow-blueprint-viewer-screen --> elsa-workflow-blueprint-properties-panel
elsa-workflow-blueprint-viewer-screen --> context-consumer
elsa-workflow-blueprint-side-panel --> elsa-workflow-blueprint-properties-panel
elsa-workflow-blueprint-side-panel --> context-consumer
elsa-workflow-blueprint-properties-panel --> context-consumer
elsa-studio-workflow-blueprint-view --> elsa-workflow-blueprint-viewer-screen
style elsa-workflow-blueprint-viewer-screen fill:#f9f,stroke:#333,stroke-width:4px

View file

@ -20,7 +20,7 @@ export class ElsaWorkflowEditorNotifications {
disconnectedCallback() {
eventBus.detach(EventTypes.WorkflowPublished, this.onWorkflowPublished);
eventBus.detach(EventTypes.WorkflowRetracted, this.onWorkflowRetracted);
eventBus.detach(EventTypes.WorkflowRetracted, this.onWorkflowRetracted);
eventBus.detach(EventTypes.WorkflowImported, this.onWorkflowImported);
eventBus.detach(EventTypes.ClipboardPermissionDenied, this.onClipboardPermissionsDenied);
eventBus.detach(EventTypes.ClipboardCopied, this.onClipboardCopied);
@ -30,5 +30,7 @@ export class ElsaWorkflowEditorNotifications {
onWorkflowRetracted = (workflowDefinition: WorkflowDefinition) => toastNotificationService.show('Workflow Retracted', `Workflow successfully retracted at version ${workflowDefinition.version}.`, 1500);
onWorkflowImported = () => toastNotificationService.show('Workflow Imported', `Workflow successfully imported.`, 1500);
onClipboardPermissionsDenied = () => toastNotificationService.show('Clipboard Error', `Clipboard pemission denied.`, 1500);
onClipboardCopied = () => toastNotificationService.show('Copy to Clipboard', `Activities successfully copied to Clipboard.`, 1500);
onClipboardCopied = (title: string, body: string) => {
toastNotificationService.show(title || 'Copy to Clipboard', body || 'Activities successfully copied to Clipboard.', 1500);
}
}

View file

@ -10,11 +10,13 @@
### Used by
- [elsa-workflow-definition-editor-screen](../elsa-workflow-definition-editor-screen)
- [elsa-workflow-instance-journal](../../workflow-instance-viewer/elsa-workflow-instance-journal)
### Graph
```mermaid
graph TD;
elsa-workflow-definition-editor-screen --> elsa-workflow-definition-editor-notifications
elsa-workflow-instance-journal --> elsa-workflow-definition-editor-notifications
style elsa-workflow-definition-editor-notifications fill:#f9f,stroke:#333,stroke-width:4px
```

View file

@ -26,6 +26,7 @@ import {i18n} from "i18next";
import {loadTranslations} from "../../../i18n/i18n-loader";
import {resources} from "./localizations";
import * as collection from 'lodash/collection';
import {Map} from "../../../../utils/utils";
@Component({
tag: 'elsa-workflow-definition-editor-screen',
@ -59,6 +60,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
x: 0,
y: 0,
activity: null,
selectedActivities: {}
};
@State() connectionContextMenuState: ActivityContextMenuState = {
@ -79,6 +81,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
el: HTMLElement;
designer: HTMLElsaDesignerTreeElement;
configureComponentCustomButtonContext: ConfigureComponentCustomButtonContext = null;
helpDialog: HTMLElsaModalDialogElement;
@Method()
async getServerUrl(): Promise<string> {
@ -323,7 +326,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
}
}
updateUrl(id){
updateUrl(id) {
this.history.push(`/workflow-definitions/${id}`, {});
}
@ -403,8 +406,15 @@ export class ElsaWorkflowDefinitionEditorScreen {
async onDeleteActivityClick(e: Event) {
e.preventDefault();
await this.designer.removeActivity(this.activityContextMenuState.activity);
this.handleContextMenuChange({x: 0, y: 0, shown: false, activity: null});
const {activity, selectedActivities} = this.activityContextMenuState;
if (selectedActivities[activity.activityId]) {
await this.designer.removeSelectedActivities();
} else {
await this.designer.removeActivity(activity);
}
this.handleContextMenuChange({x: 0, y: 0, shown: false, activity: null, selectedActivities: {}});
await eventBus.emit(EventTypes.HideModalDialog);
}
@ -569,6 +579,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
ref={el => this.designer = el}/>
{this.renderPanel()}
{this.renderWorkflowSettingsButton()}
{this.renderWorkflowHelpButton()}
{this.renderActivityContextMenu()}
{this.renderConnectionContextMenu()}
<elsa-workflow-settings-modal workflowDefinition={this.workflowDefinition}/>
@ -735,6 +746,8 @@ export class ElsaWorkflowDefinitionEditorScreen {
renderActivityContextMenu() {
const t = this.t;
const selectedActivities = Object.keys(this.activityContextMenuState.selectedActivities);
const {activity} = this.activityContextMenuState;
return <div
data-transition-enter="elsa-transition elsa-ease-out elsa-duration-100"
@ -747,7 +760,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
style={{left: `${this.activityContextMenuState.x}px`, top: `${this.activityContextMenuState.y}px`}}
ref={el =>
registerClickOutside(this, el, () => {
this.handleContextMenuChange({x: 0, y: 0, shown: false, activity: null});
this.handleContextMenuChange({x: 0, y: 0, shown: false, activity: null, selectedActivities: {}});
})
}
>
@ -769,7 +782,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
href="#"
class="elsa-block elsa-px-4 elsa-py-2 elsa-text-sm elsa-leading-5 elsa-text-gray-700 hover:elsa-bg-gray-100 hover:elsa-text-gray-900 focus:elsa-outline-none focus:elsa-bg-gray-100 focus:elsa-text-gray-900"
role="menuitem">
{t('ActivityContextMenu.Delete')}
{(selectedActivities.length > 1 && selectedActivities.indexOf(activity.activityId) !== -1) ? t('ActivityContextMenu.DeleteSelected') : t('ActivityContextMenu.Delete')}
</a>
</div>
</div>
@ -831,8 +844,48 @@ export class ElsaWorkflowDefinitionEditorScreen {
);
}
renderWorkflowSettingsModal() {
return;
renderWorkflowHelpButton() {
return (
<span>
<button type="button"
onClick={this.showHelpModal}
class="workflow-settings-button elsa-fixed elsa-top-20 elsa-right-28 elsa-inline-flex elsa-items-center elsa-p-2 elsa-rounded-full elsa-border elsa-border-transparent elsa-bg-white shadow elsa-text-gray-400 hover:elsa-text-blue-500 focus:elsa-text-blue-500 hover:elsa-ring-2 hover:elsa-ring-offset-2 hover:elsa-ring-blue-500 focus:elsa-outline-none focus:elsa-ring-2 focus:elsa-ring-offset-2 focus:elsa-ring-blue-500">
<svg xmlns="http://www.w3.org/2000/svg" class="elsa-h-8 elsa-w-8" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</button>
<elsa-modal-dialog ref={el => this.helpDialog = el}>
<div slot="content" class="elsa-p-8">
<h3 class="elsa-text-lg elsa-font-medium">Actions</h3>
<dl
class="elsa-mt-2 elsa-border-t elsa-border-b elsa-border-gray-200 elsa-divide-y elsa-divide-gray-200">
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">Delete connections</dt>
<dd class="elsa-text-gray-900">RIGHT-click the connection to delete.</dd>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">Connect outcomes to existing activity</dt>
<dd class="elsa-text-gray-900">Press and hold SHIFT while LEFT-clicking the outcome to connect. Release SHIFT and LEFT-click the target activity.</dd>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">Pan</dt>
<dd class="elsa-text-gray-900">Click anywhere on the designer and drag mouse.</dd>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">Zoom</dt>
<dd class="elsa-text-gray-900">Use scroll-wheel on mouse.</dd>
</div>
</dl>
</div>
</elsa-modal-dialog>
</span>
);
}
showHelpModal = async () => {
await this.helpDialog.show();
}
renderSavingIndicator() {
@ -891,7 +944,7 @@ export class ElsaWorkflowDefinitionEditorScreen {
private renderPanel() {
return (
<elsa-flyout-panel>
<elsa-flyout-panel expandButtonPosition={3}>
<elsa-tab-header tab="general" slot="header">General</elsa-tab-header>
<elsa-tab-content tab="general" slot="content">
<elsa-workflow-properties-panel

View file

@ -5,7 +5,8 @@
'Published': 'Published',
"ActivityContextMenu":{
"Edit": "Edit",
"Delete": "Delete"
"Delete": "Delete",
"DeleteSelected": "Delete Selected"
},
"ConnectionContextMenu":{
"Paste": "Paste",
@ -18,11 +19,12 @@
'Published': 'Gepubliceerd',
"ActivityContextMenu":{
"Edit": "Bewerken",
"Delete": "Verwijderen"
"Delete": "Verwijderen",
"DeleteSelected": "Verwijder Geselecteerde"
},
"ConnectionContextMenu":{
"Paste": "Plakken",
}
}
}
};
};

View file

@ -7,7 +7,7 @@ import {
PagedList,
WorkflowBlueprint,
WorkflowExecutionLogRecord, WorkflowInstance,
WorkflowModel,
WorkflowModel, WorkflowStatus,
} from "../../../../models";
import {activityIconProvider} from "../../../../services/activity-icon-provider";
import {createElsaClient} from "../../../../services/elsa-client";
@ -86,6 +86,24 @@ export class ElsaWorkflowInstanceJournal {
return map[eventName] || 'gray';
}
getStatusColor(status: WorkflowStatus) {
switch (status) {
default:
case WorkflowStatus.Idle:
return 'gray';
case WorkflowStatus.Running:
return 'rose';
case WorkflowStatus.Suspended:
return 'blue';
case WorkflowStatus.Finished:
return 'green';
case WorkflowStatus.Faulted:
return 'red';
case WorkflowStatus.Cancelled:
return 'yellow';
}
}
onRecordClick(record: WorkflowExecutionLogRecord) {
this.selectActivityRecordInternal(record);
this.recordSelected.emit(record);
@ -95,6 +113,7 @@ export class ElsaWorkflowInstanceJournal {
return (
<Host>
{this.renderPanel()}
<elsa-workflow-definition-editor-notifications/>
</Host>
);
}
@ -233,12 +252,18 @@ export class ElsaWorkflowInstanceJournal {
<dl class="sm:elsa-divide-y sm:elsa-divide-gray-200">
<div class="elsa-grid elsa-grid-cols-2 elsa-gap-x-4 elsa-gap-y-8 sm:elsa-grid-cols-2">
<div class="sm:elsa-col-span-2">
<dt class="elsa-text-sm elsa-font-medium elsa-text-gray-500">Activity ID</dt>
<dt class="elsa-text-sm elsa-font-medium elsa-text-gray-500">
<span>Activity ID</span>
<elsa-copy-button value={record.activityId}/>
</dt>
<dd class="elsa-mt-1 elsa-text-sm elsa-text-gray-900 elsa-mb-2">{record.activityId}</dd>
</div>
{outcomes.length > 0 ? (
<div class="sm:elsa-col-span-2">
<dt class="elsa-text-sm elsa-font-medium elsa-text-gray-500">Outcomes</dt>
<dt class="elsa-text-sm elsa-font-medium elsa-text-gray-500">
<span>Outcomes</span>
<elsa-copy-button value={outcomes.join(', ')}/>
</dt>
<dd class="elsa-mt-1 elsa-text-sm elsa-text-gray-900 elsa-mb-2">
<div
class="elsa-flex elsa-flex-col elsa-space-y-4 sm:elsa-space-y-0 sm:elsa-flex-row sm:elsa-space-x-4">
@ -252,7 +277,8 @@ export class ElsaWorkflowInstanceJournal {
{!!record.message && !exception ? (
<div class="sm:elsa-col-span-2">
<dt class="elsa-text-sm elsa-font-medium elsa-text-gray-500">
Message
<span>Message</span>
<elsa-copy-button value={record.message}/>
</dt>
<dd class="elsa-mt-1 elsa-text-sm elsa-text-gray-900">
{record.message}
@ -262,7 +288,8 @@ export class ElsaWorkflowInstanceJournal {
{!!exception ? (
[<div class="sm:elsa-col-span-2">
<dt class="elsa-text-sm elsa-font-medium elsa-text-gray-500">
Exception
<span>Exception</span>
<elsa-copy-button value={exception.Type + '\n' + exception.Message}/>
</dt>
<dd class="elsa-mt-1 elsa-text-sm elsa-text-gray-900">
{renderExceptionMessage(exception)}
@ -270,7 +297,8 @@ export class ElsaWorkflowInstanceJournal {
</div>,
<div class="sm:elsa-col-span-2">
<dt class="elsa-text-sm elsa-font-medium elsa-text-gray-500">
Exception Details
<span>Exception Details</span>
<elsa-copy-button value={JSON.stringify(exception, null, 1)}/>
</dt>
<dd class="elsa-mt-1 elsa-text-sm elsa-text-gray-900 elsa-overflow-x-auto">
<pre onClick={e => clip(e.currentTarget)}>{JSON.stringify(exception, null, 1)}</pre>
@ -279,7 +307,10 @@ export class ElsaWorkflowInstanceJournal {
) : undefined}
{collection.map(filteredRecordData, (v, k) => (
<div class="sm:elsa-col-span-2">
<dt class="elsa-text-sm elsa-font-medium elsa-text-gray-500 elsa-capitalize">{k}</dt>
<dt class="elsa-text-sm elsa-font-medium elsa-text-gray-500 elsa-capitalize">
<span>{k}</span>
<elsa-copy-button value={v}/>
</dt>
<dd class="elsa-mt-1 elsa-text-sm elsa-text-gray-900 elsa-mb-2 elsa-overflow-x-auto">
<pre onClick={e => clip(e.currentTarget)}>{v}</pre>
</dd>
@ -324,6 +355,7 @@ export class ElsaWorkflowInstanceJournal {
const {workflowInstance, workflowBlueprint} = this;
const {finishedAt, lastExecutedAt, faultedAt} = workflowInstance;
const format = 'DD-MM-YYYY HH:mm:ss';
const eventColor = this.getStatusColor(workflowInstance.workflowStatus);
return (
<dl class="elsa-border-b elsa-border-gray-200 elsa-divide-y elsa-divide-gray-200">
@ -349,7 +381,15 @@ export class ElsaWorkflowInstanceJournal {
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">Workflow Status</dt>
<dd class="elsa-text-gray-900 elsa-break-all">{workflowInstance.workflowStatus || '-'}</dd>
<dd class="elsa-text-gray-900 elsa-break-all">
<span class="elsa-relative elsa-inline-flex elsa-items-center elsa-rounded-full">
<span class="elsa-flex-shrink-0 elsa-flex elsa-items-center elsa-justify-center">
<span class={`elsa-w-2-5 elsa-h-2-5 elsa-rounded-full elsa-bg-${eventColor}-500`}
aria-hidden="true"/>
</span>
<span class="elsa-ml-3.5">{workflowInstance.workflowStatus || '-'}</span>
</span>
</dd>
</div>
<div class="elsa-py-3 elsa-flex elsa-justify-between elsa-text-sm elsa-font-medium">
<dt class="elsa-text-gray-500">Created</dt>

View file

@ -45,6 +45,8 @@ Type: `Promise<void>`
### Depends on
- [elsa-copy-button](../../../shared/elsa-copy-button)
- [elsa-workflow-definition-editor-notifications](../../workflow-definition-editor/elsa-workflow-definition-editor-notifications)
- [elsa-flyout-panel](../../../shared/elsa-flyout-panel)
- [elsa-tab-header](../../../shared/elsa-tab-header)
- [elsa-tab-content](../../../shared/elsa-tab-content)
@ -52,6 +54,8 @@ Type: `Promise<void>`
### Graph
```mermaid
graph TD;
elsa-workflow-instance-journal --> elsa-copy-button
elsa-workflow-instance-journal --> elsa-workflow-definition-editor-notifications
elsa-workflow-instance-journal --> elsa-flyout-panel
elsa-workflow-instance-journal --> elsa-tab-header
elsa-workflow-instance-journal --> elsa-tab-content

View file

@ -45,6 +45,8 @@ graph TD;
elsa-workflow-instance-viewer-screen --> elsa-workflow-instance-journal
elsa-workflow-instance-viewer-screen --> elsa-designer-tree
elsa-workflow-instance-viewer-screen --> context-consumer
elsa-workflow-instance-journal --> elsa-copy-button
elsa-workflow-instance-journal --> elsa-workflow-definition-editor-notifications
elsa-workflow-instance-journal --> elsa-flyout-panel
elsa-workflow-instance-journal --> elsa-tab-header
elsa-workflow-instance-journal --> elsa-tab-content

View file

@ -0,0 +1,40 @@
import {Component, h, Host, Prop} from '@stencil/core';
import {eventBus} from "../../../services";
import {EventTypes} from "../../../models";
@Component({
tag: 'elsa-copy-button',
shadow: false,
})
export class ElsaCopyButton {
@Prop() value: string;
render() {
return (
<Host class="elsa-align-text-top elsa-inline-block">
<button type="button" class="hover:elsa-text-blue-500 focus:elsa-text-green-600 elsa-pl-0.5" onClick={this.onCopyClick}>
<svg xmlns="http://www.w3.org/2000/svg" class="elsa-h-4 elsa-w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
</svg>
</button>
</Host>
);
}
onCopyClick = async (e) => {
e.stopPropagation();
this.checkClipboardPermissions();
await navigator.clipboard.writeText(this.value);
await eventBus.emit(EventTypes.ClipboardCopied, this, undefined, 'Data copied to clipboard.');
}
checkClipboardPermissions = () => {
navigator.permissions.query({name: 'clipboard-read'}).then((result) => {
if (result.state == 'denied')
eventBus.emit(EventTypes.ClipboardPermissionDenied, this);
});
}
}

View file

@ -0,0 +1,30 @@
# elsa-copy-button
<!-- Auto Generated Below -->
## Properties
| Property | Attribute | Description | Type | Default |
| -------- | --------- | ----------- | -------- | ----------- |
| `value` | `value` | | `string` | `undefined` |
## Dependencies
### Used by
- [elsa-workflow-instance-journal](../../screens/workflow-instance-viewer/elsa-workflow-instance-journal)
### Graph
```mermaid
graph TD;
elsa-workflow-instance-journal --> elsa-copy-button
style elsa-copy-button fill:#f9f,stroke:#333,stroke-width:4px
```
----------------------------------------------
*Built with [StencilJS](https://stenciljs.com/)*

View file

@ -33,20 +33,22 @@ export class ElsaFlyoutPanel {
render() {
const {expanded, expandButtonPosition} = this;
const expandPositionClass = expandButtonPosition == 1 ? "elsa-right-12" : "elsa-right-28";
const expandPositionClass = `elsa-right-${16 * (expandButtonPosition - 1) + 12}`;
console.log('eee', this.expanded);
return (
<Host>
<button type="button"
onClick={this.toggle}
class={`${expanded ? "hidden" : expandPositionClass} workflow-settings-button elsa-fixed elsa-top-20 elsa-inline-flex elsa-items-center elsa-p-2 elsa-rounded-full elsa-border elsa-border-transparent elsa-bg-white shadow elsa-text-gray-400 hover:elsa-text-blue-500 focus:elsa-text-blue-500 hover:elsa-ring-2 hover:elsa-ring-offset-2 hover:elsa-ring-blue-500 focus:elsa-outline-none focus:elsa-ring-2 focus:elsa-ring-offset-2 focus:elsa-ring-blue-500 elsa-z-10`}>
class={`${expanded ? "elsa-hidden" : expandPositionClass} workflow-settings-button elsa-fixed elsa-top-20 elsa-inline-flex elsa-items-center elsa-p-2 elsa-rounded-full elsa-border elsa-border-transparent elsa-bg-white shadow elsa-text-gray-400 hover:elsa-text-blue-500 focus:elsa-text-blue-500 hover:elsa-ring-2 hover:elsa-ring-offset-2 hover:elsa-ring-blue-500 focus:elsa-outline-none focus:elsa-ring-2 focus:elsa-ring-offset-2 focus:elsa-ring-blue-500 elsa-z-10`}>
<svg xmlns="http://www.w3.org/2000/svg" class="elsa-h-8 elsa-w-8" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 19l-7-7 7-7m8 14l-7-7 7-7"/>
</svg>
</button>
<section
class={`${this.expanded ? '' : 'hidden'} elsa-fixed elsa-top-4 elsa-right-0 elsa-bottom-0 elsa-overflow-hidden`}
class={`${this.expanded ? '' : 'elsa-hidden'} elsa-fixed elsa-top-4 elsa-right-0 elsa-bottom-0 elsa-overflow-hidden`}
aria-labelledby="slide-over-title" role="dialog" aria-modal="true">
<div class="elsa-absolute elsa-inset-0 elsa-overflow-hidden">
<div class="elsa-absolute elsa-inset-0" aria-hidden="true"/>
@ -60,7 +62,7 @@ export class ElsaFlyoutPanel {
data-transition-leave="elsa-transform elsa-transition elsa-ease-in-out elsa-duration-300 sm:elsa-duration-700"
data-transition-leave-start="elsa-translate-x-0"
data-transition-leave-end="elsa-translate-x-full"
class="elsa-w-screen elsa-max-w-lg elsa-h-full">
class="elsa-w-screen elsa-max-w-lg elsa-h-full ">
<button type="button"
onClick={this.toggle}
class="workflow-settings-button elsa-absolute elsa-top-4 elsa-left-2 elsa-inline-flex elsa-items-center elsa-p-2 elsa-rounded-full elsa-border elsa-border-transparent elsa-bg-white shadow elsa-text-gray-400 hover:elsa-text-blue-500 focus:elsa-text-blue-500 hover:elsa-ring-2 hover:elsa-ring-offset-2 hover:elsa-ring-blue-500 focus:elsa-outline-none focus:elsa-ring-2 focus:elsa-ring-offset-2 focus:elsa-ring-blue-500 elsa-z-10">
@ -71,20 +73,20 @@ export class ElsaFlyoutPanel {
</svg>
</button>
<div
class="elsa-h-full elsa-flex elsa-flex-col elsa-py-6 elsa-bg-white elsa-shadow-xl elsa-overflow-y-scroll elsa-bg-white">
<div class="elsa-h-full">
<div class="elsa-mt-8 elsa-p-6">
class="elsa-h-full elsa-flex elsa-flex-col elsa-py-6 elsa-bg-white elsa-shadow-xl elsa-bg-white">
<div class="elsa-h-full elsa-mt-8 elsa-p-6">
<div class="elsa-border-b elsa-border-gray-200">
<nav class="-elsa-mb-px elsa-flex elsa-space-x-8" aria-label="Tabs">
<slot name="header"/>
</nav>
</div>
<slot name="content" />
<section class="elsa-overflow-auto elsa-h-full">
<slot name="content"/>
</section>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</Host>

View file

@ -19,16 +19,21 @@ export class ElsaModalDialog {
}
@Method()
async show(animate: boolean) {
async show(animate: boolean = true) {
this.showInternal(animate);
}
@Method()
async hide(animate: boolean) {
async hide(animate: boolean = true) {
await eventBus.emit(EventTypes.HideModalDialog);
this.hideInternal(animate);
}
handleDefaultClose = async () => {
console.log('handleDefaultClose');
await this.hide();
}
showInternal(animate: boolean) {
this.isVisible = true;
@ -92,6 +97,7 @@ export class ElsaModalDialog {
<slot name="buttons">
<div class="elsa-bg-gray-50 elsa-px-4 elsa-py-3 sm:elsa-px-6 sm:elsa-flex sm:elsa-flex-row-reverse">
<button type="button"
onClick={this.handleDefaultClose}
class="elsa-mt-3 elsa-w-full elsa-inline-flex elsa-justify-center elsa-rounded-md elsa-border elsa-border-gray-300 elsa-shadow-sm elsa-px-4 elsa-py-2 elsa-bg-white elsa-text-base elsa-font-medium elsa-text-gray-700 hover:elsa-bg-gray-50 focus:elsa-outline-none focus:elsa-ring-2 focus:elsa-ring-offset-2 focus:elsa-ring-blue-500 sm:elsa-mt-0 sm:elsa-ml-3 sm:elsa-w-auto sm:elsa-text-sm">
Close
</button>

View file

@ -11,7 +11,7 @@ export class ElsaTabContent {
render() {
return (
<Host>
<div class={this.active ? '' : 'elsa-hidden'}>
<div class={`${this.active ? '' : 'elsa-hidden'} elsa-overflow-y-auto elsa-h-full`}>
<slot/>
</div>
</Host>

View file

@ -14,7 +14,7 @@ export class ElsaTabHeader {
return (
<Host>
<div class={`${className} elsa-whitespace-nowrap elsa-py-4 elsa-px-1 elsa-border-b-2 elsa-font-medium elsa-text-sm`}>
<div class={`${className} elsa-cursor-pointer elsa-whitespace-nowrap elsa-py-4 elsa-px-1 elsa-border-b-2 elsa-font-medium elsa-text-sm`}>
<slot />
</div>
</Host>

View file

@ -3935,10 +3935,6 @@ select {
top: 4rem;
}
.elsa-top-18 {
top: 4.5rem;
}
.elsa-top-20 {
top: 5rem;
}

View file

@ -1,17 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\core\Elsa.Core\Elsa.Core.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\common.props" />
<Import Project="..\..\..\..\configureawait.props" />
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Description>
Elsa Retention is an optional part of Elsa Workflows that adds retention settings to the system.
</Description>
<PackageTags>elsa, workflow settings</PackageTags>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\core\Elsa.Core\Elsa.Core.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait />
</Weavers>

View file

@ -31,7 +31,7 @@ namespace Elsa.Retention.Jobs
public async Task ExecuteAsync(CancellationToken cancellationToken = default)
{
var threshold = _clock.GetCurrentInstant().Minus(_options.TimeToLive);
var specification = new WorkflowCreatedBeforeSpecification(threshold);
var specification = new WorkflowCreatedBeforeSpecification(threshold).And(new WorkflowFinishedStatusSpecification());
var take = _options.PageSize;
IList<string> workflowInstanceIds;

View file

@ -9,7 +9,7 @@
Elsa Workflow Settings is an optional part of Elsa Workflows.
This package contains Workflow Settings.
</Description>
<PackageTags>elsa, workflow settings, orchard</PackageTags>
<PackageTags>elsa, workflow settings</PackageTags>
</PropertyGroup>
<ItemGroup>

View file

@ -36,7 +36,7 @@
<ProjectReference Include="..\..\..\locking\Elsa.DistributedLocking.AzureBlob\Elsa.DistributedLocking.AzureBlob.csproj" />
<ProjectReference Include="..\..\..\locking\Elsa.DistributedLocking.Redis\Elsa.DistributedLocking.Redis.csproj" />
<ProjectReference Include="..\..\..\locking\Elsa.DistributedLocking.SqlServer\Elsa.DistributedLocking.SqlServer.csproj" />
<ProjectReference Include="..\..\..\modules\Elsa.Retention\Elsa.Retention.csproj" />
<ProjectReference Include="..\..\..\modules\retention\Elsa.Retention\Elsa.Retention.csproj" />
<ProjectReference Include="..\..\..\modules\workflowsettings\Elsa.WorkflowSettings.Api\Elsa.WorkflowSettings.Api.csproj" />
<ProjectReference Include="..\..\..\modules\workflowsettings\Elsa.WorkflowSettings.Persistence.EntityFramework.MySql\Elsa.WorkflowSettings.Persistence.EntityFramework.MySql.csproj" />
<ProjectReference Include="..\..\..\modules\workflowsettings\Elsa.WorkflowSettings.Persistence.EntityFramework.PostgreSql\Elsa.WorkflowSettings.Persistence.EntityFramework.PostgreSql.csproj" />