bpmn-io / bpmn-js-properties-panel

A properties panel for bpmn-js.
MIT License
292 stars 196 forks source link

IOMappings Order is not stable #897

Closed MaxTru closed 1 year ago

MaxTru commented 1 year ago

Describe the Bug

When using an element template which defines IOMappings, the order of the IOMappings is important. It needs to be ensured that a variable, which is used in a IOMapping, is defined first.

This is not the case at the moment.

The result is, that some complex element template configuration (required for good UX) will create non-functing XML (will fail on Zeebe when executed).

Steps to Reproduce

  1. Use this element template:
Element Template ```json { "$schema": "https://unpkg.com/@camunda/zeebe-element-templates-json-schema/resources/schema.json", "name": "GitLab Connector", "id": "io.camunda.connectors.GitLab.v1", "version": 1, "description": "Administer and work with issues and releases", "icon": { "contents": "data:image/svg+xml;utf8,%3Csvg width='18px' height='18px' viewBox='0 -10 256 256' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' preserveAspectRatio='xMidYMid'%3E%3Cg%3E%3Cpath d='M128.07485,236.074667 L128.07485,236.074667 L175.17885,91.1043048 L80.9708495,91.1043048 L128.07485,236.074667 L128.07485,236.074667 Z' fill='%23E24329'%3E%3C/path%3E%3Cpath d='M128.07485,236.074423 L80.9708495,91.104061 L14.9557638,91.104061 L128.07485,236.074423 L128.07485,236.074423 Z' fill='%23FC6D26'%3E%3C/path%3E%3Cpath d='M14.9558857,91.1044267 L14.9558857,91.1044267 L0.641828571,135.159589 C-0.663771429,139.17757 0.766171429,143.57955 4.18438095,146.06275 L128.074971,236.074789 L14.9558857,91.1044267 L14.9558857,91.1044267 Z' fill='%23FCA326'%3E%3C/path%3E%3Cpath d='M14.9558857,91.1045486 L80.9709714,91.1045486 L52.6000762,3.79026286 C51.1408762,-0.703146667 44.7847619,-0.701927619 43.3255619,3.79026286 L14.9558857,91.1045486 L14.9558857,91.1045486 Z' fill='%23E24329'%3E%3C/path%3E%3Cpath d='M128.07485,236.074423 L175.17885,91.104061 L241.193935,91.104061 L128.07485,236.074423 L128.07485,236.074423 Z' fill='%23FC6D26'%3E%3C/path%3E%3Cpath d='M241.193935,91.1044267 L241.193935,91.1044267 L255.507992,135.159589 C256.813592,139.17757 255.38365,143.57955 251.96544,146.06275 L128.07485,236.074789 L241.193935,91.1044267 L241.193935,91.1044267 Z' fill='%23FCA326'%3E%3C/path%3E%3Cpath d='M241.193935,91.1045486 L175.17885,91.1045486 L203.549745,3.79026286 C205.008945,-0.703146667 211.365059,-0.701927619 212.824259,3.79026286 L241.193935,91.1045486 L241.193935,91.1045486 Z' fill='%23E24329'%3E%3C/path%3E%3C/g%3E%3C/svg%3E" }, "category": { "id": "connectors", "name": "Connectors" }, "appliesTo": [ "bpmn:Task" ], "elementType": { "value": "bpmn:ServiceTask" }, "groups": [ { "id": "endpoint", "label": "HTTP Endpoint" }, { "id": "operation", "label": "Operation" }, { "id": "output", "label": "Response Mapping" }, { "id": "errors", "label": "Error Handling" } ], "properties": [ { "type": "Hidden", "value": "io.camunda:http-json:1", "binding": { "type": "zeebe:taskDefinition:type" } }, { "group": "authentication", "type": "Hidden", "value": "noAuth", "binding": { "type": "zeebe:input", "name": "authentication.type" } }, { "label": "GitLab base URL", "group": "endpoint", "type": "String", "value": "https://gitlab.example.com", "feel": "optional", "binding": { "type": "zeebe:input", "name": "baseUrl" }, "constraints": { "notEmpty": true, "pattern": { "value": "^(=|http://|https://|secrets).*$", "message": "Must be a http(s) URL." } } }, { "label": "GitLab access token", "group": "endpoint", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "gitlabAccessToken" }, "constraints": { "notEmpty": true } }, { "type": "Hidden", "value": "={\"PRIVATE-TOKEN\":gitlabAccessToken, \"Content-Type\":\"application/json\"}", "binding": { "type": "zeebe:input", "name": "headers" }, "constraints": { "notEmpty": true } }, { "label": "Operation group", "id": "operationGroup", "group": "operation", "description": "Choose operation group", "type": "Dropdown", "choices": [ { "name": "Issues", "value": "issues" }, { "name": "Releases", "value": "releases" } ], "binding": { "type": "zeebe:input", "name": "operationGroup" } }, { "label": "Operation", "id": "operation", "group": "operation", "description": "Choose operation to perform", "type": "Dropdown", "choices": [ { "name": "Get an issue by ID", "value": "getIssueById" }, { "name": "Create an issue", "value": "createAnIssue" }, { "name": "Delete an issue", "value": "deleteAnIssue" }, { "name": "Comment to an issue", "value": "commentToAnIssue" }, { "name": "Search issues", "value": "searchIssues" } ], "binding": { "type": "zeebe:input", "name": "operation" }, "condition": { "property": "operationGroup", "equals": "issues" } }, { "label": "Operation", "id": "operation", "group": "operation", "description": "Choose operation to perform", "type": "Dropdown", "choices": [ { "name": "List all releases by project ID", "value": "getReleasesByProjectId" }, { "name": "Get release by a tag name", "value": "getReleaseByTagName" }, { "name": "Create a release", "value": "createRelease" } ], "binding": { "type": "zeebe:input", "name": "operation" }, "condition": { "property": "operationGroup", "equals": "releases" } }, { "type": "Hidden", "value": "get", "binding": { "type": "zeebe:input", "name": "method" }, "condition": { "property": "operation", "oneOf": [ "getIssueById", "searchIssues", "getReleasesByProjectId", "getReleaseByTagName" ] } }, { "type": "Hidden", "value": "post", "binding": { "type": "zeebe:input", "name": "method" }, "condition": { "property": "operation", "oneOf": [ "commentToAnIssue", "createAnIssue", "createRelease" ] } }, { "type": "Hidden", "value": "delete", "binding": { "type": "zeebe:input", "name": "method" }, "condition": { "property": "operation", "oneOf": [ "deleteAnIssue" ] } }, { "label": "Project ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "projectId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "getIssueById" ] } }, { "label": "Issue ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "issueId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "getIssueById" ] } }, { "type": "Hidden", "value": "=baseUrl + \"/api/v4/projects/\"+ projectId +\"/issues/\" + issueId", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "getIssueById" ] } }, { "label": "Project ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "projectId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "createAnIssue" ] } }, { "label": "Title", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "issueTitle" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "createAnIssue" ] } }, { "label": "Description", "group": "operation", "type": "Text", "feel": "optional", "binding": { "type": "zeebe:input", "name": "issueDescription" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "createAnIssue" ] } }, { "type": "Hidden", "value": "=baseUrl + \"/api/v4/projects/\"+ projectId +\"/issues\"", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "createAnIssue" ] } }, { "type": "Hidden", "value": "={\"title\":issueTitle, \"description\":issueDescription}", "binding": { "type": "zeebe:input", "name": "queryParameters" }, "condition": { "property": "operation", "oneOf": [ "createAnIssue" ] } }, { "label": "Project ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "projectId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "deleteAnIssue" ] } }, { "label": "Issue ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "issueId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "deleteAnIssue" ] } }, { "type": "Hidden", "value": "=baseUrl + \"/api/v4/projects/\"+ projectId +\"/issues/\" + issueId", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "deleteAnIssue" ] } }, { "label": "Project ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "projectId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "commentToAnIssue" ] } }, { "label": "Issue ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "issueId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "commentToAnIssue" ] } }, { "label": "Note text", "group": "operation", "type": "Text", "feel": "optional", "binding": { "type": "zeebe:input", "name": "commentBody" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "commentToAnIssue" ] } }, { "label": "Level on confidentiality", "group": "operation", "description": "Define whether issue is confidential", "type": "Dropdown", "value": "false", "choices": [ { "name": "Confidential", "value": "true" }, { "name": "Non-confidential", "value": "false" } ], "binding": { "type": "zeebe:input", "name": "issueIsConfidential" }, "condition": { "property": "operation", "oneOf": [ "commentToAnIssue" ] } }, { "type": "Hidden", "value": "={\"body\":commentBody, \"confidential\":issueIsConfidential}", "binding": { "type": "zeebe:input", "name": "queryParameters" }, "condition": { "property": "operation", "oneOf": [ "commentToAnIssue" ] } }, { "type": "Hidden", "value": "=baseUrl + \"/api/v4/projects/\"+ projectId +\"/issues/\" + issueId + \"notes\"", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "commentToAnIssue" ] } }, { "label": "Scope", "group": "operation", "type": "Dropdown", "optional": true, "value": "all", "choices": [ { "name": "All", "value": "all" }, { "name": "Created by access token owner", "value": "created_by_me" }, { "name": "Assigned by access token owner", "value": "assigned_to_me" } ], "binding": { "type": "zeebe:input", "name": "searchIssueScope" }, "condition": { "property": "operation", "oneOf": [ "searchIssues" ] } }, { "label": "State", "group": "operation", "type": "Dropdown", "value": "all", "optional": true, "choices": [ { "name": "All", "value": "all" }, { "name": "Opened", "value": "opened" }, { "name": "Closed", "value": "closed" } ], "binding": { "type": "zeebe:input", "name": "searchIssueState" }, "condition": { "property": "operation", "oneOf": [ "searchIssues" ] } }, { "label": "Assignee ID", "group": "operation", "type": "String", "feel": "optional", "optional": true, "binding": { "type": "zeebe:input", "name": "searchIssueAssigneeId" }, "condition": { "property": "operation", "oneOf": [ "searchIssues" ] } }, { "label": "Assignee username", "group": "operation", "type": "String", "feel": "optional", "optional": true, "binding": { "type": "zeebe:input", "name": "searchIssueAssigneeUsername" }, "condition": { "property": "operation", "oneOf": [ "searchIssues" ] } }, { "label": "Author ID", "group": "operation", "type": "String", "feel": "optional", "optional": true, "binding": { "type": "zeebe:input", "name": "searchIssueAuthorId" }, "condition": { "property": "operation", "oneOf": [ "searchIssues" ] } }, { "label": "Contains text", "group": "operation", "type": "String", "feel": "optional", "optional": true, "binding": { "type": "zeebe:input", "name": "searchIssueSearch" }, "condition": { "property": "operation", "oneOf": [ "searchIssues" ] } }, { "type": "Hidden", "value": "={\"state\":if searchIssueState = null then null else searchIssueState, \"scope\": if searchIssueScope = null then null else searchIssueScope, \"assignee_id\": if searchIssueAssigneeId = null then null else searchIssueAssigneeId, \"assignee_username\": if searchIssueAssigneeUsername = null then null else searchIssueAssigneeUsername, \"author_id\": if searchIssueAuthorId = null then null else searchIssueAuthorId, \"search\": if searchIssueSearch = null then null else searchIssueSearch}", "binding": { "type": "zeebe:input", "name": "queryParameters" }, "condition": { "property": "operation", "oneOf": [ "searchIssues" ] } }, { "type": "Hidden", "value": "=baseUrl + \"/api/v4/issues\"", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "searchIssues" ] } }, { "label": "Project ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "projectId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "getReleasesByProjectId" ] } }, { "type": "Hidden", "value": "=baseUrl + \"/api/v4/projects/\"+ projectId +\"/releases\"", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "getReleasesByProjectId" ] } }, { "label": "Project ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "projectId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "getReleaseByTagName" ] } }, { "label": "Tag name", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "releaseTagName" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "getReleaseByTagName" ] } }, { "type": "Hidden", "value": "=baseUrl + \"/api/v4/projects/\"+ projectId +\"/releases/\" + releaseTagName", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "getReleaseByTagName" ] } }, { "label": "Project ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "projectId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "createRelease" ] } }, { "label": "Tag name", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "releaseTagName" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "createRelease" ] } }, { "label": "Ref", "description": "Commit or branch name to create release from", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "releaseRef" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "createRelease" ] } }, { "label": "Release name", "group": "operation", "type": "String", "feel": "optional", "optional": true, "binding": { "type": "zeebe:input", "name": "releaseName" }, "condition": { "property": "operation", "oneOf": [ "createRelease" ] } }, { "label": "Description", "group": "operation", "type": "Text", "feel": "optional", "optional": true, "binding": { "type": "zeebe:input", "name": "releaseDescription" }, "condition": { "property": "operation", "oneOf": [ "createRelease" ] } }, { "type": "Hidden", "value": "=baseUrl + \"/api/v4/projects/\"+ projectId +\"/releases\"", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "createRelease" ] } }, { "type": "Hidden", "value": "={\"tag_name\": if releaseTagName = null then null else releaseTagName, \"name\": if releaseName = null then null else releaseName, \"description\": if releaseDescription = null then releaseDescription else releaseDescription, \"ref\": if releaseRef = null then null else releaseRef}", "binding": { "type": "zeebe:input", "name": "body" }, "condition": { "property": "operation", "oneOf": [ "createRelease" ] } }, { "label": "Result Variable", "description": "Name of variable to store the response in. Details in the documentation", "group": "output", "type": "String", "binding": { "type": "zeebe:taskHeader", "key": "resultVariable" } }, { "label": "Result Expression", "description": "Expression to map the response into process variables. Details in the documentation", "group": "output", "type": "Text", "feel": "required", "binding": { "type": "zeebe:taskHeader", "key": "resultExpression" } }, { "label": "Error Expression", "description": "Expression to handle errors. Details in the documentation", "group": "errors", "type": "Text", "feel": "required", "binding": { "type": "zeebe:taskHeader", "key": "errorExpression" } } ] } ```
  1. Apply the element template to a service task
  2. Configure the "comment to an issue" operation. Example: Bildschirmfoto 2023-03-23 um 10 44 16
  3. Check the resulting IOMapping:
        <zeebe:ioMapping>
          <zeebe:input source="noAuth" target="authentication.type" />
          <zeebe:input source="https://gitlab.example.com" target="baseUrl" />
          <zeebe:input source="myToken" target="gitlabAccessToken" />
          <zeebe:input source="={&#34;PRIVATE-TOKEN&#34;:gitlabAccessToken, &#34;Content-Type&#34;:&#34;application/json&#34;}" target="headers" />
          <zeebe:input source="issues" target="operationGroup" />
          <zeebe:input source="commentToAnIssue" target="operation" />
          <zeebe:input source="post" target="method" />
          <zeebe:input source="asdf1" target="projectId" />
          <zeebe:input source="asdf2" target="issueId" />
          <zeebe:input source="=baseUrl + &#34;/api/v4/projects/&#34;+ projectId +&#34;/issues/&#34; + issueId + &#34;notes&#34;" target="url" />
          <zeebe:input source="={&#34;body&#34;:commentBody, &#34;confidential&#34;:issueIsConfidential}" target="queryParameters" />
          <zeebe:input source="asdf3" target="commentBody" />
          <zeebe:input source="false" target="issueIsConfidential" />
        </zeebe:ioMapping>

Notice the bug:

Expected Behavior

IOMappings that are defined first as part of the element template will also land first as part of the resulting IOMapping

Environment

Camunda Modeler 5.9.0

Other context

nikku commented 1 year ago

Thanks for reporting! Moving to ready for further investigation.

Given the time we already spent on fixing (and asserting) the correct behavior this seems very odd :see_no_evil:.

MaxTru commented 1 year ago

Given the time we already spent on fixing (and asserting) the correct behavior this seems very odd 🙈.

I agree. Maybe I also overlooked something. Would be great if a bpmn-io export could validate my evaluation.

igpetrov commented 1 year ago

Another similar example.

UPD: Reproducible in web, and desktop modeler

Full template ``` { "$schema": "https://unpkg.com/@camunda/zeebe-element-templates-json-schema/resources/schema.json", "name": "UIPath Connector", "id": "io.camunda.connectors.Asana.v1", "version": 1, "description": "Manage your Asana project with Camunda", "icon": { "contents": "data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='781.361 0 944.893 873.377'%3E%3CradialGradient id='a' cx='943.992' cy='1221.416' r='.663' gradientTransform='matrix(944.8934 0 0 -873.3772 -890717.875 1067234.75)' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0' stop-color='%23ffb900'/%3E%3Cstop offset='.6' stop-color='%23f95d8f'/%3E%3Cstop offset='.999' stop-color='%23f95353'/%3E%3C/radialGradient%3E%3Cpath fill='url(%23a)' d='M1520.766 462.371c-113.508 0-205.508 92-205.508 205.488 0 113.499 92 205.518 205.508 205.518 113.489 0 205.488-92.019 205.488-205.518 0-113.488-91.999-205.488-205.488-205.488zm-533.907.01c-113.489.01-205.498 91.99-205.498 205.488 0 113.489 92.009 205.498 205.498 205.498 113.498 0 205.508-92.009 205.508-205.498 0-113.499-92.01-205.488-205.518-205.488h.01zm472.447-256.883c0 113.489-91.999 205.518-205.488 205.518-113.508 0-205.508-92.029-205.508-205.518S1140.31 0 1253.817 0c113.489 0 205.479 92.009 205.479 205.498h.01z'/%3E%3C/svg%3E" }, "documentationRef": "https://docs.camunda.io/docs/components/connectors/out-of-the-box-connectors/asana/", "category": { "id": "connectors", "name": "Connectors" }, "appliesTo": [ "bpmn:Task" ], "elementType": { "value": "bpmn:ServiceTask" }, "groups": [ { "id": "operation", "label": "Operation" }, { "id": "authentication", "label": "Authentication" }, { "id": "operation", "label": "Operation" }, { "id": "output", "label": "Output" }, { "id": "errors", "label": "Error Handling" } ], "properties": [ { "type": "Hidden", "value": "io.camunda:http-json:1", "binding": { "type": "zeebe:taskDefinition:type" } }, { "type": "Hidden", "value": "bearer", "binding": { "type": "zeebe:input", "name": "authentication.type" } }, { "label": "Personal access token", "group": "authentication", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "authentication.token" }, "constraints": { "notEmpty": true } }, { "type": "Hidden", "value": "https://app.asana.com", "binding": { "type": "zeebe:input", "name": "asanaBaseUrl" } }, { "label": "Operation group", "id": "operationGroup", "group": "operation", "description": "Choose operation group", "type": "Dropdown", "choices": [ { "name": "Tasks", "value": "tasks" }, { "name": "Projects", "value": "projects" } ], "binding": { "type": "zeebe:input", "name": "operationGroup" } }, { "label": "Operation", "id": "operation", "group": "operation", "description": "Choose operation to perform", "type": "Dropdown", "choices": [ { "name": "Get tasks from a project", "value": "getTasksFromProject" }, { "name": "Get a task by ID", "value": "getTaskById" }, { "name": "Create a task", "value": "createTask" }, { "name": "Delete a task", "value": "deleteTask" } ], "binding": { "type": "zeebe:input", "name": "operation" }, "condition": { "property": "operationGroup", "equals": "tasks" } }, { "label": "Operation", "id": "operation", "group": "operation", "description": "Choose operation to perform", "type": "Dropdown", "choices": [ { "name": "Get projects", "value": "getProjects" }, { "name": "Get a project by ID", "value": "getProjectById" }, { "name": "Create a project in a workspace", "value": "createProjectInWorkspace" }, { "name": "Delete a project", "value": "deleteProject" } ], "binding": { "type": "zeebe:input", "name": "operation" }, "condition": { "property": "operationGroup", "equals": "projects" } }, { "type": "Hidden", "value": "get", "binding": { "type": "zeebe:input", "name": "method" }, "condition": { "property": "operation", "oneOf": [ "getTasksFromProject", "getTaskById", "getProjects", "getProjectById" ] } }, { "type": "Hidden", "value": "post", "binding": { "type": "zeebe:input", "name": "method" }, "condition": { "property": "operation", "oneOf": [ "createTask", "createProject" ] } }, { "type": "Hidden", "value": "delete", "binding": { "type": "zeebe:input", "name": "method" }, "condition": { "property": "operation", "oneOf": [ "deleteTask", "deleteProject" ] } }, { "label": "Project ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "projectId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "getTasksFromProject" ] } }, { "type": "Hidden", "value": "=asanaBaseUrl + \"/api/1.0/tasks\"", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "getTasksFromProject" ] } }, { "type": "Hidden", "value": "={\"project\":projectId}", "binding": { "type": "zeebe:input", "name": "queryParameters" }, "condition": { "property": "operation", "oneOf": [ "getTasksFromProject" ] } }, { "label": "Task ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "taskId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "getTaskById" ] } }, { "type": "Hidden", "value": "=asanaBaseUrl + \"/api/1.0/tasks/\" + taskId", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "getTaskById" ] } }, { "label": "Task ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "taskId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "deleteTask" ] } }, { "type": "Hidden", "value": "=asanaBaseUrl + \"/api/1.0/tasks/\" + taskId", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "deleteTask" ] } }, { "label": "Task name", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "taskName" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "createTask" ] } }, { "label": "Project ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "projectId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "createTask" ] } }, { "label": "Parent task ID", "group": "operation", "type": "String", "feel": "optional", "optional": true, "binding": { "type": "zeebe:input", "name": "parentTaskId" }, "condition": { "property": "operation", "oneOf": [ "createTask" ] } }, { "label": "Notes", "group": "operation", "type": "String", "feel": "optional", "optional": true, "binding": { "type": "zeebe:input", "name": "taskNotes" }, "condition": { "property": "operation", "oneOf": [ "createTask" ] } }, { "type": "Hidden", "value": "=asanaBaseUrl + \"/api/1.0/tasks/\"", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "createTask" ] } }, { "type": "Hidden", "value": "={\"data\":{\"projects\":[ projectId ], \"name\": taskName, \"parent\": if parentTaskId = null then null else parentTaskId, \"notes\": if taskNotes = null then null else taskNotes }}", "binding": { "type": "zeebe:input", "name": "body" }, "condition": { "property": "operation", "oneOf": [ "createTask" ] } }, { "label": "Workspace ID", "group": "operation", "type": "String", "feel": "optional", "optional": true, "binding": { "type": "zeebe:input", "name": "workspaceId" }, "condition": { "property": "operation", "oneOf": [ "getProjects" ] } }, { "label": "Team ID", "group": "operation", "type": "String", "feel": "optional", "optional": true, "binding": { "type": "zeebe:input", "name": "teamId" }, "condition": { "property": "operation", "oneOf": [ "getProjects" ] } }, { "type": "Hidden", "value": "=asanaBaseUrl + \"/api/1.0/projects\"", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "getProjects" ] } }, { "type": "Hidden", "value": "={\"workspace\":if workspaceId = null then null else workspaceId, \"team\":if teamId = null then null else teamId}", "binding": { "type": "zeebe:input", "name": "queryParameters" }, "condition": { "property": "operation", "oneOf": [ "getProjects" ] } }, { "label": "Project ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "projectId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "getProjectById" ] } }, { "type": "Hidden", "value": "=asanaBaseUrl + \"/api/1.0/projects/\" + projectId", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "getProjectById" ] } }, { "label": "Workspace ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "workspaceId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "createProjectInWorkspace" ] } }, { "label": "Project name", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "projectName" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "createProjectInWorkspace" ] } }, { "label": "Project note", "group": "operation", "type": "String", "feel": "optional", "optional": true, "binding": { "type": "zeebe:input", "name": "projectNote" }, "condition": { "property": "operation", "oneOf": [ "createProjectInWorkspace" ] } }, { "type": "Hidden", "value": "=asanaBaseUrl + \"/api/1.0/workspaces/\" + workspaceId + \"/projects\"", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "createProjectInWorkspace" ] } }, { "type": "Hidden", "value": "={\"data\":{\"name\": projectName,\"notes\": if projectNote = null then null else projectNote }}", "binding": { "type": "zeebe:input", "name": "body" }, "condition": { "property": "operation", "oneOf": [ "createProjectInWorkspace" ] } }, { "label": "Project ID", "group": "operation", "type": "String", "feel": "optional", "binding": { "type": "zeebe:input", "name": "projectId" }, "constraints": { "notEmpty": true }, "condition": { "property": "operation", "oneOf": [ "deleteProject" ] } }, { "type": "Hidden", "value": "=asanaBaseUrl + \"/api/1.0/projects/\" + projectId", "binding": { "type": "zeebe:input", "name": "url" }, "condition": { "property": "operation", "oneOf": [ "deleteProject" ] } }, { "label": "Result Variable", "description": "Name of variable to store the response in. Details in the documentation", "group": "output", "type": "String", "binding": { "type": "zeebe:taskHeader", "key": "resultVariable" } }, { "label": "Result Expression", "description": "Expression to map the response into process variables. Details in the documentation", "group": "output", "type": "Text", "feel": "required", "binding": { "type": "zeebe:taskHeader", "key": "resultExpression" } }, { "label": "Error Expression", "description": "Expression to handle errors. Details in the documentation", "group": "errors", "type": "Text", "feel": "required", "binding": { "type": "zeebe:taskHeader", "key": "errorExpression" } } ] } ```

Consider the following (lines 261-293):

{
      "label": "Task ID",
      "group": "operation",
      "type": "String",
      "feel": "optional",
      "binding": {
        "type": "zeebe:input",
        "name": "taskId"
      },
      "constraints": {
        "notEmpty": true
      },
      "condition": {
        "property": "operation",
        "oneOf": [
          "getTaskById"
        ]
      }
    },
    {
      "type": "Hidden",
      "value": "=asanaBaseUrl + \"/api/1.0/tasks/\" + taskId",
      "binding": {
        "type": "zeebe:input",
        "name": "url"
      },
      "condition": {
        "property": "operation",
        "oneOf": [
          "getTaskById"
        ]
      }
    },

Also produces the reverse order between taskId and url. Changing names didn't help.

<zeebe:ioMapping>
          <zeebe:input source="bearer" target="authentication.type" />
          <zeebe:input target="authentication.token" />
          <zeebe:input source="https://app.asana.com" target="asanaBaseUrl" />
          <zeebe:input source="tasks" target="operationGroup" />
          <zeebe:input source="getTaskById" target="operation" />
          <zeebe:input source="get" target="method" />
          <zeebe:input source="=asanaBaseUrl + &#34;/api/1.0/tasks/&#34; + taskId" target="url" />
          <zeebe:input target="taskId" />
</zeebe:ioMapping>
smbea commented 1 year ago

Root cause:

I believe the problem with our initial fix for https://github.com/bpmn-io/bpmn-js-properties-panel/issues/838 is that we didn't properly handle conditions.

When sorting, we retrieve the index of the property in the template by comparing the property binding: https://github.com/bpmn-io/bpmn-js-properties-panel/blob/4d12d3d9881d64bd5cab137f0c089c14d3859d42/src/provider/cloud-element-templates/UpdateTemplatePropertiesOrder.js#L112

But by doing this, we neglected that there can be properties with same binding but different conditions.

For the example in the description, we have two properties with binding { "type": "zeebe:input", "name": "queryParameters" }, but they have different conditions. In this case, the findIndex returns the first property with that binding regardless if it's the one activated or not.

I’m assuming that we can filter the template by the applied conditions before re-sorting and that should fix this.