Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/nested-editing-stories.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@openworkflowspec/diagram-editor": minor
---

add nested editing sample workflows
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const preview: Preview = {

options: {
storySort: {
order: ["Introduction", "Features", "Examples", "Use Cases"],
order: ["Introduction", "Features", "Examples", "Use Cases", "Nested Editing"],
},
},
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2021-Present The Open Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import type { Meta, StoryObj } from "@storybook/react-vite";
import { DiagramEditor } from "../features/DiagramEditor";
import * as workflows from "./index";

const meta = {
title: "Nested Editing/Workflows",
component: DiagramEditor,
parameters: {
layout: "fullscreen",
},
render: (args, { globals }) => {
return <DiagramEditor {...args} colorMode={args.colorMode ?? globals.colorMode ?? "system"} />;
},
} satisfies Meta<typeof DiagramEditor>;

export default meta;
type Story = StoryObj<typeof meta>;

const DEFAULT_STORY_ARGS = {
isReadOnly: false,
locale: "en" as const,
} as const;

const createWorkflowStory = (workflowContent: string): Story => ({
args: {
...DEFAULT_STORY_ARGS,
content: workflowContent,
},
});

export const AllTaskTypes: Story = createWorkflowStory(workflows.allTaskTypes);
export const CallEndpointUnion: Story = createWorkflowStory(workflows.callEndpointUnion);
export const CallHeadersMap: Story = createWorkflowStory(workflows.callHeadersMap);
export const ListenDeepNesting: Story = createWorkflowStory(workflows.listenDeepNesting);
export const NestedValidation: Story = createWorkflowStory(workflows.nestedValidation);
export const RunTaskArray: Story = createWorkflowStory(workflows.runTaskArray);
export const SetOpenMap: Story = createWorkflowStory(workflows.setOpenMap);
export const SwitchLockedCases: Story = {
args: {
...DEFAULT_STORY_ARGS,
isReadOnly: true,
content: workflows.switchLockedCases,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{/*
* Copyright 2021-Present The Open Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/}

import { Meta } from "@storybook/addon-docs/blocks";

<Meta title="Nested Editing/Overview" />

# Nested Editing

These stories provide isolated environments for building and testing the nested editing system.
Comment thread
cheryl7114 marked this conversation as resolved.
Each story targets a specific interaction pattern introduced by a particular task type or shape,
making it easy to develop, review, and regression-test editing behaviour without noise from unrelated features.

The **All Task Types** story includes all 12 task types (`call`, `set`, `run`, `wait`, `fork`, `listen`, `emit`, `for`, `try/catch`, `switch`, `do`, `raise`) in a single workflow, providing a reference for how each task appears in the diagram editor.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2021-Present The Open Workflow Specification Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export { default as allTaskTypes } from "./workflows/all-task-types.yaml?raw";
export { default as callEndpointUnion } from "./workflows/call-endpoint-union.yaml?raw";
export { default as callHeadersMap } from "./workflows/call-headers-map.yaml?raw";
export { default as listenDeepNesting } from "./workflows/listen-deep-nesting.yaml?raw";
export { default as nestedValidation } from "./workflows/nested-validation.yaml?raw";
export { default as runTaskArray } from "./workflows/run-task-array.yaml?raw";
export { default as setOpenMap } from "./workflows/set-open-map.yaml?raw";
export { default as switchLockedCases } from "./workflows/switch-locked-cases.yaml?raw";
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#
# Copyright 2021-Present The Open Workflow Specification Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
document:
dsl: "1.0.3"
namespace: examples
name: all-task-types
version: "0.1.0"
use:
errors:
notFound:
type: https://example.com/errors/not-found
status: 404
title: Resource Not Found
do:
Comment thread
cheryl7114 marked this conversation as resolved.
- callHttpTask:
call: http
with:
method: get
endpoint: https://api.example.com/users
headers:
Accept: application/json
X-Api-Key: ${ .apiKey }
query:
page: "1"
limit: "20"
- setContextTask:
set:
userId: ${ .users[0].id }
userName: ${ .users[0].name }
fetchedAt: ${ now }
meta:
source: api.example.com
version: v2
- runScriptTask:
run:
script:
language: javascript
arguments:
- --user-id
- ${ .userId }
environment:
NODE_ENV: production
code: |
const [,, flag, id] = process.argv;
console.log(JSON.stringify({ processed: id }));
- waitTask:
wait:
seconds: 5
- forkTask:
fork:
compete: false
branches:
- notifyEmail:
call: http
with:
method: post
endpoint: https://api.example.com/notifications/email
body:
userId: ${ .userId }
- notifySlack:
call: http
with:
method: post
endpoint: https://api.example.com/notifications/slack
body:
userId: ${ .userId }
- listenTask:
listen:
to:
any:
- with:
type: com.example.user.verified
correlate:
userId:
from: .subject
- with:
type: com.example.user.rejected
correlate:
userId:
from: .subject
- emitTask:
emit:
event:
with:
source: https://api.example.com
type: com.example.user.processed.v1
data:
userId: ${ .userId }
userName: ${ .userName }
- forTask:
for:
each: role
in: ${ .roles }
at: index
do:
- assignRole:
call: http
with:
method: post
endpoint: https://api.example.com/users/${ .userId }/roles
body:
role: ${ .role }
- tryTask:
try:
- fetchPreferences:
call: http
with:
method: get
endpoint: https://api.example.com/users/${ .userId }/preferences
catch:
errors:
with:
type: https://open-workflow-specification.org/spec/1.0.0/errors/communication
status: 404
as: error
do:
- setDefaultPreferences:
set:
preferences:
theme: default
language: en
- switchTask:
switch:
- verified:
when: ${ .eventType == "com.example.user.verified" }
then: doNestedTask
- rejected:
when: ${ .eventType == "com.example.user.rejected" }
then: raiseErrorTask
- default:
then: raiseErrorTask
- doNestedTask:
do:
- enrichProfile:
call: http
with:
method: get
endpoint: https://api.example.com/profile/${ .userId }
- storeProfile:
set:
profile: ${ .body }
enrichedAt: ${ now }
then: exit
- raiseErrorTask:
raise:
error: notFound
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#
# Copyright 2021-Present The Open Workflow Specification Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Nested editing focus: endpoint union — the endpoint field can be a plain string URI
# or a structured object with uri + authentication. Both forms appear here so the
# editor can be tested switching between union variants inside nested do containers.
document:
dsl: "1.0.3"
namespace: examples
name: call-endpoint-union
version: "0.1.0"
do:
- prepareRequest:
set:
serviceToken: ${ .auth.token }
inputData: ${ .payload }
- callServices:
do:
- callPublicApi:
call: http
with:
method: get
endpoint: https://public.api.example.com/catalogue
query:
category: ${ .category }
- callSecureApi:
call: http
with:
method: post
endpoint:
uri: https://secure.api.example.com/process
authentication:
bearer:
token: ${ .serviceToken }
body:
payload: ${ .inputData }
- callOAuthApi:
call: http
with:
method: get
endpoint:
uri: https://oauth.api.example.com/data
authentication:
oauth2:
authority: https://auth.example.com
grant: client_credentials
client:
id: ${ .clientId }
secret: ${ .clientSecret }
- mergeResults:
set:
catalogue: ${ .catalogue }
processed: ${ .processed }
data: ${ .data }
Loading