Merge branch 'main' of github.com:sartography/spiff-arena

This commit is contained in:
jasquat 2023-01-25 14:36:05 -05:00
commit 1702521ccb
13 changed files with 54 additions and 3850 deletions

View File

@ -1,23 +1,16 @@
version: "3.8"
services:
spiffworkflow-db:
container_name: spiffworkflow-db
image: mysql:8.0.29
platform: linux/amd64
cap_add:
- SYS_NICE
restart: "no"
spiffworkflow-frontend:
container_name: spiffworkflow-frontend
image: ghcr.io/sartography/spiffworkflow-frontend:latest
depends_on:
spiffworkflow-backend:
condition: service_healthy
environment:
- MYSQL_DATABASE=spiffworkflow_backend_development
- MYSQL_ROOT_PASSWORD=my-secret-pw
- MYSQL_TCP_PORT=8003
APPLICATION_ROOT: "/"
PORT0: "${SPIFF_FRONTEND_PORT:-8001}"
ports:
- "8003"
healthcheck:
test: mysql --user=root --password=my-secret-pw -e 'select 1' spiffworkflow_backend_development
interval: 10s
timeout: 5s
retries: 10
- "${SPIFF_FRONTEND_PORT:-8001}:${SPIFF_FRONTEND_PORT:-8001}/tcp"
spiffworkflow-backend:
container_name: spiffworkflow-backend
@ -26,58 +19,69 @@ services:
spiffworkflow-db:
condition: service_healthy
environment:
- APPLICATION_ROOT=/
- SPIFFWORKFLOW_BACKEND_ENV=development
- FLASK_DEBUG=0
- FLASK_SESSION_SECRET_KEY=super_secret_key
- OPEN_ID_SERVER_URL=http://localhost:8000/openid
- SPIFFWORKFLOW_FRONTEND_URL=http://localhost:8001
- SPIFFWORKFLOW_BACKEND_URL=http://localhost:8000
- SPIFFWORKFLOW_BACKEND_PORT=8000
- SPIFFWORKFLOW_BACKEND_UPGRADE_DB=true
- SPIFFWORKFLOW_BACKEND_DATABASE_URI=mysql+mysqlconnector://root:my-secret-pw@spiffworkflow-db:8003/spiffworkflow_backend_development
- BPMN_SPEC_ABSOLUTE_DIR=/app/process_models
- SPIFFWORKFLOW_BACKEND_LOAD_FIXTURE_DATA=false
- SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME=example.yml
- RUN_BACKGROUND_SCHEDULER=true
- OPEN_ID_CLIENT_ID=spiffworkflow-backend
- OPEN_ID_CLIENT_SECRET_KEY=my_open_id_secret_key
APPLICATION_ROOT: "/"
SPIFFWORKFLOW_BACKEND_ENV: "development"
FLASK_DEBUG: "0"
FLASK_SESSION_SECRET_KEY: "${FLASK_SESSION_SECRET_KEY:-super_secret_key}"
OPEN_ID_SERVER_URL: "http://localhost:${SPIFF_BACKEND_PORT:-8000}/openid"
SPIFFWORKFLOW_FRONTEND_URL: "http://localhost:${SPIFF_FRONTEND_PORT:-8001}"
# WARNING: Frontend is a static site which assumes frontend port - 1 on localhost.
SPIFFWORKFLOW_BACKEND_URL: "http://localhost:${SPIFF_BACKEND_PORT:-8000}"
SPIFFWORKFLOW_BACKEND_PORT: "${SPIFF_BACKEND_PORT:-8000}"
SPIFFWORKFLOW_BACKEND_UPGRADE_DB: "true"
SPIFFWORKFLOW_BACKEND_DATABASE_URI: "mysql+mysqlconnector://root:${SPIFF_MYSQL_PASS:-my-secret-pw}@spiffworkflow-db:${SPIFF_MYSQL_PORT:-8003}/spiffworkflow_backend_development"
BPMN_SPEC_ABSOLUTE_DIR: "/app/process_models"
SPIFFWORKFLOW_BACKEND_LOAD_FIXTURE_DATA: "false"
SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_NAME: "example.yml"
RUN_BACKGROUND_SCHEDULER: "true"
OPEN_ID_CLIENT_ID: "spiffworkflow-backend"
OPEN_ID_CLIENT_SECRET_KEY: "my_open_id_secret_key"
ports:
- "8000:8000"
- "${SPIFF_BACKEND_PORT:-8000}:${SPIFF_BACKEND_PORT:-8000}/tcp"
volumes:
- ./process_models:/app/process_models
- ./log:/app/log
healthcheck:
test: curl localhost:8000/v1.0/status --fail
test: "curl localhost:${SPIFF_BACKEND_PORT:-8000}/v1.0/status --fail"
interval: 10s
timeout: 5s
retries: 20
spiffworkflow-frontend:
container_name: spiffworkflow-frontend
image: ghcr.io/sartography/spiffworkflow-frontend
environment:
- APPLICATION_ROOT=/
- PORT0=8001
ports:
- "8001:8001"
spiffworkflow-connector:
container_name: spiffworkflow-connector
image: ghcr.io/sartography/connector-proxy-demo
image: ghcr.io/sartography/connector-proxy-demo:latest
environment:
- FLASK_ENV=${FLASK_ENV:-development}
- FLASK_DEBUG=0
- FLASK_SESSION_SECRET_KEY=${FLASK_SESSION_SECRET_KEY:-super_secret_key}
- CONNECTOR_PROXY_PORT=8004
FLASK_ENV: "${FLASK_ENV:-development}"
FLASK_DEBUG: "0"
FLASK_SESSION_SECRET_KEY: "${FLASK_SESSION_SECRET_KEY:-super_secret_key}"
CONNECTOR_PROXY_PORT: "${SPIFF_CONNECTOR_PORT:-8004}"
ports:
- "8004:8004"
- "${SPIFF_CONNECTOR_PORT:-8004}:${SPIFF_CONNECTOR_PORT:-8004}/tcp"
healthcheck:
test: curl localhost:8004/liveness --fail
test: "curl localhost:${SPIFF_CONNECTOR_PORT:-8004}/liveness --fail"
interval: 10s
timeout: 5s
retries: 20
spiffworkflow-db:
container_name: spiffworkflow-db
image: mysql:8.0.29
platform: linux/amd64
cap_add:
- SYS_NICE
restart: "no"
environment:
MYSQL_DATABASE: "spiffworkflow_backend_development"
MYSQL_ROOT_PASSWORD: "${SPIFF_MYSQL_PASS:-my-secret-pw}"
MYSQL_TCP_PORT: "${SPIFF_MYSQL_PORT:-8003}"
ports:
- "${SPIFF_MYSQL_PORT:-8003}:${SPIFF_MYSQL_PORT:-8003}/tcp"
healthcheck:
test: "mysql --user=root --password=${SPIFF_MYSQL_PASS:-my-secret-pw} -e 'select 1' spiffworkflow_backend_development"
interval: 10s
timeout: 5s
retries: 10
volumes:
spiffworkflow_backend:

View File

@ -19,7 +19,6 @@ from spiffworkflow_backend.exceptions.api_error import api_error_blueprint
from spiffworkflow_backend.helpers.api_version import V1_API_PATH_PREFIX
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import migrate
from spiffworkflow_backend.routes.admin_blueprint.admin_blueprint import admin_blueprint
from spiffworkflow_backend.routes.openid_blueprint.openid_blueprint import (
openid_blueprint,
)
@ -106,7 +105,6 @@ def create_app() -> flask.app.Flask:
app.register_blueprint(user_blueprint)
app.register_blueprint(api_error_blueprint)
app.register_blueprint(admin_blueprint, url_prefix="/admin")
app.register_blueprint(openid_blueprint, url_prefix="/openid")
# preflight options requests will be allowed if they meet the requirements of the url regex.

View File

@ -1,187 +0,0 @@
"""APIs for dealing with process groups, process models, and process instances."""
from typing import Union
from flask import Blueprint
from flask import flash
from flask import redirect
from flask import render_template
from flask import request
from flask import url_for
from werkzeug.wrappers import Response
from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor,
)
from spiffworkflow_backend.services.process_instance_service import (
ProcessInstanceService,
)
from spiffworkflow_backend.services.process_model_service import ProcessModelService
from spiffworkflow_backend.services.spec_file_service import SpecFileService
from spiffworkflow_backend.services.user_service import UserService
admin_blueprint = Blueprint(
"admin", __name__, template_folder="templates", static_folder="static"
)
ALLOWED_BPMN_EXTENSIONS = {"bpmn", "dmn"}
@admin_blueprint.route("/process-groups", methods=["GET"])
def process_group_list() -> str:
"""Process_group_list."""
process_groups = ProcessModelService.get_process_groups()
return render_template("process_group_list.html", process_groups=process_groups)
@admin_blueprint.route("/process-groups/<process_group_id>", methods=["GET"])
def process_group_show(process_group_id: str) -> str:
"""Show_process_group."""
process_group = ProcessModelService.get_process_group(process_group_id)
return render_template("process_group_show.html", process_group=process_group)
@admin_blueprint.route("/process-models/<process_model_id>", methods=["GET"])
def process_model_show(process_model_id: str) -> Union[str, Response]:
"""Show_process_model."""
process_model = ProcessModelService.get_process_model(process_model_id)
files = SpecFileService.get_files(process_model, extension_filter="bpmn")
current_file_name = process_model.primary_file_name
if current_file_name is None:
flash("No primary_file_name", "error")
return redirect(url_for("admin.process_group_list"))
bpmn_xml = SpecFileService.get_data(process_model, current_file_name)
return render_template(
"process_model_show.html",
process_model=process_model,
bpmn_xml=bpmn_xml,
files=files,
current_file_name=current_file_name,
)
@admin_blueprint.route(
"/process-models/<process_model_id>/<file_name>", methods=["GET"]
)
def process_model_show_file(process_model_id: str, file_name: str) -> str:
"""Process_model_show_file."""
process_model = ProcessModelService.get_process_model(process_model_id)
bpmn_xml = SpecFileService.get_data(process_model, file_name)
files = SpecFileService.get_files(process_model, extension_filter="bpmn")
return render_template(
"process_model_show.html",
process_model=process_model,
bpmn_xml=bpmn_xml,
files=files,
current_file_name=file_name,
)
@admin_blueprint.route(
"/process-models/<process_model_id>/upload-file", methods=["POST"]
)
def process_model_upload_file(process_model_id: str) -> Response:
"""Process_model_upload_file."""
process_model = ProcessModelService.get_process_model(process_model_id)
if "file" not in request.files:
flash("No file part", "error")
request_file = request.files["file"]
# If the user does not select a file, the browser submits an
# empty file without a filename.
if request_file.filename == "" or request_file.filename is None:
flash("No selected file", "error")
else:
if request_file and _allowed_file(request_file.filename):
if request_file.filename is not None:
SpecFileService.add_file(
process_model, request_file.filename, request_file.stream.read()
)
ProcessModelService.save_process_model(process_model)
return redirect(
url_for("admin.process_model_show", process_model_id=process_model.id)
)
@admin_blueprint.route(
"/process_models/<process_model_id>/edit/<file_name>", methods=["GET"]
)
def process_model_edit(process_model_id: str, file_name: str) -> str:
"""Edit_bpmn."""
process_model = ProcessModelService.get_process_model(process_model_id)
bpmn_xml = SpecFileService.get_data(process_model, file_name)
return render_template(
"process_model_edit.html",
bpmn_xml=bpmn_xml.decode("utf-8"),
process_model=process_model,
file_name=file_name,
)
@admin_blueprint.route(
"/process-models/<process_model_id>/save/<file_name>", methods=["POST"]
)
def process_model_save(process_model_id: str, file_name: str) -> Union[str, Response]:
"""Process_model_save."""
process_model = ProcessModelService.get_process_model(process_model_id)
SpecFileService.update_file(process_model, file_name, request.get_data())
if process_model.primary_file_name is None:
flash("No primary_file_name", "error")
return redirect(url_for("admin.process_group_list"))
bpmn_xml = SpecFileService.get_data(process_model, process_model.primary_file_name)
return render_template(
"process_model_edit.html",
bpmn_xml=bpmn_xml.decode("utf-8"),
process_model=process_model,
file_name=file_name,
)
@admin_blueprint.route("/process-models/<process_model_id>/run", methods=["GET"])
def process_model_run(process_model_id: str) -> Union[str, Response]:
"""Process_model_run."""
user = UserService.create_user("Mr. Test", "internal", "Mr. Test")
process_instance = (
ProcessInstanceService.create_process_instance_from_process_model_identifier(
process_model_id, user
)
)
processor = ProcessInstanceProcessor(process_instance)
processor.do_engine_steps()
result = processor.get_data()
process_model = ProcessModelService.get_process_model(process_model_id)
files = SpecFileService.get_files(process_model, extension_filter="bpmn")
current_file_name = process_model.primary_file_name
if current_file_name is None:
flash("No primary_file_name", "error")
return redirect(url_for("admin.process_group_list"))
bpmn_xml = SpecFileService.get_data(process_model, current_file_name)
return render_template(
"process_model_show.html",
process_model=process_model,
bpmn_xml=bpmn_xml,
result=result,
files=files,
current_file_name=current_file_name,
)
# def _find_or_create_user(username: str = "test_user1") -> Any:
# """Find_or_create_user."""
# user = UserModel.query.filter_by(username=username).first()
# if user is None:
# user = UserModel(username=username)
# db.session.add(user)
# db.session.commit()
# return user
def _allowed_file(filename: str) -> bool:
"""_allowed_file."""
return (
"." in filename
and filename.rsplit(".", 1)[1].lower() in ALLOWED_BPMN_EXTENSIONS
)

View File

@ -1,26 +0,0 @@
import BpmnViewer from "bpmn-js";
var viewer = new BpmnViewer({
container: "#canvas",
});
viewer
.importXML(pizzaDiagram)
.then(function (result) {
const { warnings } = result;
console.log("success !", warnings);
viewer.get("canvas").zoom("fit-viewport");
})
.catch(function (err) {
const { warnings, message } = err;
console.log("something went wrong:", warnings, message);
});
export function sayHello() {
console.log("hello");
}
window.foo = "bar";

View File

@ -1,18 +0,0 @@
{
"name": "spiffworkflow-backend",
"version": "0.0.0",
"description": "Serve up Spiff Workflows to the World!",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"bpmn-js": "^9.1.0",
"bpmn-js-properties-panel": "^1.1.1"
},
"devDependencies": {
"webpack-cli": "^4.9.2"
}
}

View File

@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<head>
{% block head %}
<link
rel="stylesheet"
href="{{ url_for('admin.static', filename='style.css') }}"
/>
<title>{% block title %}{% endblock %}</title>
{% endblock %}
</head>
<body>
<h1>{{ self.title() }}</h1>
{% with messages = get_flashed_messages(with_categories=true) %} {% if
messages %}
<ul class="flashes">
{% for category, message in messages %}
<li class="{{ category }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %} {% endwith %} {% block content %}{% endblock %}
</body>
</html>

View File

@ -1,18 +0,0 @@
{% extends "layout.html" %} {% block title %}Process Groups{% endblock %} {%
block content %}
<table>
<tbody>
{# here we iterate over every item in our list#} {% for process_group in
process_groups %}
<tr>
<td>
<a
href="{{ url_for('admin.process_group_show', process_group_id=process_group.id) }}"
>{{ process_group.display_name }}</a
>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@ -1,25 +0,0 @@
{% extends "layout.html" %}
{% block title %}Process Group: {{ process_group.id }}{% endblock %}
{% block content %}
<button
type="button"
onclick="window.location.href='{{ url_for( 'admin.process_group_list') }}';"
>
Back
</button>
<table>
<tbody>
{# here we iterate over every item in our list#}
{% for process_model in process_group.process_models %}
<tr>
<td>
<a
href="{{ url_for('admin.process_model_show', process_model_id=process_model.id) }}"
>{{ process_model.display_name }}</a
>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@ -1,167 +0,0 @@
{% extends "layout.html" %} {% block title %}
Process Model Edit: {{ process_model.id }}
{% endblock %}
{% block head %}
<meta charset="UTF-8" />
<!-- example styles -->
<!-- required modeler styles -->
<link rel="stylesheet" href="https://unpkg.com/bpmn-js@9.1.0/dist/assets/bpmn-js.css" />
<link rel="stylesheet" href="https://unpkg.com/bpmn-js@9.1.0/dist/assets/diagram-js.css" />
<link rel="stylesheet" href="https://unpkg.com/bpmn-js@9.1.0/dist/assets/bpmn-font/css/bpmn.css" />
<link rel="stylesheet" href="https://unpkg.com/bpmn-js-properties-panel/dist/assets/properties-panel.css">
<link rel="stylesheet" href="https://unpkg.com/bpmn-js-properties-panel/dist/assets/element-templates.css">
<!-- modeler distro -->
<script src="https://unpkg.com/bpmn-js@9.1.0/dist/bpmn-modeler.development.js"></script>
<!-- needed for this example only -->
<script src="https://unpkg.com/jquery@3.3.1/dist/jquery.js"></script>
<!-- example styles -->
<style>
html, body, #canvas {
height: 100%;
padding: 0;
margin: 0;
}
.diagram-note {
background-color: rgba(66, 180, 21, 0.7);
color: White;
border-radius: 5px;
font-family: Arial;
font-size: 12px;
padding: 5px;
min-height: 16px;
width: 50px;
text-align: center;
}
.needs-discussion:not(.djs-connection) .djs-visual > :nth-child(1) {
stroke: rgba(66, 180, 21, 0.7) !important; /* color elements as red */
}
#save-button {
position: fixed;
bottom: 20px;
left: 20px;
}
</style>
{% endblock %}
{% block content %}
<div id="result">{{ result }}</div>
<button
type="button"
onclick="window.location.href='{{ url_for( 'admin.process_model_show_file', process_model_id=process_model.id, file_name=file_name ) }}';"
>
Back
</button>
<button type="button" onclick="exportDiagram()">Save</button>
<!-- <div class="modeler"> -->
<div id="canvas"></div>
<div id="properties"></div>
<!-- </div> -->
<meta id="bpmn_xml" data-name="{{bpmn_xml}}" />
<script>
// import BpmnModeler from '/admin/static/node_modules/bpmn-js/lib/Modeler.js';
// import {
// BpmnPropertiesPanelModule,
// BpmnPropertiesProviderModule,
// } from '/admin/static/node_modules/bpmn-js-properties-panel/dist/index.js';
//
// const bpmnModeler = new BpmnModeler({
// container: '#canvas',
// propertiesPanel: {
// parent: '#properties'
// },
// additionalModules: [
// BpmnPropertiesPanelModule,
// BpmnPropertiesProviderModule
// ]
// });
// modeler instance
var bpmnModeler = new BpmnJS({
container: "#canvas",
keyboard: {
bindTo: window,
},
});
/**
* Save diagram contents and print them to the console.
*/
async function exportDiagram() {
try {
var data = await bpmnModeler.saveXML({ format: true });
//POST request with body equal on data in JSON format
fetch("/admin/process-models/{{ process_model.id }}/save/{{ file_name }}", {
method: "POST",
headers: {
"Content-Type": "text/xml",
},
body: data.xml,
})
.then((response) => response.json())
//Then with the data from the response in JSON...
.then((data) => {
console.log("Success:", data);
})
//Then with the error genereted...
.catch((error) => {
console.error("Error:", error);
});
alert("Diagram exported. Check the developer tools!");
} catch (err) {
console.error("could not save BPMN 2.0 diagram", err);
}
}
/**
* Open diagram in our modeler instance.
*
* @param {String} bpmnXML diagram to display
*/
async function openDiagram(bpmnXML) {
// import diagram
try {
await bpmnModeler.importXML(bpmnXML);
// access modeler components
var canvas = bpmnModeler.get("canvas");
var overlays = bpmnModeler.get("overlays");
// zoom to fit full viewport
canvas.zoom("fit-viewport");
// attach an overlay to a node
overlays.add("SCAN_OK", "note", {
position: {
bottom: 0,
right: 0,
},
html: '<div class="diagram-note">Mixed up the labels?</div>',
});
// add marker
canvas.addMarker("SCAN_OK", "needs-discussion");
} catch (err) {
console.error("could not import BPMN 2.0 diagram", err);
}
}
// trying to use the python variable bpmn_xml directly causes the xml to have escape sequences
// and using the meta tag seems to help with that
var bpmn_xml = $("#bpmn_xml").data();
openDiagram(bpmn_xml.name);
// wire save button
$("#save-button").click(exportDiagram);
</script>
{% endblock %}

View File

@ -1,159 +0,0 @@
{% extends "layout.html" %} {% block title %}Process Model: {{ process_model.id
}}{% endblock %} {% block head %} {{ super() }}
<meta charset="UTF-8" />
<script src="{{ url_for('admin.static', filename='node_modules/bpmn-js/dist/bpmn-viewer.development.js') }}"></script>
<!-- viewer distro (without pan and zoom) -->
<!--
<script src="https://unpkg.com/bpmn-js@9.1.0/dist/bpmn-viewer.development.js"></script>
-->
<!-- required viewer styles -->
<link
rel="stylesheet"
href="https://unpkg.com/bpmn-js@9.1.0/dist/assets/bpmn-js.css"
/>
<!-- viewer distro (with pan and zoom) -->
<script src="https://unpkg.com/bpmn-js@9.1.0/dist/bpmn-navigated-viewer.development.js"></script>
<!-- needed for this example only -->
<script src="https://unpkg.com/jquery@3.3.1/dist/jquery.js"></script>
<!-- example styles -->
<style>
html,
body,
#canvas {
height: 90%;
padding: 0;
margin: 0;
}
.diagram-note {
background-color: rgba(66, 180, 21, 0.7);
color: White;
border-radius: 5px;
font-family: Arial;
font-size: 12px;
padding: 5px;
min-height: 16px;
width: 50px;
text-align: center;
}
.needs-discussion:not(.djs-connection) .djs-visual > :nth-child(1) {
stroke: rgba(66, 180, 21, 0.7) !important; /* color elements as red */
}
</style>
{% endblock %} {% block content %}
<div id="result">{{ result }}</div>
<button
type="button"
onclick="window.location.href='{{ url_for( 'admin.process_group_show', process_group_id=process_model.process_group_id ) }}';"
>
Back
</button>
<button
type="button"
onclick="window.location.href='{{ url_for( 'admin.process_model_run' , process_model_id=process_model.id ) }}';"
>
Run
</button>
<button
type="button"
onclick="window.location.href='{{ url_for( 'admin.process_model_edit' , process_model_id=process_model.id, file_name=current_file_name ) }}';"
>
Edit
</button>
{% if files %}
<h3>BPMN Files</h3>
<ul>
{% for file in files %}
<li>
<a
href="{{ url_for('admin.process_model_show_file', process_model_id=process_model.id, file_name=file.name) }}"
>{{ file.name }}</a
>
{% if file.name == current_file_name %} (current) {% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
<form
method="post"
action="/admin/process-models/{{process_model.id}}/upload-file"
enctype="multipart/form-data"
>
<input type="file" name="file" />
<input type="submit" value="Upload" />
</form>
<div id="canvas"></div>
<meta id="bpmn_xml" data-name="{{bpmn_xml}}" />
<script>
var diagramUrl =
"https://cdn.staticaly.com/gh/bpmn-io/bpmn-js-examples/dfceecba/starter/diagram.bpmn";
// viewer instance
var bpmnViewer = new BpmnJS({
container: "#canvas",
});
/**
* Open diagram in our viewer instance.
*
* @param {String} bpmnXML diagram to display
*/
async function openDiagram(bpmnXML) {
// import diagram
try {
await bpmnViewer.importXML(bpmnXML);
// access viewer components
var canvas = bpmnViewer.get("canvas");
var overlays = bpmnViewer.get("overlays");
// zoom to fit full viewport
canvas.zoom("fit-viewport");
// attach an overlay to a node
overlays.add("SCAN_OK", "note", {
position: {
bottom: 0,
right: 0,
},
html: '<div class="diagram-note">Mixed up the labels?</div>',
});
// add marker
canvas.addMarker("SCAN_OK", "needs-discussion");
} catch (err) {
console.error("could not import BPMN 2.0 diagram", err);
}
}
var bpmn_xml = $("#bpmn_xml").data();
openDiagram(bpmn_xml.name);
// load external diagram file via AJAX and open it
//$.get(diagramUrl, openDiagram, 'text');
</script>
<!--
Thanks for trying out our BPMN toolkit!
If you'd like to learn more about what our library,
continue with some more basic examples:
* https://github.com/bpmn-io/bpmn-js-examples/overlays
* https://github.com/bpmn-io/bpmn-js-examples/interaction
* https://github.com/bpmn-io/bpmn-js-examples/colors
* https://github.com/bpmn-io/bpmn-js-examples/commenting
To get a bit broader overview over how bpmn-js works,
follow our walkthrough:
* https://bpmn.io/toolkit/bpmn-js/walkthrough/
Related starters:
* https://raw.githubusercontent.com/bpmn-io/bpmn-js-examples/starter/modeler.html
-->
{% endblock %}